XPath is able to find nodes without needing to know the position in the tree.
use strictures;
use XML::LibXML qw();
my $dom = XML::LibXML->load_xml(string => <<'XML');
<a>
<id>ABC</id>
<class />
<gender />
</a>
XML
for my $id ($dom->findnodes('//id[string()="ABC"]')) {
$id->removeChildNodes;
$id->appendText('DEF');
}
print $dom->toString
A simple XML::Twig solution would be:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $FILE= 'id.xml';
XML::Twig->new( twig_handlers => { 'id[string()="ABC"]' => sub { $_->set_text( 'DEF'); } },
keep_spaces => 1,
)
->parsefile( $FILE)
->print_to_file( $FILE);
Just for fun: an efficient XML::Twig solution is a bit more convoluted, mostly because you can't use string()
conditions with twig_roots
. Still, it's quite compact, and it never loads the whole file in memory.
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new( twig_roots => { id => sub { $_->flush }, },
twig_handlers => { 'id[string()="ABC"]' => sub { $_->set_text( 'DEF'); } },
twig_print_outside_roots => 1,
)
->parsefile_inplace( 'id.xml');
perl -i.bak -pe 's/abc/def/g' myfile.xml
you'll get a new file myfile.xml.bak which ha