我是新手Ruby程序员,刚刚获得了转换巨大XML并将其保存到单独的JSON文件的新任务。例如:
<listing>
<id>abc12345</id>
<name>BCD</name>
<address>12 Main St</address>
</listing>
<listing>
<id>a1b2c3d4</id>
<name>XYZ</name>
<address>14 Main St</address>
</listing>
<listing>
<id>bcde45678</id>
<name>MNO</name>
<address>14 Broadway</address>
</listing>
我想将它保存到单个文件并使用id作为此示例中的文件名将是abc12345.json,a1b2c3d4.json和bcde45678.json,每个将包含以下内容:
{
"listing": {
"id": "bcde45678",
"name": "MNO",
"address": "14 Broadway"
}
}
是否有人可以帮助我解决这个问题。对于所有未来的帮助,我非常感激
答案 0 :(得分:2)
我假设您要将列表块作为JSON打印到单个文件。如果您可以访问'active_support / core_ext'和'nokogiri',并且您不太关心如何将XML转换为JSON,那么您可以这样做:
require 'active_support/core_ext'
require 'nokogiri'
xml = Nokogiri::XML(File.read "yourfile")
xml.search("//listing").each do |l|
filename = l.at_xpath("id").content
File.open(filename + '.json', 'w') do |file|
file.print Hash.from_xml(l.to_xml).to_json
end
end
答案 1 :(得分:0)
这是使用XMLSimple(或不是,你选择的毒药)和使用JSON的核心模块扩展的好例子:
require 'json/add/core'
require 'xmlsimple'
xml_files = [
'<listing>
<id>abc12345</id>
<name>BCD</name>
<address>12 Main St</address>
</listing>',
'<listing>
<id>a1b2c3d4</id>
<name>XYZ</name>
<address>14 Main St</address>
</listing>',
'<listing>
<id>bcde45678</id>
<name>MNO</name>
<address>14 Broadway</address>
</listing>'
]
xml_files.each do |xml|
obj = XmlSimple.xml_in(xml, :ForceArray => false)
File.write(obj['id'] + '.json', JSON.pretty_generate(obj))
end
创建三个文件:
a1b2c3d4.json:
{
"id": "a1b2c3d4",
"name": "XYZ",
"address": "14 Main St"
}
abc12345.json:
{
"id": "abc12345",
"name": "BCD",
"address": "12 Main St"
}
bcde45678.json:
{
"id": "bcde45678",
"name": "MNO",
"address": "14 Broadway"
}
我怀疑XMLSimple是基于Perl的XMLSimple,它读取XML文件并将其转换为本机对象。在这种情况下,它将创建XML的哈希,允许轻松访问<id>
标记的内容作为普通哈希键。 XMLSimple具有并且需要很多灵活性来将传入的XML解析为对象,因此我使用:ForceArray => false
标志对其进行了微调,这使得在为哈希键创建值时代码更加宽松。您需要花一些时间通过文档来了解它的选项。
JSON.pretty_generate(obj)
创建格式良好的输出。这会影响文件大小,但如果你有人必须阅读这些文件,那就没关系了。如果没有,请使用obj.to_json
生成更紧凑的输出,这将减少读取JSON文件时的I / O时间。
负责编写XML的各个块。
你没有说“巨大”意味着什么。在我的世界里,巨大的可以是多GB的文件,很可能是两位数。对于一个非常大的XML文件,我建议使用Nokogiri :: SAX来使用流处理并生成小的XML文件,类似于您的示例XML。然后你可以使用上面的代码迭代那些。
如果文件不是很大,但只是很大,那么让Nokogiri将整个文件解析为DOM并遍历<listing>
节点,并将它们输出到文件中。您提供的示例XML对于真正的XML文件无效,因为它缺少包含节点,因此,基于“固定”版本:
require 'json/add/core'
require 'nokogiri'
require 'xmlsimple'
xml_files =<<EOT
<xml_root>
<listing>
<id>abc12345</id>
<name>BCD</name>
<address>12 Main St</address>
</listing>
<listing>
<id>a1b2c3d4</id>
<name>XYZ</name>
<address>14 Main St</address>
</listing>
<listing>
<id>bcde45678</id>
<name>MNO</name>
<address>14 Broadway</address>
</listing>
</xml_root>
EOT
doc = Nokogiri::XML(xml_files)
xml_files = []
doc.search('listing').each do |listing|
xml_file = listing.at('id').text + '.xml'
xml_files << xml_file
File.write(xml_file, listing.to_xml)
end
xml_files.each do |file|
obj = XmlSimple.xml_in(File.read(file), :ForceArray => false)
File.write(obj['id'] + '.json', JSON.pretty_generate(obj))
end
运行后,这些文件存在,JSON文件的内容与相应的XML文件相关:
a1b2c3d4.json a1b2c3d4.xml abc12345.json abc12345.xml bcde45678.json bcde45678.xml
对于简单的XML,您可以省去XMLSimple,但对于大型XML块,以下可能会有点痛苦,但是,至少这是一个你可以选择的痛苦。这是没有SimpleXML的方法:
require 'json/add/core'
require 'nokogiri'
xml_files =<<EOT
<xml_root>
<listing>
<id>abc12345</id>
<name>BCD</name>
<address>12 Main St</address>
</listing>
<listing>
<id>a1b2c3d4</id>
<name>XYZ</name>
<address>14 Main St</address>
</listing>
<listing>
<id>bcde45678</id>
<name>MNO</name>
<address>14 Broadway</address>
</listing>
</xml_root>
EOT
doc = Nokogiri::XML(xml_files)
xml_files = []
doc.search('listing').each do |listing|
id, name, address = %w[id name address].map { |node| listing.at(node).content }
File.write(
id + '.json',
{
'id' => id,
'name' => name,
'address' => address
}.to_json
)
end