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.