我使用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>
中获取文字。
答案 0 :(得分:2)
您不会在xpath查询中询问文本内容:
rs = doc.xpath('//a/b1/c/d1/text()')
答案 1 :(得分:2)
您滥用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/2001\n 02/02/2004\n "
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
虽然告诉解析器在text()
内找到<d1>
节点似乎很好/聪明,但是返回的内容不是文本,需要进一步访问才能生成它可以使用,所以请考虑放弃使用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
来实现你编码的大部分。当您必须指定一个或另一个时,请使用特定版本。