在将XML转换为Ruby哈希时保持属性

我有一个我想要解析的大型XML文档。 在本文档中,许多标签具有不同的属性。 例如:

 Do Re Mi  

目前,我通过要求'active_support/core_ext/hash'来使用Rail的散列解析库。

当我将其转换为哈希时,它会删除属性。 它返回:

 {"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 = <  Do Re Mi   Blah blah blah   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时,代码将循环遍历所有节点,并提取信息,定义类的实例,并将其附加到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输入XML

 xml = ' Do Re Mi ' Hash.from_xml(xml) 

输出将是

 {"album"=>{"song_name"=>{"type"=>"published", "__content__"=>"Do Re Mi"}}} 

我实际上认为它是垃圾方法,它正在检查类型属性,如果它没有返回一个哈希值,它将返回true,在方法的变量中是什么? 返回false。 这是process_hash方法中的最后一次检查。 因此它将为type属性返回nil,并且不会为它构建哈希。

对于那些感兴趣的人我正在谈论的是活跃的支持gem active_support / core_ext / hash / conversions.rb

module ActiveSupport class XMLConverter private def garbage?(value) false end end end

我只是默认它是假的,它对我有用,但它可能并不适合所有人。

正如您在上面提到的问题一样, Nokogiri是(简短的)答案。

如果您可以提供一些示例代码,有人可能会提出更好的答案。