Как я могу прочитать большой XML-файл в Ruby с помощью libxml-ruby?
Мы используем libxml-ruby уже пару лет. Это фантастично для файлов размером 30 МБ или меньше, но оно ЗАТРАГИВАЕТСЯ ошибками сегмента. Никто в проекте, похоже, не хочет их исправлять, только обвиняя их в стороннем программном обеспечении. Это их прерогатива, конечно, это бесплатно.
Тем не менее, я до сих пор не могу прочитать эти большие файлы. Полагаю, я мог бы написать какой-нибудь жалкий взлом, чтобы разбить их на более мелкие файлы, но я бы хотел этого избежать. У кого-нибудь еще есть опыт чтения очень больших XML-файлов в Ruby?
4 ответа
Я бы порекомендовал посмотреть на синтаксический анализатор SAX XML. Они предназначены для обработки огромных файлов. Мне не нужно было время от времени, но они довольно просты в использовании; Когда он читает XML-файл, он передает вашему коду различные события, которые вы перехватываете и обрабатываете с помощью своего кода.
На сайте Nokogiri есть ссылка на SAX Machine, которая основана на Nokogiri, так что это был бы другой вариант. В любом случае, Nokogiri очень хорошо поддерживается и используется многими людьми, включая меня, для всех HTML и XML, которые я анализирую. Он поддерживает синтаксический анализ как DOM, так и SAX, позволяет использовать средства доступа CSS и XPath и использует libxml2 для своего синтаксического анализа, поэтому он быстрый и основан на стандартной библиотеке синтаксического анализа.
При загрузке больших файлов, независимо от того, являются они XML-файлами или нет, вы должны начать разбирать фрагменты за раз (в данном случае это называется потоковой передачей), а не загружать весь файл в память.
Я настоятельно рекомендую прочитать эту статью о парсерах. Использование этой техники позволит вам с большей легкостью читать этот файл, а не загружать все файлы сразу в память.
Спасибо всем за ваш превосходный вклад. Я смог решить мою проблему, посмотрев на Обработка большого XML-файла с помощью фрагмента libxml-ruby.
Ответ состоял в том, чтобы избежать использования:
reader.expand
и вместо этого использовать:
reader.read
или же:
reader.next
в сочетании с:
reader.node
Пока вы не пытаетесь сохранить узел как есть, он прекрасно работает. Вы хотите немедленно работать с этим узлом, потому что reader.next унесет его.
Чтобы ответить на более ранний ответ, из того, что я могу понять, libxml-ruby - это потоковый парсер. Проблемы с ошибками сегмента возникли при сборе мусора, который вызывал большие утечки памяти. Как только я научился не использовать reader.expand, все подошло к розам.
ОБНОВИТЬ:
Я не смог решить мою проблему в конце концов. Похоже, нет пути, чтобы добраться до поддерева без использования reader.expand.
И поэтому я думаю, что нет способа прочитать и прочитать большой XML-файл с помощью libxml-ruby? Ошибка reader.expand утечки памяти была открыта даже без ответа с 2009 года? FAIL FAIL FAIL.
В libxml-ruby действительно много ошибок, не только сбоев, но и несовместимости версий, утечек памяти и т. д.
Я очень рекомендую Нокогири. Сообщество Ruby сплотилось вокруг Nokogiri как новый источник быстрого анализа XML. У него есть синтаксический анализатор чтения, SAX-анализатор и ваш стандартный анализатор DOM-памяти в памяти.
Для действительно больших файлов XML я бы порекомендовал Reader, потому что он такой же быстрый, как SAX, но его легче запрограммировать, потому что вам не нужно отслеживать такое большое количество состояний вручную.