in reply to [SOLVED] Moving elements with XML::Twig: Document root closing tag is duplicated on output

Normally, I'd expect flushing to be required outside of the twig handlers. What it kind of looks like is happening, besides being a probable bug in XML::Twig, is that you're flushing even when you're not changing anything. For example, updating _move to be:

sub _move { my $did_something = 0; foreach my $descendant ( $_[1]->descendants('slip') ) { $did_something++; $descendant->set_att('_TYPE' => 'produce'); # Move the <slip> out of the <box> section # # This appears to be the problem, even though # this should never be reached in the second # document (no <slip> descendants) $descendant->move('before', $_[1]); } $_[1]->delete; $_[0]->flush() if $did_something; 1; }
seems to resolve the problem. Also, adding $broken_xml->flush; to after the call to safe_parse does not bring back the problem. And I think that extra flush is something XML::Twig documents as being required in some circumstances anyway, IIRC.

Replies are listed 'Best First'.
Re^2: Moving elements with XML::Twig: Document root closing tag is duplicated on output
by ateague (Monk) on Feb 22, 2016 at 18:44 UTC
    And I think that extra flush is something XML::Twig documents as being required in some circumstances anyway, IIRC.

    Correct. According to the XML::Twig docs, "if you use flush at any point during parsing, the document will be flushed one last time at the end of the parsing, to the proper filehandle."

    For example, updating _move to be:<snip...>

    That is essentially what I ended up doing in my final code to work around the problem:

    sub _move { # Skip this section if no "<slip>" descendants are found if ( !scalar $_[1]->descendants('slip') ) { $_[1]->delete; $_[0]->purge; } # "<slip>" descendants found, process as normal else { <...> $_[1]->delete; $_[0]->flush(); } 1; }

    This appears to work, but I don't know why it works, or even what the root problem is. It all feels very cargo-cult right now...