Bootstrap FreeKB - Perl (Scripting) - XML::Simple looping through keys
Perl (Scripting) - XML::Simple looping through keys

Updated:   |  Perl (Scripting) articles

When looping through keys using XML::Simple, there are two main approaches.

  • Loop through keys as hash
  • Loop through keys as array

 

The structure of the XML file usually dictates whether you are going to loop as a hash or as an array. Let's say you need to get character names Bugs Bunny, Elmer Fudd, and Yosemite Sam from an XML file. If the elements that contain the data you need (<name> in this example) only appears once under it's parent tag (<character> in this example), then it usually makes sense to loop through the keys as hash.

XML for a hash loop

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

 

On the other hand, if the element that contains the data you need (<name> in this example) appears two or more times under its parent tag (<character> in this example), then it makes sent to loop through the keys as an array.

XML for an array loop

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

 


Loop through hash

Before looping through an XML file as a hash, it usually makes sense to view the structure of the XML file using Dumper.

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

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

print Dumper $xml;

 

In this example, Dumper will produce the following output.

$VAR1 = {
          'character' => {
                           'Bugs Bunny' => {},
                           'Elmer Fudd' => {},
                           'Yosemite Sam' => {}
                         }
         };

 

This will print Bugs Bunny, Elmer Fudd, and Yosemite Sam.

foreach my $key ( keys %{$xml->{character}} ) {
  print "$key \n";
}

 


Loop through array

Add ForceArray => 1 to parse the XML file as an array instead of a hash.

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

 

In this example, Dumper will print the following. The main takeaway here is that Bugs Bunny, Elmer Fudd, and Yosemite Sam are surrounded by [ ], which means these values are in an array.

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

 

This will print Bugs Bunny, Elmer Fudd, and Yosemite Sam to the console.

foreach my $key ( @{$xml->{character}} ) {
  print "$key \n";
}

 

 


3 layers

Let's consider the same XML file where the values are 3 "layers" deep.

<acme>
   <character>
     <name role="main">Bugs Bunny</name>
     <name role="support">Elmer Fudd</name>
     <name role="support">Yosemite Sam</name>
   </character>
</acme>

 

Dumper will produce the following. The big takeaway here is that there are two arrays, "character" and "name". 

$VAR1 = {
          'character' => [
                           {
                            '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 ( @{$xml->{character}} ) {
  print @{$_->{name}};
}

 


4 layers

Let's consider the same XML file where the values are 3 "layers" deep.

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

 

Dumper will show there are 3 arrays, "character", "role", and "name". In this situation, you first need to loop through the "character" array, then loop through the "role" array, and then you can print the values in the "name" array.

foreach my $character ( @{$xml->{character}} ) {
  foreach my $main ( @{$character->{main}} ) {
    print "@{$main->{name}}\n";
  }
}

 




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 4d5a46 in the box below so that we can be sure you are a human.