代码之家  ›  专栏  ›  技术社区  ›  aeh

使用脚本向xml中的每个标记添加递增值属性

  •  0
  • aeh  · 技术社区  · 16 年前

    我想为xml中的每个标记添加一个属性,该属性使用awk、sed、perl或plain shell cmd递增

    <tag1 key="123">
      <tag2 abc="xf d"/>
      <tag3 def="d2 32">
       </tag3>
    </tag1>
    

    我期待以下输出

    <tag1 key="123" order="1">
      <tag2 abc="xf d" order="2"/>
      <tag3 def="d2 32" order="3">
       </tag3>
    </tag1>
    

    如果可能的话,我不会考虑任何依赖关系(Twig、LibXML),纯字符串操作。

    3 回复  |  直到 16 年前
        1
  •  -1
  •   schot    16 年前

    通常应该使用适当的解析器来处理xml。但是在 awk :

    awk 'match($0, /<[^\/>]+/) { \
         $0 = substr($0, 1, RSTART+RLENGTH-1) " order=\"" ++i "\"" \
              substr($0, RSTART+RLENGTH) \
         }; 1'
    

    > 或 /> 在每一条线上。如果找到了,把绳子 order="i" 在它之后,同时递增 i . 单身汉 1 啊 的默认操作: { print $0 } .

    我更新了正则表达式以处理修改后的输入。当您在一行上有多个打开标签时,它就会失败,等等。

        2
  •  4
  •   brian d foy    16 年前

    我喜欢Perl的 XML::Twig 为了这种事。无论你做什么,你都必须调整它,这样你就可以访问所有你想影响的元素。要先处理家长,再处理孩子,您可能需要排队:

    use XML::Twig;
    
    my $xml = <<'XML';
    <tag1 key="123">
      <tag2 key="1234"/>
      <tag3 key="12345">
       </tag3>
    </tag1>
    XML
    
    my $twig = XML::Twig->new(
        pretty_print => 'indented',
        );
    $twig->parse( $xml );
    my @queue = ( $twig->root );
    
    my $n = 1;  
    while( my $elem = shift @queue ) {
        next unless $elem->tag =~ /\Atag[123]\z/;
        $elem->set_att( order => $n++ );
        push @queue, $elem->children( qr/\Atag/ );
        }
    
    $twig->print;
    

    此脚本的输出为:

    <tag1 key="123" order="1">
      <tag2 key="1234" order="2"/>
      <tag3 key="12345" order="3"></tag3>
    </tag1>
    
        3
  •  2
  •   Dave Cross    16 年前

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use XML::LibXML;
    
    my $counter = 1;
    
    my $xp = XML::LibXML->new->parse_file('test.xml');
    
    foreach($xp->findnodes('//*')) { # '//*' returns all nodes
      $_->setAttribute('order', $counter++);
    }
    
    print $xp->toString;