Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

A puzzle for parsing XML with XML::Simple!

by pysome (Scribe)
on Jan 25, 2008 at 07:09 UTC ( [id://664234]=perlquestion: print w/replies, xml ) Need Help??

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

Dear All, Now ,i came across a puzzled problem ,pls help me. my code
use XML::Simple; use Data::Dumper; my $xml = XML::Simple->new(); my $body = ' <all> <products> <item> <name>a</name> <price>1</price> <count>1</count> </item> <item> <name>b</name> <price>1</price> <count>1</count> </item> </products> </all>'; my $xhash = $xml->XMLin($body); print Dumper($xhash);
the result is :
$VAR1 = {
          'products' => {
              'item' => {
                  'a' => {
                        'count' => '1',
                        'price' => '1'
                   },
                   'b' => {
                        'count' => '1',
                        'price' => '1'
                   }
               }
           }
        };
I really don't want to this result. I want to get all "item" info into a Array ref. just like this:
$VAR1 = { 'products' => { 'item' =>[ { 'name' => 'a', 'count' => '1', 'price' => '1' }, { 'name' => 'b', 'count' => '1', 'price' => '1' } ] } };
how to carry out the task? Thanks in advance! BTW:i use the option "ForceArray => 1",the result also is not perfect . Pysome

Replies are listed 'Best First'.
Re: A puzzle for parsing XML with XML::Simple!
by bobf (Monsignor) on Jan 25, 2008 at 08:34 UTC

    ForceArray won't do it, but all is not lost. Try KeyAttr instead:

    my $xml = XML::Simple->new( KeyAttr => [ 'item' ] );
    $VAR1 = { 'products' => { 'item' => [ { 'count' => '1', 'name' => 'a', 'price' => '1' }, { 'count' => '1', 'name' => 'b', 'price' => '1' } ] } };

    Also, don't forget that even if the parser doesn't give you exactly what you want, there is always post-processing. :-)

    HTH

      ++ for your solution, bobf,
      but an offset for your assertion that "ForceArray won't do it"
      because olus' solution (below) using FA *ALSO* does what the OP asked (for the data given).

      Update: Careless monk has no excuse for the stricken section; replace with "olus' note -- also re 'KeyAttr' is also valuable." Duh! on me and thanks to both bobf and olus for catching this before it sat there any longer.

        I probably should have said I couldn't get ForceArray to do it in my tests, thereby leaving room for someone more clever than I to find a solution using that option.

        That said, olus' solution uses KeyAttr just as mine does, not ForceArray (olus++ for reading the docs). Am I missing something?

Re: A puzzle for parsing XML with XML::Simple!
by olus (Curate) on Jan 25, 2008 at 11:43 UTC
    The thing to be aware of in this case is to the following note on the module documentation.
    Note 1: The default value for 'KeyAttr' is ['name', 'key', 'id']. If y +ou do not want folding on input or unfolding on output you must setti +ng this option to an empty list to disable the feature.
    So, since you have an element named 'name', XML::Simple does that grouping trick.
    What you need to do is to set KeyAttr to an empty list
    my $xml = XML::Simple->new(KeyAttr=>[]);
Re: A puzzle for parsing XML with XML::Simple!
by ikegami (Patriarch) on Jan 25, 2008 at 07:51 UTC
    How about
    ForceArray => [qw( item )]

    If some form for ForceArray doesn't do the trick, you're out of luck.

      thank you.But it can't work:(

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://664234]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-04-25 11:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found