2011-07-13 24 views
12

Büyük (1 GB veya daha fazla) XML dosyalarını ayrıştırmak için Ruby's Nokogiri'yi kullanmaya çalışıyorum. Sadece 4 kayıt içeren available here kodunu daha küçük bir dosyada test ediyorum. Ubuntu 10.10'da Nokogiri sürüm 1.5.0, Ruby 1.8.7 kullanıyorum. SAX'ı çok iyi anlamadığımdan, başlangıç ​​noktası olan Nokogiri :: XML :: Reader'ı deniyorum.Büyük XML dosyalarını ayrıştırmak için Nokogiri :: XML :: Reader'ı nasıl kullanırım?

PMID etiketinin içeriği almak için ilk girişimi, şuna benzer:

İşte
["21714156", "21693734", "21692271", "21692260"] 

Aslında gördüğüm budur:

İşte
#!/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 

görmeyi ümit ne

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

Bazı nedenlerden ötürü, kodum her instanc için ekstra, boş bir PMID etiketi buluyor veya üretiyor gibi görünüyor PMID e. Ya bu ya da inner_xml düşündüğüm gibi çalışmıyor.

Kodumun ve verilerimin gösterilen sonucu oluşturduğunu ve nerede yanlış gittiğimi önerdiğini herkesin onaylayabilmesi için minnettar olurum.

+0

"Eski günlerde", birçok GB RAM ile ev sahipliği yapmadan önce, bir veya iki GB içeriğe yükleme yapmaktan endişeleniyorduk. Artık günler, mevcut tüm RAM'i tüketecek beklenmedik bir dosya alma riskleri olmadıkça, Nokogiri ve Ruby'yi tam boyutlu dosyaya çekmeyi deneyeceğim. Evet, 1GB çok fazla metin, ancak 8GB veya 16GB'lık bir sistemde hiçbir şey yok. Bellek ayırma ve çöp toplama hızını etkileyebileceğinden, yükleme ve işleme süresinin iyileştirilip etkilenmediğini görmek için izleyin; SAX modelinin kullanılması, bu durumda yardımcı olabilir, ancak yüklemeyi ve bir DOM gibi davranmayı tercih ederim. –

+0

Hız, RAM'den daha fazla meseledir. Örneğin, Hpricot (tercih edilen kitaplığım) ile paylaşılan bir sunucuda 96 GB RAM: 72 dakika ile ayrıştırma yapmayı denedim. – neilfws

+0

Birkaç yıldır Hpricot'u takip etmiyorum; Çok kullandım ama görkemli bir şekilde sürekli olarak patladığı bazı sorunlara rastladım ve Nokogiri bunu yapmadı, ben de değiştim ve geriye bakmadım. 72 dakika koşmak için uzun bir zaman gibi görünüyor. Profilciyi çalıştırmayı deneyebilir ve herhangi bir şey ortaya çıkarıp açmayacağını görebilirsiniz. Aksi halde, kodu ve XML'yi özetler ve buraya göndeririz ve işleri hızlandırmaya yardımcı oluruz. –

cevap

18

Akıştaki her öğe iki olay olarak gelir: biri öğeyi açmak için diğeri ise kapatmak için. Açılış etkinliği

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

sahip olacak ve kapanış olay

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

görüyorsanız boş dizeler olayları kapanış sadece öğesidir sahip olacaktır. SAX ayrıştırma ile temel olarak bir ağacın içinden geçtiğinizi hatırlayın, böylece bir olayı tekrar kapatıp kapatırken size söyleyeceğiniz ikinci etkinliğe ihtiyacınız vardır.

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

Veya belki:

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

Ya da bazı başka varyasyonu

Muhtemelen bunun gibi daha fazla bir şey istiyorum.

+0

İlk çözümünüz çalışıyor; çok teşekkürler. – neilfws

+0

neden bunu denemiyorsunuz - https://github.com/amolpujari/reading-huge-xml –

İlgili konular