Резюме
Я использую Ruby (ruby 2.1.2p95 (2014-05-08) [x86_64-linux-gnu]
на моей машине, ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
в производственной среде) и Nori для преобразования XML-документа (первоначально обработанного с помощью Nokogiri для некоторой проверки) в Ruby Hash, но позже я обнаружил, что Nori отбрасывает атрибуты самых глубоких элементов XML.
Сведения о выпуске и воспроизведение
Для этого я использую код, похожий на следующий:
xml = Nokogiri::XML(File.open('file.xml')) { |config| config.strict.noblanks }
hash = Nori.new.parse xml.to_s
Код обычно работает по назначению, за исключением одного случая. Всякий раз, когда Нори анализирует XML-текст, он отбрасывает атрибуты элемента из листовых элементов (т.е. Элементов, у которых нет дочерних элементов).
Например, следующий документ:
<?xml version="1.0"?>
<root>
<objects>
<object>
<fields>
<id>1</id>
<name>The name</name>
<description>A description</description>
</fields>
</object>
</objects>
</root>
... преобразуется в ожидаемый хэш (некоторый вывод опущен для краткости):
irb(main):066:0> xml = Nokogiri::XML(txt) { |config| config.strict.noblanks }
irb(main):071:0> ap Nori.new.parse(xml.to_s), :indent => -2
{
"root" => {
"objects" => {
"object" => {
"fields" => {
"id" => "1",
"name" => "The name"
"description" => "A description"
}
}
}
}
}
Проблема возникает, когда атрибуты элементов используются для элементов без детей. Например, следующий документ не преобразуется, как ожидалось:
<?xml version="1.0"?>
<root>
<objects>
<object id="1">
<fields>
<field name="Name">The name</field>
<field name="Description">A description</field>
</fields>
</object>
</objects>
</root>
Тот же Nori.new.parse(xml.to_s)
, отображаемый awesome_print
, показывает, что атрибуты самых глубоких элементов <field>
отсутствуют:
irb(main):131:0> ap Nori.new.parse(xml.to_s), :indent => -2
{
"root" => {
"objects" => {
"object" => {
"fields" => {
"field" => [
[0] "The name",
[1] "A description"
]
},
"@id" => "1"
}
}
}
}
У Хэша только свои значения как список, который я не хотел. Я ожидал, что элементы <field>
сохраняют свои атрибуты так же, как их родительские элементы (например, см. @id="1"
для <object>
), а не для того, чтобы их атрибуты были отрублены.
Даже если документ изменен, чтобы выглядеть следующим образом, он все равно не работает должным образом:
<?xml version="1.0"?>
<root>
<objects>
<object id="1">
<fields>
<Name type="string">The name</Name>
<Description type="string">A description</Description>
</fields>
</object>
</objects>
</root>
Он создает следующий хэш:
{
"root" => {
"objects" => {
"object" => {
"fields" => {
"Name" => "The name",
"Description" => "A description"
},
"@id" => "1"
}
}
}
}
Что не хватает атрибутов type="whatever"
для каждого ввода поля.
Поиск в конечном итоге приведет меня к Issue # 59 с последним сообщением (с августа 2015 года), в котором он не может "найти ошибку" в коде Nori. "
Заключение
Итак, мой вопрос: Кто-нибудь из вас знает, как работать вокруг проблемы Nori (например, возможно, настройка), которая позволила бы мне использовать мою исходную схему (то есть та, атрибуты в элементах без детей)? Если да, можете ли вы поделиться фрагментом кода, который будет обрабатывать это правильно?
Мне пришлось перепроектировать мою XML-схему и изменить код примерно три раза, чтобы заставить ее работать, поэтому, если есть способ заставить Nori вести себя, и я просто не знаю об этом, я бы хотел знать, что это такое.
Я хотел бы избежать установки большего количества библиотек в максимально возможной степени, чтобы это нормально работало с структурой схемы, которую я первоначально хотел использовать, но я открыт для возможности, если она доказала свою эффективность. (Мне придется снова заново пересчитать код...) Рамки, безусловно, слишком завышены для этого, поэтому, пожалуйста, не предлагайте Ruby on Rails или аналогичный полный -статические решения.
Обратите внимание, что мое текущее решение, основанное на (неохотно) переработанной схеме, работает, но сложнее сгенерировать и обработать, чем исходное, и я хотел бы вернуться к более простой/более мелкой схеме.