Processando arquivo XML grande com o bloco libxml-ruby por pedaço
Eu gostaria de ler um grandeXML arquivo que contém mais de um milhão de pequenos registros bibliográficos (como<article>...</article>
) usando libxml em Ruby. Eu tentei a classe Reader em combinação com oexpand
método para ler o registro por registro, mas não tenho certeza se essa é a abordagem correta, pois meu código consome memória. Por isso, estou procurando uma receita como processar convenientemente registro por registro com uso constante de memória. Abaixo está meu loop principal:
File.open('dblp.xml') do |io|
dblp = XML::Reader.io(io, :options => XML::Reader::SUBST_ENTITIES)
pubFactory = PubFactory.new
i = 0
while dblp.read do
case dblp.name
when 'article', 'inproceedings', 'book':
pub = pubFactory.create(dblp.expand)
i += 1
puts pub
pub = nil
$stderr.puts i if i % 10000 == 0
dblp.next
when 'proceedings','incollection', 'phdthesis', 'mastersthesis':
# ignore for now
dblp.next
else
# nothing
end
end
end
A chave aqui é quedblp.expand
lê uma subárvore inteira (como um<article>
registro) e passa-o como um argumento para uma fábrica para processamento adicional. É este o caminho certo?
Dentro do método factory, uso a expressão XPath-like de alto nível para extrair o conteúdo dos elementos, como abaixo. Mais uma vez, isso é viável?
def first(root, node)
x = root.find(node).first
x ? x.content : nil
end
pub.pages = first(node,'pages') # node contains expanded node from dblp.expand