Perl XML:: Простой для анализа внутренних узлов
Я хочу разобрать файл XML, который у меня есть, и распечатать id
атрибут internal
элементы.
Это файл XML
<?xml version="1.0"?>
<!DOCTYPE test SYSTEM "http://www.kegg.jp/kegg/xml/KGML_v0.7.1_.dtd">
<test name="A" >
<node id="11" name="test1" >
<internal id="111" name="A111"/>
</node>
<node id="12" name="B">
<internal id="121" name="B121"/>
<internal id="122" name="B122"/>
</node>
</test>
и вот код, он терпит неудачу, когда один узел имеет два внутренних свойства
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
my $xml=new XML::Simple;
my $doc=$xml->XMLin("test.xml",KeyAttr => ['id']);
print Dumper($doc);
foreach my $node ( sort keys %{$doc->{node}} ) {
print $doc->{node}->{$node}->{internal}->{id}."\n";
}
Вот как выглядит самосвал
$VAR1 = {
'name' => 'test1',
'node' => {
'11' => {
'name' => 'A',
'internal' => {
'name' => 'A111',
'id' => '111'
}
},
'12' => {
'name' => 'B',
'internal' => {
'122' => {
'name' => 'B122'
},
'121' => {
'name' => 'B121'
}
}
}
}
};
2 ответа
Решение
Добавлять
ForceArray => [qw( node internal )]
Код:
my $doc = XMLin(\$xml,
ForceArray => [qw( node internal )],
KeyAttr => [qw( id )],
);
print(Dumper($doc));
my $nodes = $doc->{node};
for my $node_key ( sort { $a <=> $b } keys %$nodes ) {
my $node = $nodes->{$node_key};
my $internals = $node->{internal};
for my $internal_key ( sort { $a <=> $b } keys %$internals ) {
print("$internal_key\n");
# my $internal = $internals->{$internal_key};
# print("$internal->{name}\n");
}
}
Код:
#!/usr/bin/perl -w
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
my $xml=new XML::Simple;
my $doc=$xml->XMLin(&get_str(),ForceArray => ['internal'],KeyAttr => 'id');
print Dumper($doc);
sub get_str {
return qq#<?xml version="1.0"?>
<!DOCTYPE test SYSTEM "http://www.kegg.jp/kegg/xml/KGML_v0.7.1_.dtd">
<test name="A" >
<node id="11" name="test1" >
<internal id="111" name="A111"/>
</node>
<node id="12" name="B">
<internal id="121" name="B121"/>
<internal id="122" name="B122"/>
</node>
</test>#;
}
Выход:
$VAR1 = {
'name' => 'A',
'node' => {
'11' => {
'name' => 'test1',
'internal' => {
'111' => {
'name' => 'A111'
}
}
},
'12' => {
'name' => 'B',
'internal' => {
'122' => {
'name' => 'B122'
},
'121' => {
'name' => 'B121'
}
}
}
}
};
Примечание 1: Значением по умолчанию для "KeyAttr" является ["name", "key", "id"]. Если вы не хотите сворачивать на входе или разворачивать на выходе, вы должны установить эту опцию в пустой список, чтобы отключить эту функцию.
Примечание 2: Если вы хотите использовать эту опцию, вам также следует включить опцию ForceArray. Без ForceArray отдельный вложенный элемент будет свернут в скаляр, а не в массив, и, следовательно, не будет сложен (поскольку складываются только массивы).