我正在使用Ruby, XPath和Nokogiri,并试图从以下XML检索d1
:
<a>
<b1>
<c>
<d1>01/11/2001</d1>
<d2>02/02/2004</d2>
</c>
</b1>
</a>
这是我的循环代码:
rs = doc.xpath("//a/b1/c/d1").inner_text
puts rs
它不返回任何东西(没有错误)。
我想在<d1>
中获取文本
不要在xpath查询中询问文本内容:
rs = doc.xpath('//a/b1/c/d1/text()')
您在错误地使用XPath:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<a>
<b1>
<c>
<d1>01/11/2001</d1>
<d2>02/02/2004</d2>
</c>
</b1>
</a>
EOT
doc.at('/a/b1/c/d1').text # => "01/11/2001"
doc.at('//d1').text # => "01/11/2001"
//
在XPath-ese中意味着从顶部开始并查看文档中的任何位置。相反,如果您提供显式/绝对选择器,请从文档的顶部开始,并使用'/a/b1/c/d1'
向下钻取。或者,执行简单的操作,让解析器使用//d1
在文档中搜索特定节点。如果知道该节点只有一个实例,就可以这样做。
在上面的代码中,我使用at
而不是xpath
。at
返回第一个匹配节点,这与使用xpath('//d1').first
类似。xpath
返回一个NodeSet,类似于一个节点数组,而at
只返回一个Node。在NodeSet上使用inner_text
可能不会给您想要的结果,这些结果可能是特定节点的文本,因此要小心。
doc.xpath('/a/b1/c/d1/text()').class # => Nokogiri::XML::NodeSet
doc.xpath('//c').inner_text # => "n 01/11/2001n 02/02/2004n "
doc.xpath('/a/b1/c/d1').first.text # => "01/11/2001"
看下面几行。我没有使用XPath选择器,而是使用了更具可读性的CSS。Nokogiri都支持。
doc.at('d1').text # => "01/11/2001"
doc.at('a b1 c d1').text # => "01/11/2001"
另外,请注意从这两行返回的数据类型:
doc.at('/a/b1/c/d1/text()').class # => Nokogiri::XML::Text
doc.at('/a/b1/c/d1').text.class # => String
虽然告诉解析器在<d1>
中找到text()
节点似乎很好/聪明,但返回的不是文本,需要进一步访问才能使其可用,所以考虑放弃使用text()
,除非您确切地知道为什么需要它:
doc.at('/a/b1/c/d1/text()').text # => "01/11/2001"
最后,Nokogiri有许多用于定位节点的方法。如上所述,xpath
返回一个NodeSet, at
返回一个Node。xpath
实际上是Nokogiri的search
方法的xpath特定版本。search
, css
和xpath
都返回nodeset。at
、at_css
、at_xpath
均返回节点。当您有一个模棱两可的选择器,需要将其用作CSS或XPath时,CSS和XPath变体非常有用。大多数情况下,Nokogiri可以自己判断它是CSS还是XPath,并且会做正确的事情,因此在大多数代码中使用通用的search
和at
是可以的。当你必须指定一个或另一个时,使用特定的版本