2011-07-13 102 views
12

我正在尝试使用Ruby的Nokogiri来解析大型(1 GB或更多)XML文件。我在一个较小的文件上测试代码,只包含4条记录available here。我在Ubuntu 10.10上使用Nokogiri版本1.5.0,Ruby 1.8.7。由于我不太了解SAX,我正在尝试使用Nokogiri :: XML :: Reader来启动。如何使用Nokogiri :: XML :: Reader来解析大型XML文件?

我第一次尝试,检索PMID标签的内容,看起来像这样:

#!/usr/bin/ruby 
require "rubygems" 
require "nokogiri" 

file = ARGV[0] 
reader = Nokogiri::XML::Reader(File.open(file)) 
p  = [] 
reader.each do |node| 
    if node.name == "PMID" 
    p << node.inner_xml 
    end 
end 

puts p.inspect 

这是我希望看到:

["21714156", "21693734", "21692271", "21692260"] 

这是我居然看到:

["21714156", "", "21693734", "", "21692271", "", "21692260", ""] 

似乎由于某种原因,我的代码正在为每个实例找到或生成一个额外的空PMID标记PMID的。无论是或inner_xml不工作,因为我认为。

如果有人可以确认我的代码和数据生成显示的结果并提示我出错的位置,我将不胜感激。

+0

在“过去的日子”里,在我们拥有很多RAM的主机之前,我们曾经担心加载一个或两个GB内容。现在,除非有接收意外文件的风险,否则会消耗所有可用的RAM,否则我会尝试让Nokogiri和Ruby拉入完整大小的文件。是的,1GB是很多文本,但是在8GB或16GB系统上没有任何内容。观察内存分配和垃圾收集是否会影响速度,从而加载和处理时间是否改善或受到影响;在这种情况下使用SAX模型可以提供帮助,但是我更喜欢将其加载并像DOM一样对待它。 –

+0

速度比RAM更多的问题。例如,我尝试使用96 GB RAM的共享服务器上的Hpricot(我的首选库)解析:72分钟。 – neilfws

+0

我一直未遵循Hpricot一两年;我用了很多,但遇到了一些以光荣的方式持续爆炸的问题,而Nokogiri没有,所以我转而不回头。 72分钟似乎很长时间才能运行。您可以尝试运行分析器并查看它是否显示任何内容。否则,总结一下代码和XML并将其发布到此处,我们将尽力帮助加快速度。 –

回答

18

流中的每个元素都以两个事件发生:一个用于打开元素,另一个用于关闭它。开幕活动将有

node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT 

和闭幕活动将有

node.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT 

你看到的空字符串是刚刚闭幕的事件的元素。请记住,在SAX解析中,基本上你正在步行穿过一棵树,所以你需要第二个事件来告诉你什么时候你要回去并关闭一个元素。

你可能想要更多的东西是这样的:

reader.each do |node| 
    if node.name == "PMID" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT 
    p << node.inner_xml 
    end 
end 

或许:

reader.each do |node| 
    next if node.name  != 'PMID' 
    next if node.node_type != Nokogiri::XML::Reader::TYPE_ELEMENT 
    p << node.inner_xml 
end 

或者在其他一些变化。

+0

您的第一个解决方案有效;非常感谢。 – neilfws

+0

为什么不试试这个 - https://github.com/amolpujari/reading-huge-xml –