3

我有一个要解析的大型 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 的另一种方法,以便我仍然可以包含属性信息。

4

4 回答 4

4

将 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 并直接导入它会更聪明。

于 2013-10-11T03:29:30.063 回答
4

主动支持 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

它将为您提供如下输出。

前输入 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"}}}
于 2015-04-03T11:11:18.643 回答
0

我实际上认为它是垃圾方法,它正在检查类型属性,如果它不返回散列,它将在方法 become_hash 中返回 true?返回假。这是 process_hash 方法中的最后一次检查。所以它会为类型属性返回 nil 并且不会为它构建散列。

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

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

我只是将其默认为 false,它对我有用,但可能并不适合所有人。

于 2016-07-29T17:45:29.357 回答
-2

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

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

于 2013-10-11T03:16:52.510 回答