Bootstrap FreeKB - Perl (Scripting) - XML::Simple ForceArray
Perl (Scripting) - XML::Simple ForceArray

Updated:   |  Perl (Scripting) articles

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}};
  }
}

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


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