Как использовать 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
не работает, как я думал.
Буду признателен, если кто-нибудь сможет подтвердить, что мой код и данные генерируют показанный результат и предлагают, где я ошибаюсь.
Ответы
Ответ 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
Или некоторые другие варианты.