如何防止 XML::LibXML 使用自关闭标签保存修改后的 xml
How to prevent XML::LibXML to save modified xml using self-closing tag
以下工作代码读取我的 XML
包含大量空元素的文件,然后应用 2 处更改并以不同的名称再次保存。
但它也会将 <element></element>
等空元素更改为不需要的 <element />
等自闭合标签。
如何不使用自动关闭标签保存它?
或者换句话说如何告诉 XML::LibXML
使用空标签?
原文件是在商业应用程序中生成的,它使用带有空元素的样式,所以我想支持它。
#! /usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $filename = 'out.xml';
my $dom = XML::LibXML->load_xml(location => $filename);
my $query = '//scalar[contains(@name, "partitionsNo")]/value';
for my $i ($dom->findnodes($query)) {
$i->removeChildNodes();
$i->appendText('16');
}
open my $out, '>', 'out2.xml';
binmode $out;
$dom->toFH($out);
# now out2.xml has only self-closing tags where previously
# were used empty elements
不幸的是,XML::LibXML
不支持 libxml2 的 xmlsave
模块,该模块有一个 flag 可以在没有空标签的情况下保存。
作为解决方法,您可以向空元素添加一个空文本节点:
for my $node ($doc->findnodes('//*[not(node())]')) {
# Note that appendText doesn't work.
$node->appendChild($doc->createTextNode(''));
}
这对于大型文档来说有点昂贵,但我不知道有更好的解决方案。
也就是说,片段 <foo></foo>
和 <foo/>
都是 格式正确的 和 语义等价的 。任何 XML 以不同方式处理此类片段的解析器或应用程序都是错误的。
请注意,有些人认为 XML 规范建议使用自闭合标签,但事实并非如此。 XML 规范说:
Empty-element tags may be used for any element which has no content, whether or not it is declared using the keyword EMPTY. For interoperability, the empty-element tag should be used, and should only be used, for elements which are declared EMPTY.
这意味着声明的元素 EMPTY in a DTD。对于其他元素,或者如果不存在 DTD,XML 标准建议不要使用自闭合标签 ("and should only be used")。但这只是互操作性的非约束性建议。
有包变量
$XML::LibXML::setTagCompression
将其设置为真值会强制所有空标签打印为 <e></e>
,而假值会强制 <e/>
.
请参阅解析器文档中的 SERIALIZATION。
以下工作代码读取我的 XML
包含大量空元素的文件,然后应用 2 处更改并以不同的名称再次保存。
但它也会将 <element></element>
等空元素更改为不需要的 <element />
等自闭合标签。
如何不使用自动关闭标签保存它?
或者换句话说如何告诉 XML::LibXML
使用空标签?
原文件是在商业应用程序中生成的,它使用带有空元素的样式,所以我想支持它。
#! /usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $filename = 'out.xml';
my $dom = XML::LibXML->load_xml(location => $filename);
my $query = '//scalar[contains(@name, "partitionsNo")]/value';
for my $i ($dom->findnodes($query)) {
$i->removeChildNodes();
$i->appendText('16');
}
open my $out, '>', 'out2.xml';
binmode $out;
$dom->toFH($out);
# now out2.xml has only self-closing tags where previously
# were used empty elements
不幸的是,XML::LibXML
不支持 libxml2 的 xmlsave
模块,该模块有一个 flag 可以在没有空标签的情况下保存。
作为解决方法,您可以向空元素添加一个空文本节点:
for my $node ($doc->findnodes('//*[not(node())]')) {
# Note that appendText doesn't work.
$node->appendChild($doc->createTextNode(''));
}
这对于大型文档来说有点昂贵,但我不知道有更好的解决方案。
也就是说,片段 <foo></foo>
和 <foo/>
都是 格式正确的 和 语义等价的 。任何 XML 以不同方式处理此类片段的解析器或应用程序都是错误的。
请注意,有些人认为 XML 规范建议使用自闭合标签,但事实并非如此。 XML 规范说:
Empty-element tags may be used for any element which has no content, whether or not it is declared using the keyword EMPTY. For interoperability, the empty-element tag should be used, and should only be used, for elements which are declared EMPTY.
这意味着声明的元素 EMPTY in a DTD。对于其他元素,或者如果不存在 DTD,XML 标准建议不要使用自闭合标签 ("and should only be used")。但这只是互操作性的非约束性建议。
有包变量
$XML::LibXML::setTagCompression
将其设置为真值会强制所有空标签打印为 <e></e>
,而假值会强制 <e/>
.
请参阅解析器文档中的 SERIALIZATION。