FreeKB - XML::Simple in Perl - ForceArray
XML::Simple in Perl - ForceArray

Home > Search


two level XML

Consider the following simple XML that has two levels.

<acme>
  <name>Bugs Bunny</name>
</acme>

 

Data::Dumper can be used to see how XML::Simple is going to parse the XML file.

use XML::Simple;
use Data::Dumper;

my $xml= XMLin("cartoon.xml");
print Dumper $xml;

 

Which will produce the following. Notice Bugs Bunny is inside of { } characters. Data inside of { } is interepreted as a hash.

$VAR1 = {
          'name' => {
                'Bugs Bunny',
               }
        };

 

The following would work as expected, and print Bugs Bunny.

use XML::Simple;
my $xml= XMLin("cartoon.xml");
print $xml->{'name'};

 

Consider the following XML.

<acme>
  <name>Bugs Bunny</name>
  <name>Elmer Fudd</name>
  <name>Yosemite Sam</name>
</acme>

 

Now, Bugs Bunny, Elmer Fudd, and Yosemite Sam are inside of [ ] characters. Data inside of [ ] is interpreted as an array.

$VAR1 = {
          'name' => [
                'Bugs Bunny',
                'Elmer Fudd',
                'Yosemite Sam'
               ]

        };

 

Attempting to print each name like this . . .

use XML::Simple;
my $xml= XMLin("cartoon.xml");
print $xml->{'name'};

 

. . . would produce the following, because the 'name' values are inside of the [ ] characters, thus they are array items.

ARRAY(Ox12bf350)


You can print a particular cartoon character by specifying the array value (0 prints Bugs Bunny, 1 print Elmer Fudd, 2 prints Yosemite Sam). 

print $xml->{'name'}->[0];
print $xml->{'name'}->[1];
print $xml->{'name'}->[2];

 

Or, you could print all of the values in the array. This will print Bugs Bunny Elmer Fudd Yosemite Sam. However, this will not work if there is only a single cartoon character.

print @{$xml->{'name'}};

 

The solution to this challenge is to use the ForceArray => 1 option.

$cartoon = XMLin("cartoon.xml", ForceArray => 1 );

 

Once the ForceArray => 1 option is used, you can then use the following to print all of the values of the array. This will work when there is only a single item in the array, or when there are two or more items in the array.

print @{$xml->{'name'}};

 

One caveot is that the following markup will fail to print a cartoon character once the ForceArray options is set.

print $cartoon->{'name'};

 

Instead, you would have to append the array value, like this.

print $cartoon->{'name'}->[0];

 


hash and array mixtures

Let's consider this XML.

<acme>
  <characters>
    <name>Bugs Bunny</name>
    <name>Elmer Fudd</name>
    <name>Yosemite Sam</name>
  </characters>
</acme>

 

Dumper will produce the following. Notice 'characters' is inside of { } (hash data). Bugs Bunny, Elmer Fudd, and Yosemite Sam are inside of [ ] (array data).

$VAR1 = {
          'characters' => 
                          {
                            'name' => [
                                      'Bugs Bunny',
                                      'Elmer Fudd',
                                      'Yosemite Sam'
                                      ]
                          }
         };

 

In this situation, you would loop through the first array (character) and then print the second array (name).

foreach my $key (keys %{$xml}) {
  foreach my $character ( @{$xml->{$key}} ) {
    print @{$character->{name}};
  }
}

 



Add a Comment




We will never share your name or email with anyone. Enter your email if you would like to be notified when we respond to your comment.




Please enter 07ee0 in the box below so that we can be sure you are a human.




Comments