Разбор очень больших XML-документов (и немного больше) в Java - PullRequest
18 голосов
/ 10 декабря 2008

(Все следующее должно быть написано на Java)

Мне нужно создать приложение, которое будет принимать в качестве входных XML-документов, которые могут быть очень большими. Документ зашифрован - не с использованием XMLsec, а с помощью уже существующего алгоритма шифрования моего клиента - будет обрабатываться в три этапа:

Сначала поток будет расшифрован в соответствии с вышеупомянутым алгоритмом.

Во-вторых, класс расширения (написанный третьей стороной для API, который я предоставляю) будет читать некоторую часть файла. Количество прочитанного не предсказуемо, в частности, оно не гарантируется в заголовке файла, но может произойти в любой точке XML.

Наконец, другой класс расширения (та же сделка) подразделяет входной XML на 1..n подмножества документов. Вполне возможно, что они в какой-то степени будут перекрывать часть документа, которая обрабатывается второй операцией, т.е. я считаю, что мне нужно будет перемотать любой механизм, который я использую для работы с этим объектом.

Вот мой вопрос:

Есть ли способ сделать это, никогда не считывая весь фрагмент данных в память одновременно? Очевидно, что я могу реализовать дешифрование в качестве фильтра входного потока, но я не уверен, возможно ли проанализировать XML так, как я описываю; просматривая большую часть документа, необходимо собрать информацию о втором шаге, а затем перемотав документ и пропустив его снова, чтобы разделить его на рабочие места, в идеале выпуская все части документа, которые больше не используются после они были пройдены.

Ответы [ 6 ]

12 голосов
/ 10 декабря 2008

Stax - верный путь. Я бы рекомендовал посмотреть на Woodstox

7 голосов
/ 10 декабря 2008

Звучит как работа для StAX ( JSR 173 ). StAX - это синтаксический анализатор, который означает, что он более или менее работает как анализатор на основе событий, такой как SAX, но у вас больше контроля над тем, когда прекратить чтение, какие элементы извлекать ...

Удобство использования этого решения будет во многом зависеть от того, что на самом деле делают ваши классы расширений, если у вас есть контроль над их реализацией и т. Д. *

Суть в том, что если документ очень большой, вы, вероятно, захотите использовать анализатор на основе событий, а не на основе дерева, поэтому вы не будете использовать много памяти.

Реализации StAX можно найти в SUN ( SJSXP ), Codehaus или нескольких других провайдерах.

3 голосов
/ 10 декабря 2008

Я бы написал пользовательскую реализацию InputStream, которая расшифровывает байты в файле, а затем использовал SAX для анализа результирующего XML, когда он выходит из потока.

SAXParserFactory.newInstance().newSAXParser().parse(
  new DecryptingInputStream(), 
  new MyHandler()
);
3 голосов
/ 10 декабря 2008

Вы можете использовать BufferedInputStream с очень большим размером буфера и использовать mark() до работы класса расширения и reset() после.

Если те части, которые нужны классу расширения, находятся очень далеко от файла, то это может привести к чрезмерной загрузке памяти ».

Более общим решением было бы написать свой собственный BufferedInputStream -рабочий, который буферизует на диск, если данные, подлежащие буферизации, превышают некоторый заданный порог.

1 голос
/ 10 декабря 2008

Вас может заинтересовать XOM :

XOM довольно уникален тем, что это двойной потоковый / древовидный API. Отдельные узлы в дереве могут быть обрабатывается, пока документ еще в процессе постройки. Включает программы XOM работать почти так же быстро, как базовый парсер может предоставлять данные. Вы не нужно ждать, пока документ быть полностью разобран, прежде чем вы сможете начать работать с ним.

XOM очень эффективно использует память. если ты прочитать весь документ в память, XOM использует как можно меньше памяти. Что еще более важно, XOM позволяет вам фильтровать документы, как они построены так вам не нужно строить части дерево, которое вас не интересует. Для Например, вы можете пропустить сборку текста узлы, которые представляют только границу пробел, если такой пробел не имеет значения в вашем приложении. Вы даже можете обработать кусок документа по частям и выбросить каждый кусок когда вы закончите с этим. XOM был используется для обработки документов, которые гигабайт в размере.

0 голосов
/ 11 марта 2011

Посмотрите на библиотеку XOM . Пример, который вы ищете, это StreamingExampleExtractor.java в каталоге примеров исходного дистрибутива. Это показывает методику для выполнения потокового анализа большого XML-документа, только создавая определенные узлы, обрабатывая их и отбрасывая их. Это очень похоже на подход саксофона, но имеет гораздо больше встроенных возможностей синтаксического анализа, поэтому потоковый анализ может быть достигнут довольно легко.

Если вы хотите работать на более высоком уровне, посмотрите на NUX . Это обеспечивает высокоуровневый потоковый API xpath, который считывает только объем данных в память, необходимый для оценки xpath.

...