use warnings;
use strict;
use XML::LibXML;
my $doc = XML::LibXML->load_xml(string => <<'XML');
hello, foobar world! foo fooofoo
XML
my $re = qr/foo/; # don't include any capturing parens in this!
my @nodes = $doc->documentElement;
while (my $node = pop @nodes) {
for my $c ($node->childNodes) {
if ($c->nodeType==XML_ELEMENT_NODE) { push @nodes, $c }
elsif ($c->nodeType==XML_TEXT_NODE || $c->nodeType==XML_CDATA_SECTION_NODE) {
my @parts = split /($re)/, $c->data;
next unless @parts>1;
my $d = $doc->createDocumentFragment;
for my $i (0..$#parts) {
if ($i%2) { # regex match
my $e = $doc->createElement('x');
$e->appendText($parts[$i]);
$d->appendChild($e);
}
else { # text around match
$d->appendText($parts[$i]);
}
}
$node->replaceChild($d, $c);
}
}
}
print $doc->toString;
__END__
hello, foobar world! foo fooofoo