使用Nokogiri :: XML :: Builder忽略空节点的最简洁方法是什么

时间:2011-03-22 13:24:27

标签: ruby xml nokogiri dsl

因此,假设我有一个类似于以下内容的构建器模板:

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
  xml.environment do |environment|
    environment.title title
    environment.feed feed
    environment.status status
    environment.description description
    # many many more
  end
end
builder.to_xml

如果feeddescriptionnil,则可以输出:

<?xml version="1.0" encoding="UTF-8"?>
<environment>
  <title>title</title>
  <feed/>
  <status>status</status>
  <description/>
</environment>

我宁愿完全忽视nils。 实现这一目标的最佳方式是什么?

所需的输出:

<?xml version="1.0" encoding="UTF-8"?>
<environment>
  <title>title</title>
  <status>status</status>
</environment>

当前解决方案:

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
  xml.environment do |environment|
    environment.title title if title
    environment.feed feed if feed
    environment.status status if status
    environment.description description if description
    # many many more
  end
end
builder.to_xml

有更清洁的方式吗?

这对Builder#initialize来说是否是一个有用的选项?

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8', :empty_nodes => false)

2 个答案:

答案 0 :(得分:1)

这取决于你真正有多少个字段, 但我的建议是,你已经通过手动输入每个错误而犯了错误。

如果顺序无关紧要,只需使用哈希。 (否则使用OrderedHash)

fields = {
  :title => title,
  :feed  => feed,
  :status => status,
  :description => description,
  # many more
}

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
  xml.environment do |environment|
    fields.each do |field_name, field_value|
      if field_value
        environment.send(field_name, field_value)
      end
    end
  end
end
builder.to_xml

似乎有效。

它不漂亮,但至少你只需要在一个地方定义你的字段和值。 优选对象方法?

答案 1 :(得分:1)

我知道这个问题已经过时并且已经有了答案,但是只花了一点时间来解决这个问题,这个问题的快速解决方案(尽管可能不具备性能)位于Nokogiri::XML::Node#traverse

一旦您构建了文档,您只需要遍历一次,检查空标记并随时删除它们,如下所示:

builder.doc.traverse do |node|
  node.remove if node.element? && node.text == ""
end

请注意#traverse会返回上一次操作的结果,因此请确保在完成遍历后返回一些内容(您的构建器或XML字符串)。