我正在尝试清理一些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
}