in reply to Re: Is it possible to parse an XML file recursively using XML::Twig?
in thread Is it possible to parse an XML file recursively using XML::Twig?

I had trouble with your second solution that involved " the '_all_' handler, and test each node for having children". When I ran it, as written, I got output like:

(ArrayOfBooks) Book: (ArrayOfBooks) Book: (Book) Released: (ArrayOfBooks) Book: (ArrayOfBooks) Book: (ArrayOfBooks) Book: Can't call method "tag" on an undefined value at monk_twig_xml_leaf2.p +l line 11. at monk_twig_xml_leaf2.pl line 19. at monk_twig_xml_leaf2.pl line 19.

I tried commenting out the "purge" call and got empty output with no errors, seemingly because $element->has_children was returning true for "#PCDATA" text nodes. I am new to XML:Twig, but not so new to XML, and am starting to appreciate XML::Twig's potential for optimization. I did come up with some working code as well but would first be interested in what I might be doing wrong that Preceptor's example wouldn't run.

Ron

Replies are listed 'Best First'.
Re^3: Is it possible to parse an XML file recursively using XML::Twig?
by Preceptor (Deacon) on Oct 24, 2015 at 23:23 UTC

    Calling tag on undefined value is probably the parent call. Adding a "defined" test there will probably do the trick. But I will suggest that the strength of the module is in using xpath so you rarely need to do a traverse in the first place. ≤/P>

      The following more cautious code seemed to work for me and should purge memory regularly. I worry that calling purge on every element which might purge something you still need around.

      use strict; use warnings; use XML::Twig; $|++; my $twig = XML::Twig->new( twig_handlers => { # as noted in the documentation for end_tag_handlers ... # "twig_handlers are called when an element is completely pars +ed" # so should be safe to purge here 'Book' => sub { my ($twig, $el) = @_; # print "purging ...\n"; $twig->purge; }, 'Book//*' => sub { # see http://search.cpan.org/~mirod/XML-Twig-3.49/Twig.pm# +cond # for #ELT which is an element print $_->tag, ': ', $_->text, $/ unless ($_->has_children('#ELT')); } } ); $twig->parsefile('books.xml');
      Ron
        This is exactly what I was looking for! Thank you :) I now just need to figure how to have the full nested path for each child. Thank you once again :)