我正在使用XML::LibXML
,我只需要计算XPath表达式指定的节点数。
使用下面前两个代码行中的任何一个产生我正在寻找的东西。我可以将count
XPath函数与findvalue
或find
但不是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)
文档中的参数$xpath_expression
与仅$xpath
之间确实存在差异吗?
对于返回标量的两个人来说,有什么区别?
我试图理解使用一种查找类型而不是另一种查找类型的重要性 - 谢谢!
答案 0 :(得分:17)
不同之处在于方法返回的值的类型。
findnodes
用于返回节点列表。如果在列表上下文中调用该方法,则它返回相应类型的对象列表,例如XML::LibXML::Element
,XML::LibXML::Text
等。如果在标量上下文中调用它,则返回单个{{1包含相同信息的对象。
不能用于返回任意表达式,例如XML::LibXML::NodeList
将不返回任何内容。您只能通过此方法获取列表文档节点。
$dom->findnodes('42')
用于返回单个文本或数字值,即不是XML节点。如果传递一个评估为节点列表的XPath表达式,则它会通过连接列表中任何节点内的所有文本节点将该列表转换为文本。
findvalue
可以返回任何内容。它将返回一个节点列表作为find
对象,一个数值作为XML::LibXML::NodeList
对象,一个字符串文字作为XML::LibXML::Number
对象等。与XML::LibXML::Literal
不同,它是 always 返回单个标量值,即使在列表上下文中调用也是如此。
我从未选择使用findnodes
。当你不知道期望什么样的结果时,它看起来像是一个捕获。
例如,您可能希望编写find
来获取根元素中的记录数。 my $nrecs = $dom->findvalue('count(/root/record)')
将是一个简单的perl数值。
另一方面,要获取这些记录的列表,您可以使用$nrecs
。现在my @records = $dom->findnodes('/root/record')
包含许多@records
个对象。
在您的示例中,
XML::LibXML::Element
这会将my $node_cnt = $dom->findvalue("count($xpath_str)"); # WORKS!
设置为一个简单的Perl号码,而这个
$node_cnt
将my $node_cnt = $dom->find("count($xpath_str)"); # WORKS!
设置为$node_cnt
对象,该字符串化(当您打印时)与前一个语句相同。通过在两种情况下打印XML::LibXML::Number
来证明这一点。
然后
print ref $node_cnt
失败,因为XPath my @node_cnt = $dom->findnodes("count($xpath_str)"); # count doesn't work!
求值为数字,而不是XML节点(它不是XML树的一部分)。无法将数字转换为节点,因此结果为空列表。如果它是反过来的,并且我们在一个评估到节点列表的表达式上调用了count
,那么有一种模糊的方法可以转换为文本值,findvalue
做得最好,返回列表中节点包含的所有文本节点的串联。