I am trying to parse XML using XML::LibXML module. The XML data structure has node called <row>
which encloses two child nodes <key>
and <value>
. I want to parse each of these <row>
and build a hash data structure. I could come up with below code to achieve it but I feel there would be a better way to do it.
use strict;
use warnings;
use Data::Dumper;
use XML::LibXML;
my $XML=<<EOF;
<config>
<row>
<key>
<A1>alpha</A1>
<A2>beta</A2>
<A3>cat</A3>
<A4>delta</A4>
</key>
<value>
<B1>eclipse</B1>
<B2>pico</B2>
<B3>penta</B3>
<B4>zeta</B4>
</value>
</row>
<row>
<key>
<A1>tom</A1>
<A2>harry</A2>
<A3>bob</A3>
<A4>ben</A4>
</key>
<value>
<B1>TAP</B1>
<B2>MAN</B2>
<B3>WORK</B3>
<B4>MAINTAIN</B4>
</value>
</row>
</config>
EOF
my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($XML);
my %hash;
my $i = 1;
foreach my $node ($doc->findnodes('/config/row/key')) {
foreach my $tag ('A1', 'A2','A3','A4') {
$hash{'KEY' . $i}{$tag} = $node->findvalue( $tag );
}
$i++;
}
$i = 1;
foreach my $node ($doc->findnodes('/config/row/value')) {
foreach my $tag ('B1', 'B2','B3','B4') {
$hash{'KEY' . $i}{$tag} = $node->findvalue( $tag );
}
$i++;
}
print Dumper \%hash;
Output
$VAR1 = {
'KEY2' => {
'A3' => 'bob',
'B3' => 'WORK',
'B1' => 'TAP',
'A1' => 'tom',
'B4' => 'MAINTAIN',
'B2' => 'MAN',
'A2' => 'harry',
'A4' => 'ben'
},
'KEY1' => {
'A3' => 'cat',
'B3' => 'penta',
'B1' => 'eclipse',
'A1' => 'alpha',
'B4' => 'zeta',
'B2' => 'pico',
'A2' => 'beta',
'A4' => 'delta'
}
};
Actually, instead of creating imaginary keys ( KEY1 , KEY2 .. ) , I would like to have <A1>
node's value to be considered as key for each section. Can someone please help me out here.
Desired output:
'tom' => {
'A3' => 'bob',
'B3' => 'WORK',
'B1' => 'TAP',
'B4' => 'MAINTAIN',
'B2' => 'MAN',
'A2' => 'harry',
'A4' => 'ben'
},
'alpha' => {
'A3' => 'cat',
'B3' => 'penta',
'B1' => 'eclipse',
'B4' => 'zeta',
'B2' => 'pico',
'A2' => 'beta',
'A4' => 'delta'
}