Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Parsing hashes with variable structure

by SomeNoob (Initiate)
on Nov 09, 2012 at 00:10 UTC ( #1003032=perlquestion: print w/replies, xml ) Need Help??
SomeNoob has asked for the wisdom of the Perl Monks concerning the following question:

Hello. This is my first question so my apologies in advance if I break any taboos. I did read the formatting tips and how to ask a question articles.

From a high level I am trying to write an XML parser. I'm using XML::Simple to get the XML into a hash and am then navigating that hash to pull out the data I need. In the hash that XML::Simple gives me, there is an array of hashes, and while looping through those I have a problem with the structure below:

'user' => { + 'firstname' => 'Joe', + 'lastname' => 'Shmoe', }, 'user' => 'Finance Department'

What I want to do is print out either the user's full name OR the department if there is no substructure under the user reference. However, I get a "Can't use string ("Vox Procurement Managers") as a HASH ref while "strict refs" in use at line 138." error when the code gets to the Finance Department bit. I've tried checking if(exists $xml->$usernumber->{"user"}->{"firstname"} before trying to print the full name but that still throws the error. Further googling and searching here has not helped. Basically I need a way to check if that reference in the hash points to a string ("Finance Department") or to more hashes down below. An if statement based on if( ref ($xml->$usernumber->{"user"}}) eq "HASH") always returned true and did not work either.

Replies are listed 'Best First'.
Re: Parsing hashes with variable structure
by jethro (Monsignor) on Nov 09, 2012 at 01:55 UTC

    Is your problem solved with the addition of {} around $usernumber or was that a copy mistake? If the problem still exists, read on:

    #!/usr/bin/env perl use warnings; use strict; use 5.10.0; my $h= { 'user' => { 'firstname' => 'Joe','lastname' => 'Shmoe'}}; my $h2= { 'user' => 'Finance Department'}; say "yes" if (ref($h->{'user'}) eq "HASH"); say "no" if (not ref($h2->{'user'}) eq "HASH"); #OUTPUT: yes no

    As you can see ref() works. So probably you feed the wrong data to ref(). You could use Data::Dumper to print out your $xml to see if it fits your expectation. And print out $xml->{$usernumber}->{"user"} just before your "if"-clause to check what it contains at that crucial moment. If ref() returns "HASH" then you can be really sure that it is a hash that is in there and not the string "Finance Department"

      Thanks so much! ref() did work; I must have made some kind of mistake when I tried it before. Again, thanks a ton for helping me out.

Re: Parsing hashes with variable structure
by frozenwithjoy (Priest) on Nov 09, 2012 at 00:27 UTC
    What do line 138 and relevant surrounding lines look like?

      Line 138 itself is the if(exists...) line and it's in the middle of a loop going through the array of references to different user hashes.

        Perhaps you meant the following? (I added {} around $usernumber)
        if( exists $xml->{$usernumber}->{"user"}->{"firstname"} ) {...}

        EDIT: You may also need to extend it as such: (but it is difficult to tell for sure w/o seeing more context)

        if( ref eq 'HASH' and exists $xml->{$usernumber}->{"user"}->{"firstnam +e"} ) {...}

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1003032]
Approved by Athanasius
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (8)
As of 2017-02-25 02:29 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (364 votes). Check out past polls.