Как я могу прочитать большой 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, но его легче запрограммировать, потому что вам не нужно отслеживать такое большое количество состояний вручную.

Другие вопросы по тегам