使用Nokogiri对HTML进行消毒



我正在尝试清理一些CMS输入的HTML,这些HTML到处都是无关的段落标记和br标记。事实证明,Sanitize宝石非常有用,但我遇到了一个特殊的问题。

问题是当段落标签(如)后面/前面有br标签时

<p>
  <br />
  Some text here
  <br />
  Some more text
  <br />
</p>

我想去掉多余的第一个和最后一个br标签,但不去掉中间的。

我非常希望我能使用消毒变压器来做到这一点,但似乎找不到合适的匹配器来实现这一点。

任何帮助都将不胜感激。

以下是如何定位<p>:所包含的特定<br>节点

require 'nokogiri'
doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p>
  <br />
  Some text here
  <br />
  Some more text
  <br />
</p>
EOT
doc.search('p > br').map(&:to_html)
# => ["<br>", "<br>", "<br>"]

一旦我们知道我们可以找到它们,就很容易删除特定的:

br_nodes = doc.search('p > br')
br_nodes.first.remove
br_nodes.last.remove
doc.to_html
# => "<p>n  n  Some text heren  <br>n  Some more textn  n</p>n"

请注意,Nokogiri删除了它们,但留下了它们的关联Text节点,这些节点是它们的直系兄弟,包含它们的"\n"。浏览器会吞噬这些内容,而不会显示行的末尾,但你可能会感到强迫症,所以下面是如何删除这些内容:

br_nodes = doc.search('p > br')
[br_nodes.first, br_nodes.last].each do |br|
  br.next_sibling.remove
  br.remove
end
doc.to_html
# => "<p>n  <br>n  Some more textn  </p>n"
initial_linebreak_transformer = lambda {|options|
  node = options[:node]
  if node.present? && node.element? && node.name.downcase == 'p'
    first_child = node.children.first
    if first_child.name.downcase == 'br'
      first_child.unlink
      initial_linebreak_transformer.call options
    end
  end
}

相关内容

  • 没有找到相关文章

最新更新