用于搜索通用文本的XPath语法?

时间:2014-06-09 10:00:46

标签: ruby parsing xpath nokogiri

我有一个使用Nokogiri解析的HTML页面,我应该找到包含在每个元素中的通用文本。它与哪个元素无关,它应该与我传递给contains()的文本匹配。

我现在能够获得的结果非常通用,我不确定我是否正确解释了XPath文档:

html = Nokogiri::HTML(page['result'])
puts html.xpath("/*[contains(., 'Foobar')]")

我想要的是包含“Foobar”的元素,但是库正在返回整个页面。我做错了什么?

2 个答案:

答案 0 :(得分:1)

/与XPath一起使用意味着从文档的根目录开始,这不是您想要的。 xpath将找到所有匹配的元素,这意味着还将找到包含所需文本的所有祖先节点,从而导致根目录下的所有内容满足条件。

以下是一个显示此示例的示例:

require 'nokogiri'

xml = '<html><body><div><p>foobar</p></div></body></html>'
doc = Nokogiri::XML(xml)
doc.xpath("/*[contains(., 'foobar')]").map(&:to_html)
# => ["<html><body><div><p>foobar</p></div></body></html>"]

我会这样搜索:

require 'nokogiri'

xml = '<html><body><div><p id="1">foobar</p></div><div><p id="2">foobar</p></div></body></html>'
doc = Nokogiri::XML(xml)
doc.search("//text()[contains(., 'foobar')]").map{ |t| t.parent.to_html }
# => ["<p id=\"1\">foobar</p>", "<p id=\"2\">foobar</p>"]

这将在所有文本节点中搜索所需的文本,然后检索该节点的父节点,这似乎更有用。

这是相同的代码,用于检索XPath到节点:

doc.search("//text()[contains(., 'foobar')]").map{ |t| t.parent.path }
# => ["/html/body/div[1]/p", "/html/body/div[2]/p"]

答案 1 :(得分:0)

您尝试过的XPath会返回包含Foobar文本的所有元素,包括这些元素的祖先(因为祖先也被视为包含Foobar文本,尽管间接 )。

您可以这样做,只获取直接包含Foobar文字的元素:

puts html.xpath("/*[contains(text(), 'Foobar')]")