Добавление атрибута инкрементного значения к каждому тегу в xml с использованием скрипта - PullRequest
0 голосов
/ 31 августа 2010

Я хочу добавить атрибут к каждому тегу в моем 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 ]

4 голосов
/ 31 августа 2010

Мне нравятся 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>
2 голосов
/ 31 августа 2010

Это довольно просто с XML :: LibXML и каплей XPath.

#!/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;
0 голосов
/ 31 августа 2010

Обычно вы должны использовать правильный парсер для обработки xml. Но в awk:

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

Я ищу открывающий тег (без части > или />) на каждой строке. Если найдено, поместите строку order="i" после нее, увеличивая i. Один 1 в последней строке просто всегда выполняет действие awk по умолчанию: { print $0 }.

Я обновил регулярное выражение для работы с вашим исправленным вводом. Сбой происходит, как только у вас есть несколько открывающих тегов в одной строке и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...