2011-07-13 28 views
12

Tôi đang cố gắng sử dụng Nokogiri của Ruby để phân tích các tệp XML lớn (1 GB hoặc hơn). Tôi đang thử nghiệm mã trên một tệp nhỏ hơn, chỉ chứa 4 bản ghi available here. Tôi đang sử dụng phiên bản Nokogiri 1.5.0, Ruby 1.8.7 trên Ubuntu 10.10. Vì tôi không hiểu SAX rất tốt, tôi đang thử Nokogiri :: XML :: Reader để bắt đầu.Làm cách nào để sử dụng Nokogiri :: XML :: Reader để phân tích các tệp XML lớn?

nỗ lực đầu tiên của tôi, để lấy nội dung của thẻ PMID, trông như thế này:

#!/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 

Dưới đây là những gì tôi hy vọng sẽ nhìn thấy:

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

Đây là những gì tôi thực sự thấy:

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

Dường như vì một số lý do, mã của tôi đang tìm kiếm hoặc tạo ra một thẻ PMID trống, bổ sung cho mọi instanc e của PMID. Hoặc là hoặc inner_xml không hoạt động như tôi nghĩ.

Tôi rất biết ơn nếu có ai có thể xác nhận rằng mã và dữ liệu của tôi tạo kết quả được hiển thị và đề xuất nơi tôi đang gặp sự cố.

+0

Trong "ngày cũ", trước khi chúng tôi có máy chủ lưu trữ có nhiều GB RAM, chúng tôi đã lo lắng về việc tải xuống một hoặc hai GB nội dung. Bây giờ ngày, trừ khi có những rủi ro khi nhận được một tập tin bất ngờ sẽ tiêu thụ tất cả RAM có sẵn, tôi sẽ cố gắng để Nokogiri và Ruby kéo tập tin đầy đủ. Yeah, 1GB là rất nhiều văn bản, nhưng trên một hệ thống 8GB hoặc 16GB nó không có gì. Xem để xem thời gian tải và xử lý có cải thiện hay bị ảnh hưởng khi cấp phát bộ nhớ và thu gom rác có thể ảnh hưởng đến tốc độ hay không; Sử dụng mô hình SAX có thể giúp trong trường hợp đó, nhưng tôi thích tải nó và xử lý nó như một DOM. –

+0

Tốc độ là vấn đề hơn RAM. Ví dụ, tôi đã thử phân tích cú pháp với Hpricot (thư viện ưa thích của tôi) trên một máy chủ chia sẻ với RAM 96 GB: 72 phút. – neilfws

+0

Tôi đã không theo dõi Hpricot trong một vài năm; Tôi đã sử dụng nó rất nhiều nhưng gặp phải một số vấn đề mà nó phát nổ một cách nhất quán trong một thời trang huy hoàng, và Nokogiri thì không, vì vậy tôi đã chuyển sang và không nhìn lại. 72 phút có vẻ như là một thời gian dài để chạy. Bạn có thể thử chạy profiler và xem nó có tiết lộ gì không. Nếu không, tóm tắt mã và XML và đăng nó ở đây và chúng tôi sẽ cố gắng giúp tăng tốc mọi thứ. –

Trả lời

18

Mỗi phần tử trong luồng đi qua dưới dạng hai sự kiện: một thành phần để mở phần tử và một để đóng phần tử đó. Sự kiện khai mạc sẽ có

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

và lễ bế mạc sẽ có

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

Các chuỗi rỗng bạn nhìn thấy chỉ là những yếu tố đóng kiện. Hãy nhớ rằng với phân tích cú pháp SAX, về cơ bản bạn đang đi qua một cái cây, do đó bạn cần sự kiện thứ hai để cho bạn biết khi nào bạn sẽ sao lưu và đóng một phần tử.

Bạn có thể muốn một cái gì đó như thế này:

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

Hoặc có lẽ:

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

Hoặc một số biến thể khác về điều đó.

+0

Giải pháp đầu tiên của bạn hoạt động; cảm ơn rất nhiều. – neilfws

+0

tại sao không thử điều này - https://github.com/amolpujari/reading-huge-xml –

Các vấn đề liên quan