FreeKB - Looping through keys using XML::Simple in Perl
Looping through keys using XML::Simple in Perl

Home > Search


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 ( keys %{$xml->{character}} ) {
  print "$_\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 ( @{$xml->{character}} ) {
  print "$_\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";
  }
}

 



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




Comments