5

For the life of me I can't figure out the proper code to access the comment lines in my XML file. Do I use findnodes, find, getElementByTagName (doubt it).

Am I even making the correct assumption that these comment lines are accessible? I would hope so, as I know I can add a comment.

The type number for a comment node is 8, so they must be parseable.

Ultimately, what I want tot do is delete them.

my @nodes = $dom->findnodes("//*");

foreach my $node (@nodes) {
  print $node->nodeType, "\n";
}

<TT>
 <A>xyz</A>
 <!-- my comment -->
</TT> 
4

3 回答 3

9
  • 如果您需要做的只是生成一份删除了注释节点的 XML 副本,那么 的第一个参数toStringC14N是一个标志,表示您是否希望在输出中添加注释。省略所有参数会隐式将第一个参数设置为 false 值,因此

    $doc->toStringC14N
    

将重现 XML 修剪的评论。请注意,C14N 指定的规范 XML 格式不包括 XML 声明头。它总是以 UTF-8 编码的 XML 1.0。

  • 如果您需要在进一步处理之前从文档的内存结构中删除注释,那么findnodesXPath 表达式//comment()将为您找到它们,unbindNode并将它们从 XML 中删除。

这个程序演示

use strict;
use warnings;

use XML::LibXML;

my $doc = XML::LibXML->load_xml(string => <<END_XML);
<TT>
 <A>xyz</A>
 <!-- my comment -->
</TT>
END_XML

# Print everything
print $doc->toString, "\n";

# Print without comments
print $doc->toStringC14N, "\n\n";

# Remove comments and print everything
$_->unbindNode for $doc->findnodes('//comment()');
print $doc->toString;

输出

<?xml version="1.0"?>
<TT>
 <A>xyz</A>
 <!-- my comment -->
</TT>

<TT>
 <A>xyz</A>

</TT>

<?xml version="1.0"?>
<TT>
 <A>xyz</A>

</TT>



更新

要选择特定注释,您可以将谓词表达式添加到 XPath 选择器。要在示例数据中查找特定评论,您可以编写

$doc->findnodes('//comment()[. = " my comment "]')

请注意,注释的文本包括前导和尾随之外的--,因此空格很重要,如该调用所示。

如果你想让事情变得更宽松一些,你可以使用normalize=space,它删除前导和尾随空格,并将字符串中的每个空格序列压缩为一个空格。现在你可以写

$doc->findnodes('//comment()[normalize-space(.) = "my comment"]')

即使看起来像这样,同一个电话也会找到您的评论。

<!--
my
comment
-->

最后,您可以使用contains,正如您所期望的,它只是检查一个字符串是否包含另一个字符串。使用它你可以写

$doc->findnodes('//comment()[contains(., "comm")]')

选择哪一种取决于您的要求和您的情况。

于 2013-10-17T17:10:18.293 回答
8

根据 XPath 规范:

  • *是匹配任何名称的元素节点的测试。注释节点不是元素节点。

  • comment()是一个匹配评论节点的测试。

未经测试:

for $comment_node ($doc->findnodes('//comment()')) {
   $comment_node->parentNode->removeChild($comment_node);
}
于 2013-10-17T17:01:13.090 回答
2

我知道不是,但在这里你有另一种方法可以使用模块XML::LibXML轻松删除评论:XML::Twig

#!/usr/bin/env perl

use warnings;
use strict;
use XML::Twig;

my $twig = XML::Twig->new(
    pretty_print => 'indented',
    comments => 'drop'
)->parsefile( shift )->print;

像这样运行它:

perl script.pl xmlfile

这会产生:

<TT>
  <A>xyz</A>
</TT>

comments选项还具有process允许您使用 的值与它们一起工作的xpath#COMMENT

于 2013-10-17T16:35:42.073 回答