in reply to [SOLVED] Moving elements with XML::Twig: Document root closing tag is duplicated on output
'/shipment/box' => sub { _move(@_); 1; }
Even the SYSNOPSIS for the XML::Twig reports the example on how to call a subroutine to process the part intercepted by th handler:
list => \&my_list_process,
The, perfectly correct and valid, style to call a sub with &subname is described in perlsub where is stated &NAME; # Makes current @_ visible to called subroutine. If someone tell you is Perl4 rubbish.. let me know.. ;)
So changing your
# '/shipment/box' => sub { _move(@_); 1; } #wrong # to '/shipment/box' => \&_move,
makes everything much clearer and Twiggy.
For the rest I can say that, also you have an unneeded 1; as last thing in your sub. Seems more logical to have an exit condition if no slip are found (..ooops):
sub _move { unless ($_[1]->descendants('slip')){ $_[0]->purge(); return; } foreach my $descendant ...
This way the program runs as we expected:
#!/usr/bin/perl # use 5.020; unneeded aside from the say use strict; use warnings; use XML::Twig; ## ## This works as expected ## my $working_xml = XML::Twig->new( twig_handlers => { #'/shipment/box' => sub { _move(@_); 1; }, #why? and why 1; a +t the end? '/shipment/box' => \&_move, }, pretty_print => 'indented', )->safe_parse( <<"XML" <?xml version="1.0" encoding="UTF-8"?> <shipment> <box> <packing> <slip>potato</slip> <slip>pear</slip> <slip>peach</slip> </packing> </box> <box> <packing> <slip>apple</slip> </packing> </box> </shipment> XML ); print "\n\n---------------------\n\n"; ## ## This ALSO WORKS FINE NOW!! ## my $broken_xml = XML::Twig->new( twig_handlers => { '/shipment/box' => \&_move, }, pretty_print => 'indented', )->safe_parse( <<"XML" <?xml version="1.0" encoding="UTF-8"?> <shipment> <box> <packing> <slip>potato</slip> <slip>pear</slip> <slip>peach</slip> </packing> </box> <box> <packing> <note>nothing here!</note> </packing> </box> </shipment> XML ); # ---------- sub _move { unless ($_[1]->descendants('slip')){ $_[0]->purge(); return; } foreach my $descendant ( $_[1]->descendants('slip') ) { $descendant->set_att('_TYPE' => 'produce'); $descendant->move('before', $_[1]); } $_[1]->delete; $_[0]->flush(); #1; # why? } ## OUTPUT <?xml version="1.0" encoding="UTF-8"?> <shipment> <slip _TYPE="produce">potato</slip> <slip _TYPE="produce">pear</slip> <slip _TYPE="produce">peach</slip> <slip _TYPE="produce">apple</slip> </shipment> --------------------- <?xml version="1.0" encoding="UTF-8"?> <shipment> <slip _TYPE="produce">potato</slip> <slip _TYPE="produce">pear</slip> <slip _TYPE="produce">peach</slip> </shipment>
L*
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Moving elements with XML::Twig: Document root closing tag is duplicated on output -- solution
by Tanktalus (Canon) on Feb 21, 2016 at 03:54 UTC | |
by Discipulus (Canon) on Feb 21, 2016 at 18:29 UTC | |
|
Re^2: Moving elements with XML::Twig: Document root closing tag is duplicated on output -- solution
by ateague (Monk) on Feb 22, 2016 at 19:59 UTC | |
by Discipulus (Canon) on Feb 23, 2016 at 08:35 UTC |