Изначально использовал Rexml и сразу стало понятно что при парсинге файлов больше 1мб парсер никуда не годиться. Файл объемом в 10мб он парсил две-три минуты, при этом съедая 400 и больще мб ОЗУ.
Далее попробовал hpricot, но и он не показал особых улучшений. Примерно все стало на 15-20% быстрее, но это все равно долго.
В итоге я добрался до nokogiri, вот он меня приятно порадовал. Файлы размером в 10мб парсились за неполные 2 секунды и памяти при это почти не съедал. Nokogiri для парсинга использует XPath соответственно код получается довольно наглядным и простым. Ниже пример:
xml = File.read(filename)
doc = Nokogiri::XML(xml)
self.page_height = doc.xpath('//VisioDocument/Pages/Page/PageSheet/PageProps')
.search('.//PageHeight').inner_html
doc.xpath('//VisioDocument/Pages/Page/Shapes/Shape').each do |s|
shape = {}
shape.store(:master_id, s.attributes['Master'].text) if s.attributes['Master']
if line_object?(s)
xform1d = s.at('.//XForm1D')
shape.store(:x, xform1d.at('.//BeginX').inner_html)
shape.store(:y, xform1d.at('.//BeginY').inner_html)
shape.store(:to_x, xform1d.at('.//EndX').inner_html)
shape.store(:to_y, xform1d.at('.//EndY').inner_html)
self.line_shapes << shape
end
end
Возможно разница в производительности связана с неправильными использованием библиoтек, но я старался делать все по оригинальной документации.