【发布时间】:2016-06-14 14:06:18
【问题描述】:
总结
我正在使用 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 哈希,但后来我发现 Nori正在删除最深的 XML 元素的属性。
问题详情及复现
为此,我使用类似于以下的代码:
xml = Nokogiri::XML(File.open('file.xml')) { |config| config.strict.noblanks }
hash = Nori.new.parse xml.to_s
代码通常按预期工作,除了一种情况。每当 Nori 解析 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> 元素像它们的父元素一样保留它们的属性(例如,对于 <object>,请参阅 @id="1"),而不是因为它们的属性被截断。
即使将文档修改为如下所示,它仍然无法按预期工作:
<?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 年 8 月开始)说他无法“找到 Nori 代码中的错误”。
结论
所以,我的问题是:你们中是否有人知道一种解决 Nori 问题的方法(例如,可能是一种设置),它允许我使用我的原始模式(即与没有子元素的元素中的属性)?如果是这样,您能否分享一个可以正确处理此问题的代码 sn-p?
我不得不重新设计我的 XML 架构并更改代码大约 3 次才能使其正常工作,所以如果有办法让 Nori 正常工作,而我根本不知道,我想知道它是什么。
我想避免尽可能多地安装更多库,只是为了让它与我最初想要使用的架构结构正常工作,但如果它被证明,我愿意接受去工作。 (我不得不再次重构代码...)为此,框架肯定是矫枉过正,所以请:不建议Ruby on Rails 或类似的全栈解决方案。
请注意,我当前的解决方案基于(不情愿地)重新设计的架构,正在运行,但它的生成和处理比原来的更复杂,我想回到更简单/更浅的架构。
【问题讨论】:
-
我建议创建自己的递归方法“xml to json”。你可以用 nokogiri 做到这一点。
-
@andoke:如果您能详细说明这一点,我将不胜感激,也许可以提供包含概念验证代码的答案。如果我要在工作中花更多时间在这方面,并重构 XML 文档,我需要知道它确实可以工作,而不是死胡同。
-
Nori 中有一个针对这个错误的 GitHub 问题:issue #59 “It ignores attributes when a child is a text node”
-
@RoryO'Kane:谢谢,但在发布问题之前我已经遇到过这个问题,我什至在原帖中也提到过。对于这篇文章,我想看看是否有人知道该问题的解决方法。