
Let's say you have an XML file that has multiple keys that have an identical name, and your objective is to parse out the character names (Bugs Bunny, Elmer Fudd, Yosemite Sam).
<acme>
<main>
<character name="Bugs Bunny"></character>
</main>
<support>
<character name="Elmer Fudd"></character>
<character name="Yosemite Sam"></character>
</support>
</acme>
Let's first consider XML::Simple's default behavior.
#!/usr/bin/perl
use strict;
use warnings;
use XML::Simple;
my $xml = XMLin("cartoon.xml");
print Dumper $xml;
Notice that only Bugs Bunny has the 'name' key. Elmer Fudd and Yosemite Sam have {}. In this condition, it is going to be very difficult to create a simple clean script to parse out Bugs Bunny, Elmer Fudd, Yosemite Sam. Let's apply two controls to clean up the data.
$VAR1 = {
'support' => {
'character' => {
'Elmer Fudd' => {},
'Yosemite Sam' => {}
}
},
'main' => {
'character' => {
'name' => 'Bugs Bunny'
}
}
};
Adding KeyAttr => "character" will set "character" as the key, and ForceArray => 1 will store the data into arrays.
my $xml = XMLin("cartoon.xml", KeyAttr => "character", ForceArray => 1);
Now the data is in a much better condition, where all three characters have 'name'.
$VAR1 = {
'support' => [
{
'character' => [
{
'name' => 'Elmer Fudd'
},
{
'name' => 'Yosemite Sam'
}
]
}
],
'main' => [
{
'character' => [
{
'name' => 'Bugs Bunny'
}
]
}
]
};
These for each loops will now print the character names.
foreach ( @{$xml->{main}} ) {
foreach ( @{$_->{character}} ) {
print "$_->{name}\n";
}
}
foreach ( @{$xml->{support}} ) {
foreach ( @{$_->{character}} ) {
print "$_->{name}\n";
}
}
Did you find this article helpful?
If so, consider buying me a coffee over at