我有一个大型XML文档,我正在寻找解析。在本文档中,许多标签具有不同的属性。例如:
<album>
<song-name type="published">Do Re Mi</song-name>
</album>
目前,我正在使用 Rail 的哈希解析库,需要 'active_support/core_ext/hash'
.
当我将其转换为哈希时,它会删除属性。它返回:
{"album"=>{"song-name"=>"Do Re Mi"}}
如何维护这些属性,在本例中为 type="published"
属性?
这似乎以前在"转换为带有from_xml的哈希时如何使用XML属性?"中被问过,没有确凿的答案,但那是从2010年开始的,我很好奇从那时起情况是否发生了变化。或者,我想知道您是否知道解析此 XML 的替代方法,以便我仍然可以包含属性信息。
将 XML 转换为哈希不是一个好的解决方案。留下的哈希比原始 XML 更难分析。此外,如果 XML 太大,您将留下一个无法放入内存且无法处理的哈希,而原始 XML 可以使用 SAX 解析器进行分析。
假设文件在加载时不会淹没您的内存,我建议使用 Nokogiri 来解析它,执行以下操作:
require 'nokogiri'
class Album
attr_reader :song_name, :song_type
def initialize(song_name, song_type)
@song_name = song_name
@song_type = song_type
end
end
xml = <<EOT
<xml>
<album>
<song-name type="published">Do Re Mi</song-name>
</album>
<album>
<song-name type="unpublished">Blah blah blah</song-name>
</album>
</xml>
EOT
albums = []
doc = Nokogiri::XML(xml)
doc.search('album').each do |album|
song_name = album.at('song-name')
albums << Album.new(
song_name.text,
song_name['type']
)
end
puts albums.first.song_name
puts albums.last.song_type
哪些输出:
Do Re Mi
unpublished
代码首先定义一个合适的对象,用于保存所需的数据。当 XML 解析为 DOM 时,代码将遍历所有<album>
节点,并提取信息,定义类的实例,并将其追加到albums
数组。
运行后,您将拥有一个可以行走的数组,并处理每个项目,将其存储到数据库中,或者根据需要对其进行操作。但是,如果您的目标是将该信息插入数据库,则让 DBM 读取 XML 并直接导入它会更明智。
这是主动支持 XMLConverter 类的问题请将以下代码添加到任何初始值设定项文件中。
module ActiveSupport
class XMLConverter
private
def become_content?(value)
value['type'] == 'file' || (value['__content__'] && (value.keys.size == 1 && value['__content__'].present?))
end
end
end
它将为您提供如下所示的输出。
Ex Input XML
xml = '<album>
<song-name type="published">Do Re Mi</song-name>
</album>'
Hash.from_xml(xml)
输出将是
{"album"=>{"song_name"=>{"type"=>"published", "__content__"=>"Do Re Mi"}}}
我实际上认为这是垃圾方法,它正在检查类型属性,如果它不返回哈希,它将返回 true,该方法中的 become_hash? 返回 false。这是process_hash方法中的最后一次检查。因此,它将为类型属性返回 nil,并且不会为其构建哈希。
对于那些感兴趣的人,我所说的是在活动支持gem active_support/core_ext/hash/conversions.rb
module ActiveSupport
class XMLConverter
private
def garbage?(value)
false
end
end
end
我只是默认为 false,它对我有用,但可能并不适合所有人。
就像你上面链接的问题一样,Nokogiri 是(简短的(答案。
如果你能提供一些示例代码,有人可能会想出更好的答案。