【发布时间】:2012-08-31 15:57:10
【问题描述】:
亲爱的 Perl 和 XML 大师
我的任务是使用 XPath 更新 XML 文件中的值。
我使用 Perl 中的XML::LibXML 库来读取、更改和保存 XML 文件:
# 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;
虽然它生成的文件与原始文件非常相似,但仍然存在一些麻烦:
- 换行符(行尾)是 Unix 风格的,虽然原始文件是 Windows 风格的。
- 关闭 /> 之前的空格被删除,例如
<node />变为<node/>。
有机会解决这些问题吗?我希望得到与原始文件完全相同的 XML 文件,唯一不同的是我正在修改的属性值......
附:我真的很喜欢 NAnt 中的 <xmlpoke> 多么简单。但必须使用 Perl 来完成这项工作。
【问题讨论】:
-
兼容的 XML 解析器不得是往返安全的。 (意思是:对于所有有效输入,输入与输出完全相同。) XML 标准中有多个位置要求以破坏性方式修改输入流。在空元素上关闭
/>之前的空格是必需的或禁止的,但我不知道有多少解析器会记住它以供以后序列化。 -
谢谢文达祖!有趣的信息...
标签: xml perl newline libxml2 xml-libxml