Подтвердить что ты не робот

Как использовать Nokogiri:: XML:: Reader для анализа больших XML файлов?

Я пытаюсь использовать Ruby Nokogiri для анализа больших (1 ГБ или более) XML файлов. Я тестирую код на меньшем файле, содержащем только 4 записи которые можно найти здесь. Я использую версию Nokogiri версии 1.5.0, Ruby 1.8.7 на Ubuntu 10.10. Поскольку я не очень хорошо разбираюсь в 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

Вот что я надеялся увидеть:

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

Вот что я на самом деле видел:

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

Кажется, что по какой-то причине мой код находит или генерирует дополнительный пустой тег PMID для каждого экземпляра PMID. Либо это, либо inner_xml не работает, как я думал.

Буду признателен, если кто-нибудь сможет подтвердить, что мой код и данные генерируют показанный результат и предлагают, где я ошибаюсь.

4b9b3361

Ответ 1

Каждый элемент в потоке проходит через два события: один для открытия элемента и один для его закрытия. Событие открытия будет

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

Или некоторые другие варианты.