Я бы хотел прочитать большой XML файл, который содержит более миллиона небольших библиографических записей (например, <article>...</article>
) с использованием libxml в Ruby. Я пробовал класс Reader в сочетании с методом expand
для чтения записи по записи, но я не уверен, что это правильный подход, так как мой код потребляет память. Следовательно, я ищу рецепт, как удобно обрабатывать записи по записи с постоянным использованием памяти. Ниже мой основной цикл:
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
Ключевым моментом здесь является то, что dblp.expand
читает целое поддерево (например, запись <article>
) и передает его в качестве аргумента фабрике для дальнейшей обработки. Это правильный подход?
Внутри фабричного метода я использую высокоуровневое XPath-подобное выражение для извлечения содержимого элементов, как показано ниже. Опять же, это жизнеспособно?
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