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

I have the following problem when using module 'XML::Simple'. I have an XML config file 'local.xml' that looks like this:
<WHICS> <WhicsService> <Parameters> <WHICS> <Value>123.456.7.89</Value> <Detail>Name of Unix system running WHICS</Detail> </WHICS> <ServersMax> <Value>15</Value> <Detail>Maximum number of servers running on WHICS</Detail +> </ServersMax> <Service Name="WR80B"> <Runable> <Value>yes</Value> <Detail>Run WR80B process if value is yes else does not + stat WR80B</Detail> </Runable> <PortOut> <Value>4100</Value> <Detail>Default port for Unix server connections</Detai +l> </PortOut> <command> <Value>cd /whics/ahm &amp;&amp; ./bin/wh_wweb80.sh </Va +lue> <Detail>Unix command required to run WR81B</Detail> </command> <ServersMin> <Value>7</Value> <Detail>Minimum number of servers running on WHICS</Det +ail> </ServersMin> </Service> </Parameters> </WhicsService> </WHICS>
I want to parse this XML file and extract some values. My script 'foo.pl' looks like this:
#!perl use XML::Simple; my $config = XMLin("local.xml"); print $config->{WhicsService}->{Parameters}->{WHICS}->{Value} . "\n"; +# prints '123.456.78.9' print $config->{WhicsService}->{Parameters}->{ServersMax}->{Value} . " +\n"; # prints '15' print $config->{WhicsService}->{Parameters}->{Service}->{WR80B}->{Runa +ble}->{Value} . "\n";
The first two 'print' lines work fine but the third 'print line does not print 'yes', instead nothing is printed. Any pointers would be greatly appreciated! Thanks, Adam

Replies are listed 'Best First'.
Re: Problem using module XML::Simple
by bobf (Monsignor) on Dec 05, 2005 at 05:27 UTC

    The element you're looking for isn't where you think it is. Use Data::Dumper (or a similar module) to help visualize the parsed data structure.

    Your script and XML::Simple is parsing your data into this structure (viewed using Data::Dumper):

    In other words, the value you want is in:
    $config->{WhicsService}{Parameters}{Service}{Runable}{Value}
    (note that you can eliminate the dereferencing arrows (->) between the hash elements, as documented in perlref).

    For more information about displaying complex data structures, see Re: How can I visualize my complex data structure?.

    Update: added a couple links - thanks planetscape

      This is classic example of why one should use warnings;. Had the Original Poster used warnings, rather than failing silently Perl would have complained when the OP's script tried to concatenate an undefined value with "\n". This would have been a very good indication that the datastructure returned by XMLin() wasn't what he was expecting.

      The moral; use the tools that Perl offers; use strict;, use warnings;, and in the case of deciphering the datastructures returned by XML::Simple, be sure to use Data::Dumper;. Data::Dumper is the cheap and easy way to inspect a datastructure.


      Dave

Re: Problem using module XML::Simple
by planetscape (Chancellor) on Dec 05, 2005 at 05:53 UTC
Re: Problem using module XML::Simple
by Zaxo (Archbishop) on Dec 05, 2005 at 05:44 UTC

    Adding,

    use Data::Dumper; print Dumper $config;
    to the end of your code reveals that the 'WR80B' key's value contains a hash ref whose only key is 'Runable'. You probably wanted,
    print $config->{WhicsService}{Parameters}{Service}{Runable}{Value} . " +\n";
    Actually, the 'WR80B' key doesn't exist at all until the print autovivifies it. Printing Dumper($config) before the other print statements shows the structure as XML::Simple constructs it.

    Does your top level tag need to be <WHICS>? That will stand on the way of more sophisticated parsing, having the same tag with a different use for data.

    The parent XML::Parser module gives a data structure which distinguishes between attributes and elements. It also places elements in an array, preserving their order. The simple version is probably good enough for what you're doing with configurations.

    After Compline,
    Zaxo

Re: Problem using module XML::Simple
by grantm (Parson) on Dec 05, 2005 at 18:06 UTC

    Since no one has directly answered your question ...

    The {Service}->{WR80B} bit suggests that you're expecting XML::Simple to use array folding to convert the array of <Service> elements into a hash keyed on the value of the 'Name' attributes. There are two problems with that:

    • The default value of XML::Simple's KeyAttr option includes 'name' in lower case which doesn't match 'Name' in your XML
    • There won't be an array of <Service> elements to fold into a hash because you haven't used the ForceArray option

    More details in this article.