Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

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 having an uproarious good time at the Monastery: (4)
As of 2018-06-22 04:26 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (121 votes). Check out past polls.