不同之处在于方法返回的值的类型。
findnodes
用于返回节点列表。如果在列表上下文中调用该方法,则返回适当类型的对象列表,例如XML::LibXML::Element
等XML::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
并尽其所能返回包含的所有文本节点的串联列表中的节点。