【发布时间】:2023-04-05 03:44:01
【问题描述】:
我有一个项目,它需要大量 XML 数据并将其传递给 Nokogiri,最终将每个元素添加到输出到 YAML 文件的哈希中。
这在 XML 数据集包含重复键之前有效。
示例数据:
<document>
<form xmlns="">
<title>
<main-title>Foo</main-title>
</title>
<homes>
<home>
<home-name>home 1</home-name>
<home-price>10</home-price>
</home>
<home>
<home-name>home 2</home-name>
<home-price>20</home-price>
</home>
</homes>
</form>
</document>
在homes 元素中我可以有多个家,但是每个home 总是包含不同的内容。
这些数据最终应该输出这样的结构:
title:
main-title: Foo
homes:
home:
home-name: home 1
home-price: 10
home:
home-name: home 2
home-price: 20
然而我得到的只是homes中的最后一个元素
title:
main-title: Foo
homes:
home:
home-name: home 2
home-price: 20
我相信这是因为,在将每个元素添加到散列时,如果它已经存在,它将简单地覆盖键,因此总是给我最后一个键。
这是用于将元素附加到哈希的代码:
def map_content(nodes, content_hash)
nodes.map do |element|
case element
when Nokogiri::XML::Element
child_content = map_content(element.children, {})
content_hash[element.name] = child_content unless child_content.empty?
when Nokogiri::XML::Text
return element.content
end
end
content_hash
end
我相信
content_hash[element.name] = child_content
是罪魁祸首,但是此代码创建了具有这些类型的重复键的类似 YAML 文件,并且我想保留该功能,因此我不想简单地向数据哈希添加唯一键,因为这意味着我需要修改许多方法并更新它们从 YAML 文件中提取数据的方式。
我阅读了有关 compare_by_identity 的信息,但不确定我将如何实现它。
我尝试使用compare_by_identity,但它只会生成一个空的 YAML 文件,所以它可能正在生成哈希但无法将其写入 YAML 文件?
def map_content(nodes, content_hash)
content_hash = content_hash.compare_by_identity
nodes.map do |element|
case element
when Nokogiri::XML::Element
child_content = map_content(element.children, {})
content_hash[element.name] = child_content unless child_content.empty?
when Nokogiri::XML::Text
return element.content
end
end
content_hash
end
end
【问题讨论】:
-
拥有一个“homes”键并将其下方的所有内容放在一个数组中怎么样?您建议的结构将不起作用,因为在将其加载回您的应用程序时,它会给您相同的结果(只有最后一个 :home 键)。
-
嗯我试图不修改当前的结构,但这可能是唯一的方法。
-
您想要的 YAML 输出是不可能的。 YAML 在解析时会产生带有重复键的哈希,您已经发现这是不可能的。您必须使用哈希数组。
标签: ruby xml nokogiri ruby-hash