Note When changing flush to print code in the question works for me (with valid XML).
However, I still recommend any of the versions below. Tested by two groups of valid XML files.
When XML::Twig->new(...) installed first, and then the files loop and process, I get the same behavior. The first file is processed correctly, the rest are completely closed. Edit When flush is replaced with print , the code shown actually works (with the correct XML files). However, I still suggest one of the versions below, since XML::Twig simply does not support multiple files.
The reason may relate to new as a class method. However, I do not understand why this should affect the processing of multiple files. The callback is set outside of the loop, but I tested it with reinstallation for each file, and that doesn't help.
Finally, flush -ing is not required as long as it clearly hurts here, clearing the state (which was created by the class method new ). This does not affect the code below, but it is still replaced with print .
Then just do everything in a loop. Simple version
use strict; use warnings; use File::Find::Rule; use XML::Twig; my @files = File::Find::Rule->file->name('*.xml')->in('...'); foreach my $file (@files) { print "Processing $file\n"; my $t = XML::Twig->new( pretty_print => 'indented', twig_handlers => { loot => \&clear_elt }, ); $t->parsefile_inplace($file)->print; } sub clear_elt { my ($t, $elt) = @_; my $elt_name = $elt->name;
The callback code is simplified to remove the entire item and then add it back empty. Note that the substring does not require the element name to be hardcoded. Thus, it can be used to remove any item.
We can avoid calling new in the loop with another method of the nparse class.
my $t = XML::Twig->new( pretty_print => 'indented' ); foreach my $file (@files) { print "Processing $file\n"; my $tobj = XML::Twig->nparse( twig_handlers => { loot => \&clear_elt }, $file ); $tobj->parsefile_inplace($file)->print; }
We must first call the constructor new , even if it is not used directly in the loop.
Note that calling new before the loop without twig_handlers , and then setting the handlers inside
$t->setTwigHandlers(loot => sub { ... });
Does not help. We still get only the first file processed correctly.