Perl 如何防止XML::LibXML使用自动关闭标记保存修改过的XML

Perl 如何防止XML::LibXML使用自动关闭标记保存修改过的XML,perl,xml-libxml,Perl,Xml Libxml,下面的工作代码读取我的XML文件,该文件包含许多空元素,然后应用2个更改并以不同的名称再次保存它。 但它也会将空元素(如)更改为不需要的自动关闭标记(如) 如何不使用自动关闭标签保存它? 或者换句话说,如何告诉XML::LibXML使用空标记? 原始文件是在商业应用程序中生成的,该应用程序使用带有空元素的样式,因此我希望保持这种风格 #! /usr/bin/perl use strict; use warnings; use XML::LibXML; my $filename = 'out.

下面的工作代码读取我的
XML
文件,该文件包含许多空元素,然后应用2个更改并以不同的名称再次保存它。 但它也会将空元素(如
)更改为不需要的自动关闭标记(如
) 如何不使用自动关闭标签保存它? 或者换句话说,如何告诉
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
模块,该模块有一个不带空标记的要保存的文件

作为一种解决方法,您可以向空元素添加空文本节点:

for my $node ($doc->findnodes('//*[not(node())]')) {
    # Note that appendText doesn't work.
    $node->appendChild($doc->createTextNode(''));
}
这对于大型文档来说成本有点高,但我不知道有更好的解决方案

也就是说,片段
都是格式良好的,语义上是等价的。任何以不同方式处理这些片段的XML解析器或应用程序都是有缺陷的


注意,有些人认为XML规范建议使用自动关闭标记,但事实并非如此。XML规范说:

空元素标记可用于任何没有内容的元素,无论是否使用关键字Empty声明。对于互操作性,空元素标记应该被使用,并且只应该被用于声明为空的元素


这意味着要声明的元素。对于其他元素,或者如果没有DTD,XML标准建议不要使用自动关闭标记(“并且应该只使用”)。但这只是互操作性的非约束性建议。

有一个包变量

$XML::LibXML::setTagCompression
将其设置为真值将强制将所有空标记打印为
,而假值将强制打印为


请参阅解析器文档。

@Deckerz当然
不是无效的XML。“为了能够区分文件,而不会因为将空元素交换为自动关闭标记而导致错误命中”-您解决了错误的问题。停止尝试将XML视为非XML。如果您想区分它,请使用支持XML的区分工具。@Deckerz:
是无效的。您一直这么说,但事实并非如此<代码>与
一样有效。后者只是一个快捷方式。@Deckerz:那么为什么要将


作为空元素的示例?@Deckerz,应该使用空标记
。Quote:空元素标记可用于任何没有内容的元素,无论是否使用关键字Empty声明。对于互操作性,空元素标记应该使用,并且只应该用于声明为空的元素。谢谢您的回答。毕竟我不会使用它,因为应用程序不会抱怨。鉴于这个问题下的评论战,我很高兴你给我指出libxml2 xmlsave及其标志,而不是在perls XML::LibXML中实现的。@PetrMatousu你有没有尝试过Perl中的其他XML模块来做你正在做的事情?我认为有些不依赖于XML::LibXML,它们可能已经按照您想要的方式运行了。@simbabque我也在搜索其他内容,看起来LibXML很好地满足了我的需要。有些人不喜欢SimpleXML,我需要避免任何数据丢失。我必须对修改过的文件进行更多的测试。和XML:LibXML有很好的文档记录。谢谢你指出这一点。