13

我正在使用XML::LibXML,我只需要获取 XPath 表达式指定的节点数。

使用下面的前两个代码行中的任何一个都会产生我正在寻找的内容。我可以使用countXPath 函数,也可以findvaluefind使用findnodes(是的,我知道,因为它返回一个列表)。

my $node_cnt = $dom->findvalue("count($xpath_str)");  # WORKS!
my $node_cnt = $dom->find("count($xpath_str)");       # WORKS!
my @node_cnt = $dom->findnodes("count($xpath_str)");  # count doesn't work!

这让我想到了一个普遍的唠叨问题:这三种类型有什么区别find?在文档中,它说:

$string = $node->findvalue($xpath)
$result = $node->find($xpath)
@nodes  = $node->findnodes($xpath_expression)
  1. $xpath_expression论点与$xpath文档中的论点之间真的有区别吗?

  2. 对于返回标量的两个,有什么区别?

我试图了解使用一种查找类型而不是另一种查找类型的重要性 - 谢谢!

4

1 回答 1

19

不同之处在于方法返回的值的类型。

  • findnodes用于返回节点列表。如果在列表上下文中调用该方法,则返回适当类型的对象列表,例如XML::LibXML::ElementXML::LibXML::Text。如果在标量上下文中调用,则返回XML::LibXML::NodeList包含相同信息的单个对象。

    不能用于返回任意表达式,例如$dom->findnodes('42')不会返回任何内容。您只能从此方法获取列表文档节点。

  • findvalue用于返回单个文本或数值即不是 XML 节点。如果您传递一个计算结果为节点列表的 XPath 表达式,那么它将通过连接列表中任何节点中的所有文本节点将该列表转换为文本。

  • find可以返回任何东西。它将返回一个节点列表作为一个XML::LibXML::NodeList对象,一个数值作为一个XML::LibXML::Number对象,一个字符串文字作为一个XML::LibXML::Literal对象等。与 不同的findnodes是,它总是返回单个标量值,即使在列表上下文中调用也是如此。

    我从来没有选择使用find. 当您不知道期望什么样的结果时,它看起来像是一个包罗万象的东西。

例如,您可能想要编写my $nrecs = $dom->findvalue('count(/root/record)')以获取根元素中的记录数。$nrecs将是一个简单的 perl 数值。

另一方面,要获取这些记录的列表,您可以使用 my @records = $dom->findnodes('/root/record'). 现在@records包含许多XML::LibXML::Element对象。

在你的例子中,

my $node_cnt = $dom->findvalue("count($xpath_str)");  # WORKS!

这设置$node_cnt为一个简单的 Perl 编号,而这

my $node_cnt = $dom->find("count($xpath_str)");  # WORKS!

设置$node_cnt为一个XML::LibXML::Number对象,这恰好将字符串化(当您打印它时)与前一个语句相同。print ref $node_cnt通过在这两种情况下打印来证明这一点。

然后

my @node_cnt = $dom->findnodes("count($xpath_str)");  # count doesn't work!

失败是因为 XPathcount计算结果为数字,而不是 XML 节点(它不是 XML 树的一部分)。无法将数字转换为节点,因此结果是一个空列表。如果反过来,我们调用findvalue了一个计算为节点列表的表达式,那么有一种模糊合理的方式可以转换为文本值,findvalue并尽其所能返回包含的所有文本节点的串联列表中的节点。

于 2013-11-06T16:39:02.863 回答