【问题标题】:How to remove specific tags but leave allowed tags如何删除特定标签但保留允许的标签
【发布时间】:2015-12-13 00:53:28
【问题描述】:

在某些 HTML 中,我想删除一些特定的标签,但保留标签的内容/HTML。例如,在下面的行中,我 想要删除列入黑名单的<strong><div> 标签,但保留标签的内容,并仅从我的白名单标签中保留<p><img> 和其他标签:

原文:

<div>
    some text
    <strong>text</strong>
    <p>other text</p>
    <img src="http://example.com" />
</div>

结果:

some text
text
<p>other text</p>
<img src="http://example.com" />

我想去除特定标签,某些标签不能去除。它必须像 PHP 中的 strip_tags 一样工作。所以inner_html 帮不了我。

【问题讨论】:

标签: html ruby parsing nokogiri


【解决方案1】:

使用Rails::Html::WhiteListSanitizer:

white_list_sanitizer = Rails::Html::WhiteListSanitizer.new
original = <<EOD
<div>
     some text
     <strong>text</strong>
     <p>other text</p>
     <img src="http://example.com" />
</div>
EOD

puts white_list_sanitizer.sanitize(original, tags: %w(p img))

输出:

some text
text
<p>other text</p>
<img src="http://example.com">

【讨论】:

  • 感谢您的回答。如果对我有帮助,我会尝试您的代码 - 我会将您的问题标记为正确。只用Nokogiri会更好(因为我是用它来准备html的),不过这种方式也是可以的
  • 您更喜欢非 Rails 解决方案吗?这实际上是一个围绕github.com/flavorjones/loofah gem 的轻量级包装器(它又使用 nokogiri)。如果你需要它,我可以只使用这个 gem 发布一些代码,让我知道。
  • 最近的 Rails 版本也直接提供了sanitize 作为助手。无需实例化任何类。
【解决方案2】:

如果您只想使用 Nokogiri,您可以遍历节点以递归方式删除所有不需要的标签:

def clean_node(node, whitelist)
  node.children.each do |n|
    clean_node(n, whitelist)
    unless whitelist.include?(n.name)
      n.before(n.children)
      n.remove
    end
  end
  node
end

def strip_tags(html, whitelist)
  whitelist += %w(text)
  node = Nokogiri::HTML(html).children.last
  clean_node(node, whitelist).inner_html
end

strip_tags 功能将删除所有不在白名单中的标签。对于你的例子,你会这样做:

original = <<HTML
<div>
     some text
     <strong>text</strong>
     <p>other text</p>
     <img src="http://example.com" />
</div>
HTML

puts strip_tags(original, %w(p img))

输出是:

 some text
 text
 <p>other text</p>
 <img src="http://example.com">

【讨论】:

  • 谢谢你的回答,但为什么我必须使用Nokogiri::XML?现在我正在使用Nokogiri::HTML...
  • 你是对的。我正在为任何 XML 编写通用解决方案。我在我的回答中将Nokogiri::XML 替换为Nokogiri::HTML,以针对html。
【解决方案3】:

我会这样做:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<div>
    some text
    <strong>text</strong>
    <p>other text</p>
    <img src="http://example.com" />
</div>
EOT

BLACKLIST = %w[strong div]

doc.search(BLACKLIST.join(',')).each do |node|
  node.replace(node.children)
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>
# >>     some text
# >>     text
# >>     <p>other text</p>
# >>     <img src="http://example.com">
# >> 
# >> </body></html>

基本上它在BLACKLIST 中查找节点并在文档中的任何位置找到它们,将它们替换为节点的children,从而有效地将子节点提升到其父节点。

【讨论】:

    【解决方案4】:

    您可以使用 xmp 标签来显示 HTML 标签。

    <div>
        some text
        <strong>text</strong>
        <xmp><p>other text</p>
        <img src="http://example.com" />
        </xmp>
    </div>
    

    HTML 元素“xmp”在开始和结束标记之间呈现文本,而不解释 HTML。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 2019-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-11
      相关资源
      最近更新 更多