Разбор очень больших XML-документов (и немного больше) на java
(все следующее должно быть написано на Java)
Я должен создать приложение, которое будет принимать в качестве входных XML-документов, которые потенциально очень велики. Документ зашифрован-не с помощью XMLsec, а с помощью уже существующего алгоритма шифрования моего клиента-будет обработан в три этапа:
во-первых, поток будет расшифрован в соответствии с вышеупомянутым алгоритмом.
во-вторых, класс расширения (написанный третьей стороной к API I am providing) прочитает некоторую часть файла. Сумма, которая читается, не предсказуема - в частности, она не гарантируется в заголовке файла, но может возникнуть в любой точке XML.
наконец, другой класс расширения (та же сделка) будет подразделять входной XML на 1..подмножество документов. Возможно, что они будут частично перекрывать часть документа, рассматриваемую второй операцией, т. е.: я считаю, что мне нужно будет перемотать любой механизм I использую для работы с этим объектом.
вот мой вопрос:
есть ли способ сделать это, не читая всю часть данных в память за один раз? Очевидно, я могу реализовать дешифрование в качестве фильтра входного потока, но я не уверен, что можно разобрать XML так, как я описываю; пройдя столько документа, сколько требуется для сбора информации второго шага, а затем перемотав документ и передав его снова, чтобы разделить его в задания, в идеале освобождая все части документа, которые больше не используются после их передачи.
6 ответов
Это похоже на работу для StAX (JSR 173). StAX-это парсер pull, что означает, что он работает более или менее как парсер на основе событий, такой как SAX, но у вас больше контроля над тем, когда прекратить чтение, какие элементы тянуть ...
удобство использования этого решения будет во многом зависеть от того, что на самом деле делают ваши классы расширений, если у вас есть контроль над их реализацией и т. д...
главное, что если документ очень большой, вероятно, вы хотите использовать парсер на основе событий, а не дерево, поэтому вы не будете использовать много памяти.
реализации StAX можно найти из SUN (SJSXP),Codehaus или несколько других поставщиков.
вы могли бы использовать BufferedInputStream
С очень большим размером буфера и использованием mark()
перед тем, как класс расширения работает и reset()
потом.
Если части, необходимые классу расширения, находятся очень далеко в файле,это может стать чрезвычайно интенсивным для памяти".
более общим решением было бы написать свой собственный BufferedInputStream
-workalike что буферов на диск, если данные, которые должны быть буферизованы превышает некоторый заданный порог.
Я бы написал пользовательскую реализацию InputStream
который расшифровывает байты в файле, а затем использует Сакс для анализа результирующего XML по мере его выхода из потока.
SAXParserFactory.newInstance().newSAXParser().parse(
new DecryptingInputStream(),
new MyHandler()
);
вас может заинтересовать XOM:
XOM довольно уникален тем, что это двойной потоковый / древовидный API. Отдельные узлы в дереве могут быть обрабатывается, пока документ еще строится. В позволяет программ сом работать почти так же быстро, как базовый парсер может предоставлять данные. Вы не нужно ждать документ быть полностью проанализированы, прежде чем вы можете начните работать с ним.
XOM очень память эффективный. Если вы чтение всего документа в память, XOM использует как можно меньше памяти. Что еще более важно, XOM позволяет фильтровать документы по мере их создания вам не нужно строить части дерево, которое тебя не интересует. Для например, можно пропустить построение текста узлы, представляющие только границу пробел, если такой пробел не имеет значения в вашем приложении. Вы даже можете обработать часть документа кусок и выбрасывать каждый кусок когда вы покончим с этим. Сом был используется для обработки документов, гигабайт в размере.
посмотреть XOM библиотека. Пример вы ищете StreamingExampleExtractor.java
в каталоге samples исходного дистрибутива. Это показывает метод выполнения потокового анализа большого xml-документа только для создания определенных узлов, их обработки и отбрасывания. Он очень похож на подход sax, но имеет гораздо больше возможностей синтаксического анализа, поэтому потоковый анализ может быть достигнут довольно легко.
Если вы хотите работать на более высоком уровне посмотреть NUX. Это обеспечивает высокий уровень потокового xpath API, который считывает только объем данных в память, необходимую для оценки xpath.