Dear Perl and XML gurus
I have a task to update values inside XML file using XPath.
I use XML::LibXML
library in Perl to read, alter and save XML file:
# Read XML file
my $parser = XML::LibXML->new();
my $doc = $parser->load_xml(location => $config_file);
my $root = $doc->documentElement();
# Alter nodes\attributes
foreach (keys %environment_values) {
my @nodes = $root->findnodes($_);
if (scalar @nodes < 1) {
print "ERROR: element not found in $config_file by XPath: $_\n";
die;
} elsif (scalar @nodes > 1) {
print "ERROR: more than 1 element (" . scalar @nodes . ") is found in $config_file by XPath: $_\n";
die;
}
my $node = $nodes[0];
if ($node->nodeType == XML_ELEMENT_NODE) {
$node->removeChildNodes();
$node->appendText($environment_values{$_});
} elsif ($node->nodeType == XML_ATTRIBUTE_NODE) {
$node->setValue($environment_values{$_});
} else {
print "ERROR: unknown node type: " . $node->nodeType . "\n";
die;
}
}
# Save the resulting XML file
open (my $fh, '>:raw', $config_file) or die $!;
print $fh $doc->toString();
close $fh;
Although it generates a file very similar to the original one, there are still a couple of nuisances:
- Newline characters (line endings) are Unix-style, although original file has them in Windows-style.
- Space before the closing /> gets removed, e.g.
<node />
becomes<node/>
.
Any chance to fix these? I'm hoping to get exactly the same XML file as the original one, with only differences being attribute values I'm amending...
P.S. I really like how simple is <xmlpoke>
in NAnt. But have to use Perl for this work.