require 'nokogiri'
doc = Nokogiri::XML "<root>
<a>foo<c>bar</c></a>
<b>jim<d>jam></d></b>
<a>more</a>
<x>no no no</x>
</root>"
doc.css("a, b").each {|o| p o.to_s}
# "<a>foo<c>bar</c></a>"
# "<a>more</a>"
# "<b>jim<d>jam></d></b>"
如何使标签保持原来的顺序?或者也删除嵌套标签?
你可能想看看白名单/黑名单/擦洗宝石。我想到了消毒和丝瓜络。
来自消毒剂的描述:
给定一个可接受的元素和属性列表,Sanitize将从字符串中删除所有不可接受的HTML。
From Loofah的描述:
丝瓜络擅长HTML消毒(XSS预防)。它包括一些很好的HTML杀毒器,这些杀毒器基于HTML5lib的白名单,所以它很可能不会降低代码的安全性。(这些陈述没有经过Netexperts的评估。)
在任何一种情况下,他们将节省你重新发明轮子。
require 'nokogiri'
doc = Nokogiri::XML "
<root>
<a>foo<c>bar</c></a>
<b>jim<d>jam></d></b>
<a>more</a>
<x>no no no</x>
</root>"
doc.xpath('root//*[name()!="a"][name()!="b"]').remove
puts doc
#=> <?xml version="1.0"?>
#=> <root>
#=> <a>foo</a>
#=> <b>jim</b>
#=> <a>more</a>
#=>
#=> </root>
如果这只是顺序问题,并且您需要隔离的标签都不是嵌套的,那么在Nokogiri中使用XPath而不是CSS选择器应该会以与文档中相同的顺序返回标签:
doc.xpath("//a | //h3").each { |o| puts o }
我不确定这种行为是否在Nokogiri的任何规范中,所以你可能要小心,但根据我的经验,这是真的。
当然,如果你想要的标签是嵌套的,你可能需要定义"删除除某些标签外的所有标签"的含义(例如,存在于未删除标签及其内容中的已删除标签及其内容会发生什么,等等)。
如果您的需求非常复杂,以至于XPath查询无法满足您的需求,那么您可能需要使用doc.root.children
之类的东西"遍历DOM",并递归地检查每个节点的子节点。