解析/读取大型XML文件,占用内存最少

Nie*_*ian 7 ruby xml-parsing

我有一个非常大的XML文件(300mb),格式如下:

<data>
 <point>
  <id><![CDATA[1371308]]></id>
  <time><![CDATA[15:36]]></time>
 </point>
 <point>
  <id><![CDATA[1371308]]></id>
  <time><![CDATA[15:36]]></time>
 </point>
 <point>
  <id><![CDATA[1371308]]></id>
  <time><![CDATA[15:36]]></time>
 </point>
</data>
Run Code Online (Sandbox Code Playgroud)

现在我需要读取它并遍历point节点为每个节点做一些事情.目前我正在和Nokogiri这样做:

require 'nokogiri'
xmlfeed = Nokogiri::XML(open("large_file.xml"))
xmlfeed.xpath("./data/point").each do |item|
  save_id(item.xpath("./id").text)
end
Run Code Online (Sandbox Code Playgroud)

然而,这并不是非常有效,因为它解析了整个拥抱的一切,因此创造了巨大的内存占用(几GB).

有没有办法在块中执行此操作?如果我没弄错的话可能会被称为流式传输?

编辑

使用nokogiris sax解析器的建议答案可能没问题,但是当每个节点中有多个节点point需要从中提取内容并以不同方式处理时,它会变得非常混乱.我宁愿选择point一次访问一个,处理它,然后继续下一个"忘记"前一个,而不是返回大量的条目供以后处理.

Mar*_*mas 6

鉴于使用Nokogiri的Reader界面这个鲜为人知(但很棒)的要点,你应该能够做到这一点:

Xml::Parser.new(Nokogiri::XML::Reader(open(file))) do
  inside_element 'point' do
    for_element 'id' do puts "ID: #{inner_xml}" end
    for_element 'time' do puts "Time: #{inner_xml}" end
  end
end
Run Code Online (Sandbox Code Playgroud)

有人应该把它变成宝石,也许是我;)