Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

How to get content of an XML::easytree output

by Tworec (Initiate)
on Mar 07, 2013 at 22:55 UTC ( #1022313=perlquestion: print w/ replies, xml ) Need Help??
Tworec has asked for the wisdom of the Perl Monks concerning the following question:

Hello folks!

Do you know XML::easytree? It's really good tool, but unfortunately I am a perl newbie and I can't get the content of the $tree out for my other purposes. I am really depressed, for last 4 days I couldn't come up with my own idea and the only example of what I want to do next I found is some kind of broken or what.

See:
#!/usr/bin/perl -w #use strict; use XML::Parser; use XML::Parser::EasyTree; use Data::Dumper; my $p=new XML::Parser(Style=>'EasyTree'); my $tree=$p->parsefile("test.xml"); #my $element; print_easy_tree($tree); sub print_easy_tree { my $node = shift; { if ($element->{type} eq 'e') { print "<$element->{name}>"; print_easy_tree($element->{content}); print "</$element->{name}>"; } elsif ($element->{type} eq 't') { print $element->{content}; } else { print "[IGNORED $element->{type}]"; } } }

When I try to run this code, I get error that $element is not initialized. I tried to repair it, but I don't know where and what. Please help poor stupid student monk and end his torture.

Comment on How to get content of an XML::easytree output
Download Code
Re: How to get content of an XML::easytree output
by Anonymous Monk on Mar 07, 2013 at 23:42 UTC
    Can't be done, no sample input
Re: How to get content of an XML::easytree output
by kcott (Abbot) on Mar 07, 2013 at 23:49 UTC

    G'day Tworec,

    Welcome to the monastery.

    Firstly, I see you've commented out "use strict;" - uncomment this and also add "use warnings;". Removing the output of warnings does not remove the problem they're telling you about!

    You've commented out the declaration "my $element;". You assign nothing to $element. You then use $element as if it's a hashref - this is why you're getting the error message you report.

    Your print_easy_tree() subroutine assigns its argument to $node; you then make no further reference to $node! Each instance of $element in this function should probably be $node.

    I believe that should fix up your immediate problems. Here's some tips that you may find generally useful (i.e. not just for this code); the first two won't necessarily change how your code runs, but they should make it easier to read and understand:

    • Avoid indirect object syntax when instantiating: use Class->new(args) instead of new Class(args)
    • Avoid embedding complex dereferencing within interpolated strings, e.g. instead of print "<$element->{name}>";, use print '<', $element->{name}, '>';
    • The print function does not output newlines: you'll usually want print $output_line, "\n";. Alternatively, use the say function.

    -- Ken

      "e.g. instead of print "<$element->{name}>";, use print '<', $element->{name}, '>';

      Personally, I'd prefer:

      printf '<%s>', $element->{name};

      Update: just for the heck of it, this ain't too bad either:

      print "<$_>" for $element->{name};

      Using postfix for to temporarily alias $_ is an idiom I don't see used very much, but is quite cute, and in this case has no speed penalty (quite the opposite in fact)...

      use strict; use Benchmark ':all'; open $::dummy, ">", \$::data; cmpthese(100_000, { print_for => q[ $::data = ''; print {$::dummy} "<$_>" for "a" ], printf => q[ $::data = ''; printf {$::dummy} "<%s>", "a" ], }); __END__ Rate printf print_for printf 7663/s -- -79% print_for 36765/s 380% --

      (PS: kcott's follow-up was posted before this update, so please don't read it as necessarily endorsing the for postfix technique.)

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

        That, too, is good; it isolates the $element->{name} (++).

        Tworec states "I am a perl newbie" and "<$element->{name}>" didn't seem to scream clarity; in particular, the <$element-> bit.

        -- Ken

      First of all, thanks for your reply. I changed all variables $element to $node and errors I reported are gone. But unfortunately a new one came. Not a HASH reference at line: if ($node->{type} eq 'e'). I think it's because of the $tree variable is ARRAY, but there is the main problem. My brain cannot really understand how to go threw an array of hashes and print it's elements. Should I write something like
      if(ref($node) eq HASH) do the code I have elsif(ref($node) eq ARRAY) $node = shift;
      ?

        Something like the following (untested) skeleton code:

        sub print_easy_tree { my $node_array_ref = shift; for my $node (@$node_array_ref) { if ($node->{type} eq 'e') { ... } elsif ($node->{type} eq 't') { ... } else { ... } } }

        -- Ken

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (13)
As of 2015-07-07 12:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (88 votes), past polls