我有一个使用Nokogiri解析的HTML页面,我应该找到每个元素中包含的通用文本。不管它是哪个元素,它应该匹配我传递给contains()
的文本。
我目前能够得到的结果是非常通用的,我不确定我是否正确地解释了XPath文档:
html = Nokogiri::HTML(page['result'])
puts html.xpath("/*[contains(., 'Foobar')]")
我想要的是包含"Foobar"的元素,但是库返回整个页面。我做错了什么?
使用/
和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"]
您尝试的XPath返回包含Foobar
文本的所有元素,包括上述元素的祖先(因为祖先也被认为包含Foobar
文本,尽管间接)。
您可以这样做,只获得直接包含Foobar
text:
puts html.xpath("/*[contains(text(), 'Foobar')]")