使用Nokogiri从空标签中递归清理XML文档?
我有一个嵌套的XML文档,如下所示:
test description 12345
我需要删除所有空的XML节点,如和
。
我最终得到了类似的东西:
doc = Nokogiri::XML::DocumentFragment.parse <<-EOXML test description 12345 EOXML phone = doc.css("phone") phone.children.each do | child | child.remove if child.inner_text == '' end
上面的代码只删除了第一个空标记,例如 。 我无法进入嵌套块。 我想我需要一些递归策略。 我仔细阅读了Nokogiri文档,并检查了很多例子,但我还没有找到解决方案。
我怎样才能解决这个问题?
我正在使用Ruby 1.9.3和Nokogiri 1.5.10。
您应该能够使用xpath "/phone//*[not(text())]"
找到没有任何文本的所有节点。
require 'nokogiri' doc = Nokogiri::XML::Document.parse <<-EOXML test description 12345 EOXML doc.xpath("/phone//*[not(text())]").remove puts doc.to_s.gsub(/\n\s*\n/, "\n") #=> #=> #=> test #=> description #=> #=> 12345 #=> #=>
具有不同方法的后来者,希望增加额外的洞察力。 这种方法消除了恼人的额外新行,并为您提供了保留具有值设置属性的空字段的选项。
require 'nokogiri' doc = Nokogiri::XML::Document.parse <<-EOXML test description 12345 EOXML def traverse_and_clean(kid) kid.children.map { |child| traverse_and_clean(child) } kid.remove if kid.content.blank? end traverse_and_clean(doc)
产量
test description 12345
如果你发现自己处于一个特殊的情况,需要保留一些具有某些属性设置的空字段。 您所要做的就是稍微更改traverse_and_clean
方法:
def traverse_and_clean(kid) kid.children.map { |child| traverse_and_clean(child) } kid.remove if kid.content.blank? && kid.attributes.blank? end
require 'nokogiri' doc = Nokogiri::XML::Document.parse <<-EOXML test description 12345 EOXML nodes = doc.xpath("//phone//*[not(text())]") nodes.each{|n| n.remove if n.elem? } puts doc
产量
test description 12345
与@ JustinKo的回答类似,仅使用CSS选择器:
require 'nokogiri' doc = Nokogiri::XML(< test description 12345 EOT doc.search(':empty').remove puts doc.to_xml
看看它做了什么:
test description 12345
Nokogiri实现了很多jQuery的选择器,所以总是值得看看这些扩展可以做什么。