如何使用Nokogiri :: XML :: Reader来解析大型XML文件?

nei*_*fws 12 ruby xml parsing nokogiri

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

我第一次尝试检索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
Run Code Online (Sandbox Code Playgroud)

这是我希望看到的:

["21714156", "21693734", "21692271", "21692260"]
Run Code Online (Sandbox Code Playgroud)

这是我实际看到的:

["21714156", "", "21693734", "", "21692271", "", "21692260", ""]
Run Code Online (Sandbox Code Playgroud)

似乎由于某种原因,我的代码为每个PMID实例找到或生成一个额外的空PMID标记.无论是那个还是inner_xml不像我想的那样工作.

如果有人能确认我的代码和数据生成显示的结果并建议我出错的地方,我将不胜感激.

mu *_*ort 19

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

node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
Run Code Online (Sandbox Code Playgroud)

结束活动将有

node.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT
Run Code Online (Sandbox Code Playgroud)

您看到的空字符串只是关闭事件的元素.请记住,使用SAX解析,您基本上是在树中走动,因此您需要第二个事件来告诉您何时返回并关闭元素.

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

reader.each do |node|
  if node.name == "PMID" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
    p << node.inner_xml
  end
end
Run Code Online (Sandbox Code Playgroud)

也许:

reader.each do |node|
  next if node.name      != 'PMID'
  next if node.node_type != Nokogiri::XML::Reader::TYPE_ELEMENT
  p << node.inner_xml
end
Run Code Online (Sandbox Code Playgroud)

或者其他一些变化.