2

我有一个 HTML 文档作为字符串。我使用 Nokogiri 解析它:

doc_str = <<-mydoc
  <p>Lorem ipsum dolor sit foo.</p>
  <h2>Consectetur adipisicing bar</h2>
  <p>Foo do <a href="/c-foo.aspx" class = "foo" title="Foo bar.">foofoo foo</a>.</p>
mydoc

doc = Nokogiri::HTML doc_str

我想在所有可见文本中用/替换"foo"/ :"Foo""Bar""bar"

desired = <<-mydoc
  <p>Lorem ipsum dolor sit bar.</p>
  <h2>Consectetur adipisicing bar</h2>
  <p>Bar do <a href="/c-foo.aspx" class = "foo" title="Bar bar.">foofoo bar</a>.</p>
mydoc

我怎么做?

我尝试阅读Nokogiri 教程,其中描述了Nokogiri::HTML::Document#at_css. 使用 Ruby 2.0 和最新的 Nokogiri,doc.at_css 'h1'返回nil,所以h1.content = "something"甚至是不可能的。

即使它有效,也只是解决我的查找和替换问题的第一步。

4

1 回答 1

3

doc.at_css 'h1'返回nil,因为您的 HTML 中没有h1元素。doc.at_css 'h2'正确返回元素的Nokogiri::XML::Element对象。h2

CSS 选择器无法选择文本节点,并且对于这类事情来说是一个糟糕的工具。XPath 将完成 CSS 所做的所有事情以及更多其他事情。文档根目录下的任何文本节点都是简单的//text().

编辑我刚刚注意到您似乎希望属性的内容以相同的方式更改。@*匹配任何属性,因此 XPath 表达式变为//@* | //text(). 虽然我不清楚这个 ashref="/c-foo.aspx"并且class="foo"保持不变但是title="Foo bar."变成title="bar bar.". 我相信你可以自己解决这个问题。

您需要使用 XPath 查找所有文本节点,然后用于content获取每个节点的文本值。根据需要修改它并使用content=它来替换它。

这个程序演示。该to_html方法将数据包装在使其成为有效 HTML 所需的标记中。

require 'nokogiri'

doc_str = <<-HTML
  <p>Lorem ipsum dolor sit foo.</p>
  <h2>Consectetur adipisicing bar</h2>
  <p>Foo do <a href="/c-foo.aspx" class = "foo" title="Foo bar.">foofoo foo</a>.</p>
HTML

doc = Nokogiri::HTML(doc_str)

doc.xpath('//@*', '//text()').each do |node|
  node.content = node.content.gsub(/\bfoo\b/, 'bar').gsub(/\bFoo\b/, 'Bar')
end

puts doc.to_html

输出

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<p>Lorem ipsum dolor sit bar.</p>
  <h2>Consectetur adipisicing bar</h2>
  <p>Bar do <a href="/c-bar.aspx" class="bar" title="Bar bar.">foofoo bar</a>.</p>
</body></html>
于 2013-07-04T23:35:27.273 回答