Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: XML::Simple: list all element attributes

by frozenwithjoy (Priest)
on Apr 08, 2015 at 06:03 UTC ( #1122772=note: print w/replies, xml ) Need Help??


in reply to XML::Simple: list all element attributes

When I add this:

use Data::Printer; p $data;

I get this out:

\ { node [ [0] { name "1st node", text "Text of 1st node" }, [1] { name "2nd node", text "Text of 2nd node" }, [2] { name "3rd node", text "Text of 3rd node" } ] }

There is no key called 'App', so your @{$data->{App}{node}} is an empty list.

If I change your for loop to this:

foreach my $node (@{$data->{node}}) { print $node->{name}.": ".$node->{text}."\n"; }

I get what you were expecting:

1st node: Text of 1st node 2nd node: Text of 2nd node 3rd node: Text of 3rd node

If you want to keep the root key, you can use the following and keep your original loop.

my $xml = XML::Simple->new( KeyAttr => 1, ForceArray => 0, KeepRoot => + 1 );

Replies are listed 'Best First'.
Re^2: XML::Simple: list all element attributes
by element22 (Initiate) on Apr 08, 2015 at 06:32 UTC

    Thanks, it works now. A quick follow-up question. I've just noticed that a few "nodes" have child "nodes" with similar attributes:

    <?xml version="1.0" encoding="Windows-1252"?> <App> <node name="1st node" text="Text of 1st node" /> <node name="2nd node" text="Text of 2nd node"> <node name="subnode A" text="Text of subnode A" /> <node name="subnode B" text="Text of subnode B" /> </node> <node name="3rd node" text="Text of 3rd node" /> ... </App>

    I'd like to print this out as follows:

    1st node: Text of 1st node 2nd node: Text of 2nd node subnode A: Text of subnode A subnode B: Text of subnode B 3rd node: Text of 3rd node

    Without getting into any scary recursion, how would I modify the loop to print out the subnodes, too?

    foreach my $node (@{$data->{node}}) { print $node->{name}.": ".$node->{text}."\n"; if ( ... ) { # detect the existence of a subnode here somehow foreach my $subnode (@{$data->{node}{subnode}}) { print "\t".$subnode->{name}.": ".$subnode->{text}."\n"; } } }

      What you are looking for is: if ( $node->{node} )

      However, is a little recursion OK?

      print_nodes($data); sub print_nodes { my $data = shift; foreach my $node ( @{ $data->{node} } ) { print $node->{name} . ": " . $node->{text} . "\n"; if ( $node->{node} ) { print_nodes($node); } } }

      This should work regardless of how deep the nodes go; however, it doesn't indent:

      1st node: Text of 1st node 2nd node: Text of 2nd node subnode A: Text of subnode A subnode B: Text of subnode B 3rd node: Text of 3rd node

      EDITED TO ADD INDENTATION:

      print_nodes( $data, 0 ); sub print_nodes { my ( $data, $depth ) = @_; my $tab_width = 4; foreach my $node ( @{ $data->{node} } ) { my $indent = " " x $depth x $tab_width; print $indent . $node->{name} . ": " . $node->{text} . "\n"; if ( $node->{node} ) { print_nodes( $node, $depth + 1 ); } } }
      1st node: Text of 1st node 2nd node: Text of 2nd node subnode A: Text of subnode A subnode B: Text of subnode B 3rd node: Text of 3rd node
        Everything's working now. Thank you very much for your help, especially adding the indents in recursion.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1122772]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2020-09-25 10:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I donít succeed, I Ö










    Results (137 votes). Check out past polls.

    Notices?