Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

XML: Simple - nested XML data

by dmaranan (Acolyte)
on Dec 27, 2007 at 22:50 UTC ( [id://659262]=perlquestion: print w/replies, xml ) Need Help??

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

Given the following XML:
<SuperItem> <UserID>1234</UserID> <MajorItems> <MinorItem> <Item>Box</Item> </MinorItem> </MajorItems> <MajorItems> <MinorItem> <Item>Suitcase</Item> </MinorItem> </MajorItems> </SuperItem> <br>
Using XMLin how can I access the 2nd MinorItem (Suitcase). I've read through XML::Simple documentation, but I just don't understand the ForceArray options. Also, there are no attributes to the XML tags.
Thanks!

Replies are listed 'Best First'.
Re: XML: Simple - nested XML data
by CountZero (Bishop) on Dec 28, 2007 at 00:05 UTC
    I would use XML::XPath to access the nodes.

    use strict; use XML::XPath; my $xml = '<SuperItem> <UserID>1234</UserID> <MajorItems> <MinorItem> <Item>Box</Item> </MinorItem> </MajorItems> <MajorItems> <MinorItem> <Item>Suitcase</Item> </MinorItem> </MajorItems> </SuperItem> '; my $xp = XML::XPath->new( xml => $xml ); my $path = '/SuperItem/MajorItems[2]/MinorItem'; print $xp->findnodes_as_string($path);
    Returns:
    <MinorItem> <Item>Suitcase</Item> </MinorItem>

    Actually there are several XPath expressions which would give the same result, such as //MajorItems[2]/MinorItem or /SuperItem[UserID='1234']/MajorItems[2]/MinorItem. It will all depend on the actual content and structure of your XML.

    Update: Changed XML::Xpath to XML::XPath. thx PipTigger!

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      I think that should've been XML::XPath ... which I inherited from for my XML::Tidy module. You might try:

      #!/usr/bin/perl use strict; use warnings; use XML::XPath; my $xpob = XML::XPath->new('xml' => '<SuperItem> <UserID>1234</UserID> <MajorItems> <MinorItem> <Item>Box</Item> </MinorItem> </MajorItems> <MajorItems> <MinorItem> <Item>Suitcase</Item> </MinorItem> </MajorItems> </SuperItem>'); my @itmz = $xpob->findnodes('//Item'); # retn nodez in doc ordr print $itmz[1]->getChildNode(1)->getValue(); # XPath indices are 1-bas +ed # ... so the abov line takes the 2nd <Item /> elem (Bcuz Perl is 0-bas +ed) # && traverses down to its 1st child-node (this time no more nested el +emz # but just a TextNode as the only child) to print that value: "Suitcas +e"

      XPath is good shit. Just today, I used it in a COLLADA file with: '//node[@type="JOINT"]' to give me all the elements that describe animation bones for a Wii game I'm working on. Tim sure is Toady. ;) Have fun!

      -Pip@CPAN.Org
      PipForPresident.Org
Re: XML: Simple - nested XML data
by runrig (Abbot) on Dec 27, 2007 at 23:44 UTC
    Have you looked at Data::Dumper output? Does it help answer your question?
    use Data::Dumper qw(Dumper); my $data = XMLin($xml); print Dumper($data);
      Here is the output on data dumper:
      $VAR1 = {'UserID' => ['1234'], 'MajorItems' => [{'MinorItem' => [{'Item'=>['Box']}]}, {'MinorItem' => [{'Item' =>['Suitcase']}]}] };
      My attempts to access the single item have still failed. :(

        My attempts to access the single item have still failed. :(

        Fear not, my good monk, for perldsc, perlref, perlreftut are with you. Just drill down one level at a time.

        use strict; use warnings; use Data::Dumper; use XML::Simple; my $xml = q{ <SuperItem> <UserID>1234</UserID> <MajorItems> <MinorItem> <Item>Box</Item> </MinorItem> </MajorItems> <MajorItems> <MinorItem> <Item>Suitcase</Item> </MinorItem> </MajorItems> </SuperItem> }; my $struct = XMLin( $xml, ForceArray => 1 ); dumpit( $struct ); my $MajorItems_aref = $struct->{MajorItems}; dumpit( $MajorItems_aref ); my $SecondMinorItem_href = $struct->{MajorItems}[1]; # or $MajorItems_aref->[1] dumpit( $SecondMinorItem_href ); my $MinorItem_aref = $struct->{MajorItems}[1]{MinorItem}; # or $SecondMinorItem_href->{MinorItem} dumpit( $MinorItem_aref ); my $MinorItemFirst_href = $struct->{MajorItems}[1]{MinorItem}[0]; # or $MinorItem_aref->[0] dumpit( $MinorItemFirst_href ); my $Item_aref = $struct->{MajorItems}[1]{MinorItem}[0]{Item}; # or $MinorItemFirst_href->{Item} dumpit( $Item_aref ); my $luggage = $struct->{MajorItems}[1]{MinorItem}[0]{Item}[0]; # or $Item_aref->[0] dumpit( $luggage ); sub dumpit { print Dumper( $_[0] ); }

Re: XML: Simple - nested XML data
by gube (Parson) on Dec 28, 2007 at 05:37 UTC
    Hi,

    Execute the below code, you will get the 2nd minor item item value. See if you see the $output reference you can see the entire data structure output for the corresponding xml. From the data structure you can get whatever it necessary. Basically, ForceArray will each and every tag in array format based on the hirearchy. If you create this xml in xml file and if we see the '+' symbol hirearchy in the same format it will parse as a array and it will display.

    #!/usr/local/bin/perl use strict; use warnings; use XML::Simple; my $xml = qq{<SuperItem> <UserID>1234</UserID> <MajorItems> <MinorItem> <Item>Box</Item> </MinorItem> </MajorItems> <MajorItems> <MinorItem> <Item>Suitcase</Item> </MinorItem> </MajorItems> </SuperItem>}; use XML::Simple qw/:strict/; use Data::Dumper; my $xml_simple = XML::Simple->new(KeyAttr => 1, KeepRoot => 1, ForceAr +ray => 1); my $output = $xml_simple->XMLin($xml); print "\nEntire xml..", Dumper($output); print "\n2nd Minor item..", $output->{'SuperItem'}[0]{'MajorItems'}[1] +{'MinorItem'}[0]{'Item'}[0];

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-24 22:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found