pez252 has asked for the wisdom of the Perl Monks concerning the following question:

Resolved!: see comments for solution and link to completed project(w/code)

I am writing a little script to pull data from a website that provides an API for accessing it. I post to the url with my API key and it returns some xml with the data I requested.

An example of the XML is here:
<?xml version="1.0" encoding="utf-8"?> <get_devices_response> <devices list="true"> <device> <name>12345678</name> <id>1234</id> </device> <device> <name>87654321</name> <id>8765</id> </device> </devices> </get_devices_response>


I pass this to XML::Simple with KeyAttr=>[] and ForceArray=>"device". The data structure returned (as shown by Data::Dumper) is:
$VAR1 = { 'devices' => { 'device' => [ { 'name' => '12345678', 'id' => '1234' }, { 'name' => '87654321', 'id' => '8765' } ], 'list' => 'true' } };


The problem I am having is getting the array of hashes under the key "device". I tried the following:
my $hash_ref = XMLin($XML, KeyAttr=>[] , ForceArray=>["device"]); print "The array\n"; print Dumper($hash_ref->{devices}->{device}); print "The first element\n"; print Dumper($hash_ref->{devices}->{device}[0]); print "The first element another way\n"; my @array=$hash_ref->{devices}->{device}; print Dumper($array[0]);

I expect this to return the entire array for the first print of Dumper() and the first element in the array for the second and third call of Dumper(). The following is the output:
The array $VAR1 = [ { 'name' => '12345678', 'id' => '1234' }, { 'name' => '87654321', 'id' => '8765' } ]; The first element $VAR1 = { 'name' => '12345678', 'id' => '1234' }; The first element another way $VAR1 = [ { 'name' => '12345678', 'id' => '1234' }, { 'name' => '87654321', 'id' => '8765' } ];


I have tried a number of ways to get a simple array of hashes that I can return from this subroutine, but all of them have either been wrong in some way shape or form. As a solution to this I would accept changes to how I call XML::Simple, using an other XML parser all together, and more, as long as I am able to see how many devices are returned, and the name/id for each one. But... I still would like to know where I am going wrong with the whole nested hashes and arrays (is it something to do with hashrefs vs hashes or arrayrefs vs arrays?). Any help would be greatly appreciated.

-Thanks

Replies are listed 'Best First'.
Re: Pull an array from a hash... or somthing
by olus (Curate) on Feb 22, 2008 at 19:02 UTC

    In your third attempt you are assigning the reference of the device array and not the array itself. Try:

    my @array=@{ $hash_ref->{devices}->{device} };
      I thought it had something to do with references vs arrays them selves. I made the changes you suggested and it works great. It is now returning an array as I had hoped and I can do my foreach $device (@devices) to get the name and id of each.

      Thanks a lot.
Re: Pull an array from a hash... or somthing
by kyle (Abbot) on Feb 22, 2008 at 19:02 UTC

    You seem to be confusing arrays and array references. A reference is actually a scalar that holds an address of something. To get the thing that it addresses, you have to dereference it somehow.

    In the data structure you have, this is a reference:

    $hash_ref->{devices}->{device}

    To get the array, wrap it in @{} like so:

    my @array = @{ $hash_ref->{devices}->{device} }

    Have a look at perlreftut, and maybe References quick reference,

      You're right on the money. Being new to perl I caught on quickly that there was a difference between a reference to an array and the array its self, but I have yet to figure out how each is used in all the situations. That page spells it out nicely; I'll be bookmarking that post...

      Thanks!
Re: Pull an array from a hash... or somthing
by pez252 (Novice) on Feb 22, 2008 at 22:23 UTC
    I would like to thank you both again for helping with this simple problem (that was making me bang my head on my keyboard). The end result is complete and working. The script allows you to query for information from blackberrytracker.com (the site allows you to log the GPS location of your blackberry in real time).

    The wiki page about it is here(including download links): http://wiki.tech9computers.com/index.php/Perl
    And the (free) service in question is here: http://www.blackberrytracker.com/