Какой самый простой способ игнорировать пустые узлы с помощью Nokogiri :: XML :: Builder - PullRequest
2 голосов
/ 22 марта 2011

Итак, допустим, у меня есть шаблон конструктора, подобный следующему:

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

Если бы feed и description были nil, он мог бы вывести:

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

Я бы предпочел, чтобы он полностью игнорировал ноль. Какой лучший способ добиться этого?

Желаемый выход:

<?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 #?

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

Ответы [ 2 ]

1 голос
/ 06 января 2015

Я знаю, что этот вопрос старый и уже имеет ответ, но, потратив немного времени на его выяснение, быстрое решение этой проблемы (хотя, вероятно, неэффективное) заключается в Nokogiri::XML::Node#traverse.

После того, как вы создали свой документ, вам просто нужно один раз пройти его, проверяя наличие пустых тегов и удаляя их по ходу, например так:

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

Обратите внимание, что #traverse возвращаетрезультат последней операции, поэтому обязательно верните что-нибудь (ваш компоновщик или XML-строку) после того, как вы закончите обход.

1 голос
/ 23 марта 2011

Это зависит от того, сколько полей у вас действительно есть, но я предполагаю, что вы уже совершаете ошибку, вручную набирая каждую из них.

Если порядок не имеет значения, просто используйте хеш. (в противном случае используйте 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

кажется, работает.

Это не красиво, но, по крайней мере, вам просто нужно определить свои поля и значения в одном месте. Желательно объектный метод?

...