使用xpath在所有节点中搜索文本

时间:2017-01-22 13:17:17

标签: ruby xpath nokogiri

我试图在html片段中找到单词以用href替换它们。不知何故无法找到用于Xpath的正确路径。例如:

require 'nokogiri'

html = '
<p>A paragraph Apple<p>
<span>Apple</span>
<ul>
  <li>Item 1</li>
  <li>Apple <strong>Apple</strong></li>
  <li>Apple</li>
  <li>Orange</li>
</ul>
<p><i>Apple</i>Apple</p>'

doc = Nokogiri::HTML.fragment(html)
doc.xpath('.//*[text()="Apple"]').each do |node|
  puts "\n"
  puts node.name
  puts node.content
  puts node.replace('REPLACED')
end

puts doc.to_html

结果

span
Apple
REPLACED

strong
Apple
REPLACED

li
Apple
REPLACED

i
Apple
REPLACED
<p>A paragraph Apple</p><p>
REPLACED

</p><ul>
  <li>Item 1</li>
  <li>Apple REPLACED</li>
  REPLACED
  <li>Orange</li>
</ul>
<p>REPLACEDApple</p>

因此,根p元素中的单词不会被替换,而li中的单词将被保留。在这种情况下我应该使用哪条路径来搜索root和所有孩子?在this .//*这样的页面上阅读应该是用于在根节点和子节点中进行搜索的路径。有关如何使用nokogiri或xpath正确处理此问题的任何想法?

提前致谢!

1 个答案:

答案 0 :(得分:1)

您正在寻找整个文本等于"Apple"的节点,而不是包含"Apple"的节点

html = '
<p>A paragraph Apple<p>
<span>Apple</span>
<ul>
  <li>Item 1</li>
  <li>Apple <strong>Apple</strong></li>
  <li>Apple</li>
  <li>Orange</li>
</ul>
<p><i>Apple</i>Apple</p>
<Apple>Dont replace!</Apple>
'

doc = Nokogiri::HTML.fragment(html)

doc.traverse do |node|
  if node.text?
    node.content = node.content.gsub('Apple', 'REPLACED')
  end
end

puts doc.to_html

输出:

<p>A paragraph REPLACED</p><p>
<span>REPLACED</span>
</p><ul>
  <li>Item 1</li>
  <li>REPLACED <strong>REPLACED</strong>
</li>
  <li>REPLACED</li>
  <li>Orange</li>
</ul>
<p><i>REPLACED</i>REPLACED</p>
<apple>Dont replace!</apple>