Чтение огромного XML-файла с использованием StAX и XPath - PullRequest
10 голосов
/ 27 августа 2011

Входной файл содержит тысячи транзакций в формате XML, размер которого составляет около 10 ГБ.Требуется выбрать XML каждой транзакции на основе введенного пользователем и отправить его в систему обработки.

Пример содержимого файла

<transactions>
    <txn id="1">
      <name> product 1</name>
      <price>29.99</price>
    </txn>

    <txn id="2">
      <name> product 2</name>
      <price>59.59</price>
    </txn>
</transactions>

(технический) ожидается, что пользователь введет имя входного тега, например <txn>.

Мы бы хотели, чтобы это решение было более общим.Содержимое файла может отличаться, и пользователи могут указать выражение XPath, например "//transactions/txn", для выбора отдельных транзакций.

Здесь есть несколько технических вещей, которые мы должны рассмотреть

  • Файл может находиться в общей папке или на FTP
  • Поскольку размер файла огромен, мы не можем загрузить весь файл в JVM

Можем ли мы использовать синтаксический анализатор StAX для этого сценария?Он должен принять выражение XPath в качестве входных данных и выбрать / выбрать транзакцию XML.

Поиск предложений.Заранее спасибо.

Ответы [ 7 ]

15 голосов
/ 03 апреля 2013

Если производительность является важным фактором, и / или размер документа велик (оба из которых, кажется, имеют место здесь), разница между анализатором событий (например, SAX или StAX) и собственной реализацией Java XPath заключается в том, чтопоследний создает документ DOM W3C до оценки выражения XPath.[Интересно отметить, что все реализации объектной модели документов Java, такие как DOM или Axiom, используют процессор событий (например, SAX или StAX) для построения представления в памяти, поэтому, если вы когда-либо сможете обойтись только с обработчиком событий,экономя память и время, необходимое для создания DOM.]

Как я уже говорил, реализация XPath в JDK работает с документом DOM W3C.Вы можете увидеть это в реализации исходного кода Java JDK, посмотрев com.sun.org.apache.xpath.internal.jaxp.XPathImpl, где перед вызовом методаvalu () анализатор должен сначала проанализировать источник:

  Document document = getParser().parse( source );

После этого ваши 10 ГБXML будет представлен в памяти (плюс любые накладные расходы) - вероятно, не то, что вы хотите.Хотя вам может потребоваться более «универсальное» решение, ваш пример XPath и разметка XML кажутся относительно простыми, поэтому для XPath нет веских оснований (за исключением, возможно, элегантности программирования ),То же самое будет верно для предложения XProc: это также создаст DOM.Если вам действительно нужна DOM, вы можете использовать Axiom, а не W3C DOM.Axiom имеет более дружественный API и строит свой DOM поверх StAX, поэтому он быстрый и использует Jaxen для своей реализации XPath.Jaxen требуется некоторый вид DOM (W3C DOM, DOM4J или JDOM).Это будет справедливо для всех реализаций XPath, поэтому, если вам действительно не нужно, чтобы XPath придерживался только парсера событий, было бы рекомендовано.

SAX - это старый потоковый API, с StAX новее и намного быстрее,Используя собственную реализацию JDK StAX (javax.xml.stream) или реализацию Woodstox StAX (что, на мой взгляд, значительно быстрее), я бы порекомендовал создать фильтр событий XML, который сначала совпадает с именем типа элемента(чтобы захватить ваши <txn> элементы).Это создаст небольшие пакеты событий (элемент, атрибут, текст), которые могут быть проверены на соответствие ваших пользовательских значений.При подходящем совпадении вы можете либо извлечь необходимую информацию из событий, либо направить ограниченные события, чтобы построить из них мини-DOM, если вы обнаружили, что результат легче ориентировать.Но звучит так, что это может быть излишним, если разметка проста.

Вероятно, это будет самый простой и быстрый из возможных подходов и позволит избежать затрат памяти при создании DOM.Если вы передали имена элемента и атрибута в фильтр (чтобы ваш алгоритм сопоставления был настраиваемым), вы можете сделать его относительно общим.

9 голосов
/ 27 августа 2011

Stax и XPath - это очень разные вещи. Stax позволяет анализировать потоковый XML-документ только в прямом направлении. Xpath позволяет анализировать в обоих направлениях. Stax - очень быстрый анализатор потокового XML, но, если вам нужен xpath, у java есть отдельная библиотека для этого.

Посмотрите на этот вопрос для очень похожего обсуждения: Есть ли процессор XPath для модели SAX?

2 голосов
/ 07 января 2012

Мы регулярно анализируем сложные файлы XML размером 1 ГБ и более, используя синтаксический анализатор SAX, который делает именно то, что вы описали: он извлекает частичные DOM-деревья, которые можно удобно запрашивать с помощью XPATH.

Я увлекся этим здесь - он использует SAX, а не анализатор StAX, но, возможно, стоит взглянуть.

1 голос
/ 26 февраля 2018

Забавное решение для обработки огромных файлов XML> 10 ГБ.

  1. Используйте ANTLR для создания смещения байтов для интересующих частей.Это сэкономит немного памяти по сравнению с подходом, основанным на DOM.
  2. Использование Jaxb для чтения деталей из позиции байта

Подробности в примере этого ответа SO приведены в примере дампов Википедии (17 ГБ).https://stackoverflow.com/a/43367629/1485527

1 голос
/ 03 сентября 2011

Это определенно сценарий использования XProc с реализацией потоковой и параллельной обработки, такой как QuiXProc (http://code.google.com/p/quixproc)

. В этой ситуации вам придется использовать

  <p:for-each>
    <p:iteration-source select="//transactions/txn"/>
    <!-- you processing on a small file -->
  </p:for-each>

. Вы можете дажеОберните каждое из полученных преобразований одной строкой XProc

  <p:wrap-sequence wrapper="transactions"/>

Надеюсь, это поможет

0 голосов
/ 27 августа 2011

Вам нужно быстро обработать или вам нужен быстрый поиск данных? Эти требования требуют другого подхода.

Для быстрого чтения всех данных StAX будет в порядке.

Если вам нужны быстрые поиски, а не загружать их в какую-либо базу данных, Berkeley DB XML, например,

0 голосов
/ 27 августа 2011

Потоковые преобразования для XML (STX) может быть тем, что вам нужно.

...