Есть ли основанный на Push-based/Non-blocking XML Parser для Java?
Я ищу XML-синтаксический анализатор, который вместо синтаксического анализа из InputStream или InputSource вместо этого позволяет вставлять блоки текста в парсер. Например. Я хотел бы иметь что-то вроде следующего:
public class DataReceiver {
private SAXParser parser = //...
private DefaultHandler handler = //...
/**
* Called each time some data is received.
*/
public void onDataReceived(byte[] data) {
parser.push(data, handler);
}
}
Причина в том, что мне хотелось бы что-то, что будет хорошо работать с сетевыми библиотеками NIO, а не возвращаться к потоку на модель подключения, требуемой для поддержки блокировки InputStream.
Ответы
Ответ 1
Это (апрель 2009 г.) сообщение из списка рассылки Xerces J-Users, где исходный плакат имеет ту же самую проблему. Дается один потенциально очень хороший ответ "Джефф", но после первоначального ответа на плакат нет:
http://www.nabble.com/parsing-an-xml-document-chunk-by-chunk-td22945319.html
Это потенциально достаточно новый, чтобы наброситься на список или, по крайней мере, помочь с поиском.
Edit
Найдена еще одна полезная ссылка, в которой упоминается библиотека под названием Woodstox и описывается состояние парсеров на основе потоков и NIO и некоторые возможные подходы к эмуляции потока:
http://markmail.org/message/ogqqcj7dt3lwkbov
Ответ 2
Удивительно, но никто не упомянул один Java-парсер Java, который реализует неблокирующий ( "асинхронный" ) синтаксический анализ: Aalto. Частично причиной может быть отсутствие документации (и ее низкий уровень активности). Aalto реализует базовый API-интерфейс Stax, но также и второстепенные расширения, позволяющие вводить ввод (эта часть еще не завершена, функциональность существует, но API не завершен).
Для получения дополнительной информации вы можете проверить связанную дискуссионную группу.
Ответ 3
Изменить: Теперь я вижу. Вы получаете XML в кусках и хотите передать его в правильный синтаксический анализатор XML. Итак, вам нужен объект, который представляет собой очередь на одном конце, и InputStream на другом конце?
Вы можете агрегировать массивы байтов, полученные в ByteArrayOutputStream, преобразовать их в ByteArrayInputStream и передать их SAXParser.
Или вы можете проверить пару PipedInputStream/PipedOutputStream. В этом случае вам нужно будет провести синтаксический анализ в другом потоке, поскольку анализатор SAX использует текущий поток для генерации событий, блокируя ваш метод receive().
Изменить. На основе комментариев я предлагаю использовать маршрут агрегирования. Вы собираете куски в ByteArrayOutputStream. Чтобы узнать, получили ли вы все фрагменты для своего XML, проверьте, содержит ли текущий фрагмент или содержимое ByteArrayOutputStream ваш конечный тег корня XML node. Затем вы можете просто передать данные в SAXParser, который теперь может работать в текущем потоке без проблем. Чтобы избежать ненужного повторного создания массива, вы могли бы реализовать свою собственную несинхронизированную простую байтную оболочку массива или искать такую реализацию.
Ответ 4
Отметьте openfire XMLLeightweightParser и как он генерирует XML-сообщения из отдельных блоков из-за NIO. Весь проект является отличным источником ответов на вопросы NIO и XMPP.
Ответ 5
NioSax работает с ByteBuffers
http://blog.retep.org/2010/06/25/niosax-sax-style-xml-parser-for-java-nio/
Исходный код последней версии, которую я мог найти (10.6 с 2010), находится в
Сонатный репозиторий Maven:
https://oss.sonatype.org/content/repositories/releases/uk/org/retep/
Ответ 6
Извините, мне не удалось решить эту проблему.
Я не мог найти парсер, как тот, который мне нужен.
Но я собираюсь написать один сам.
Очень просто: так же, как и изучение вопроса о возможности, но достаточно, чтобы решить мою проблему и, к счастью, ваша.
Unortunatelly я был очень buisy и следующие две недели я буду вне,
но, может быть, в июле я начну работать над этим.
Я сообщу вам, как только у меня что-то будет.
т
Ответ 7
Добавление другого ответа, поскольку этот вопрос остается высоким для релевантных поисков Google - aalto-xml. 0.9.7 (март 2011) имеет асинхронную XML-операцию. Это позволяет передавать произвольные размеры документа для продолжения разбора, а новый тип события StaX EVENT_INCOMPLETE
для указания входного буфера исчерпан, а документ остается неполным.
Это Пример Тату Салоранта (автор):
byte[] msg = "<html>Very <b>simple</b> input document!</html>".getBytes();
AsyncXMLStreamReader asyncReader = new InputFactoryImpl().createAsyncXMLStreamReader();
final AsyncInputFeeder feeder = asyncReader.getInputFeeder();
int inputPtr = 0; // as we feed byte at a time
int type = 0;
do {
// May need to feed multiple "segments"
while ((type = asyncReader.next()) == AsyncXMLStreamReader.EVENT_INCOMPLETE) {
feeder.feedInput(msg, inputPtr++, 1);
if (inputPtr >= msg.length) { // to indicate end-of-content (important for error handling)
feeder.endOfInput();
}
}
// and once we have full event, we just dump out event type (for now)
System.out.println("Got event of type: "+type);
// could also just copy event as is, using Stax, or do any other normal non-blocking handling:
// xmlStreamWriter.copyEventFromReader(asyncReader, false);
} while (type != AsyncXMLStreamReader.END_DOCUMENT);