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

Hi gus!!

I'm using XML::Parser to parse the following XML:
<level name="Exanet admin" value="1"> <menu cliname="NFS" clicmd="nfs"> <menu cliname="Exports" clicmd="exports"> <command clicmd="add" state="nfsExportsAdd"/> <command clicmd="edit" state="nfsExportsEdit"/> <command clicmd="view" state="nfsExportsView"/> </menu> <menu cliname="Configure" clicmd="configure"> <command clicmd="set" state="nfsConfigSet"/> <command clicmd="view" state="nfsConfigView"/> </menu> </menu> </level>
This XML holds a menus tree and available commands in each menu. I parse the file using the Objects style like that:
my $parser = new XML::Parser(Style => 'Objects'); my $xml = $parser->parsefile('test.xml');
I want to be able to print this menu to the user (on Unix, not to browser necessarily), therefore I have to iterate recursively on $xml returned from parsefile, something like:
&printXML($xml); sub printXML { my $ref = shift; if (ref($ref) eq 'HASH') { print "Type: HASH\n"; while (($key, $val) = each(%{$ref})) { print "key: $key, val: $val\n"; &printXML($val); } } elsif (ref($ref) eq 'ARRAY') { # kids print "Type: ARRAY\n"; for (@{$ref}) { print "bla: $_\n"; &printXML($_); } } elsif ($xml->isa('HASH')) { # elements print "Type: hash object\n"; while (($key, $val) = each(%{$ref})) { print "key: $key, val: $val\n"; &printXML($val); } } else { # text print $ref, "\n"; } }
from what I read, there can be only hash refs, array refs and hash objects inside $xml.
the thing is that I get the following error while executing the above: "Can't call method "isa" unblessed reference at on test.pl line 103".

Can anyone shed a little light? and maybe note about the above code

Hotshot

Replies are listed 'Best First'.
Re: Parsing XML
by mirod (Canon) on Nov 26, 2002 at 12:37 UTC

    $xml->isa('HASH') will not work if $xml is not blessed, so if it is a hash ref or an array ref you won't be able to use this syntax. You have to use UNIVERSAL::isa(  $xml, 'HASH') instead, calling isa as a regular sub.

    Update: you might also be better off using a higher-level module like XML::Simple, which will put the data into a nice Perl data structure for you.

      Or XML::Twig :-)

      I wouldn't recommend investing too much time coding to XML::Parser's API. The two standard APIs used by a number of modules are DOM for tree based parsing and SAX for stream based parsing. Use these and you won't be tied to one parser.

      Alternatively if you want to write less code, use one of the higher-level Perl-specific APIs like XML::Simple or XML::Twig.