Разбор очень больших XML-документов (и немного больше) в Java

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

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

Во-первых, поток будет расшифрован в соответствии с вышеупомянутым алгоритмом.

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

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

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

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

10.12.2008 12:41:01
6 ОТВЕТОВ
РЕШЕНИЕ

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

12
10.12.2008 13:41:26

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

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

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

3
10.12.2008 12:59:38

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

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

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

1
10.12.2008 13:21:53
Это выглядит как интересный и потенциально полезный подход, но нигде в документации он не предлагает способа управления синтаксическим анализом документа так, как вы его описываете. Я верю, что это возможно, но возможности не задокументированы таким образом, чтобы его было разумно обнаружить.
Chris R 10.12.2008 14:05:22

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

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

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

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

7
10.12.2008 13:24:46
Это выглядит многообещающе, пока я могу эффективно к нему подключиться. Похоже, мне придется выставлять StAX клиентам моего API, что далеко не идеально, но, по крайней мере, похоже, что возможности есть. Можете ли вы дополнить свой пост рекомендуемой реализацией вместо списка?
Chris R 10.12.2008 15:41:25
Я знаю, что это старый ответ / комментарий, но есть некоторые библиотеки, которые могут добавить немного больше удобства поверх stax (и выделить некоторые детали более низкого уровня), например StaxMate [ staxmate.codehaus.org/Tutorial] . Это все еще учитывает инкрементный анализ / запись, но уменьшает количество кода для записи.
StaxMan 6.05.2009 06:07:05

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

SAXParserFactory.newInstance().newSAXParser().parse(
  new DecryptingInputStream(), 
  new MyHandler()
);
3
10.12.2008 13:57:56

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

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

0
10.03.2011 21:16:24