是否有针对Java的基于推送/非阻塞的XML解析器?

时间:2009-06-21 12:05:07

标签: java xml nonblocking

我正在寻找一种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所需的每个连接模型的线程。

7 个答案:

答案 0 :(得分:7)

令人惊讶的是,没有人提到过一个实现非阻塞(“异步”)解析的Java XML解析器:Aalto。部分原因可能是缺乏文档(及其活动水平较低)。 Aalto实现了基本的Stax API,但也允许推送输入的小扩展(这部分尚未最终确定;功能存在但API尚未最终确定)。 有关详细信息,请查看相关的discussion group

答案 1 :(得分:4)

编辑:现在我明白了。您以块的形式接收XML,并希望将其提供给正确的XML解析器。所以你需要一个对象,一端是队列,另一端是InputStream?

您可以将收到的字节数组聚合到ByteArrayOutputStream中,将其转换为ByteArrayInputStream并将其提供给SAXParser。

或者您可以查看PipedInputStream / PipedOutputStream对。在这种情况下,你需要在另一个线程中进行解析,因为SAX解析器使用当前线程发出事件,阻塞你的receive()。

修改:根据我建议采用聚合路线的评论。您将块收集到ByteArrayOutputStream中。要知道是否收到了XML的所有块,请检查当前块或ByteArrayOutputStream的内容是否包含XML根节点的结束标记。然后你可以将数据传递给SAXParser,它现在可以在当前线程中运行而不会出现问题。为了避免不必要的数组重新创建,您可以实现自己的非同步简单字节数组包装器或查找此类实现。

答案 2 :(得分:3)

这是来自Xerces J-Users邮件列表的(2009年4月)帖子,其中原始海报具有完全相同的问题。给出了“杰夫”的一个非常好的回应,但没有跟进原始海报的回应:

http://www.nabble.com/parsing-an-xml-document-chunk-by-chunk-td22945319.html

它可能足够新,可以在列表中出现,或至少帮助搜索。

修改

找到了另一个有用的链接,提到了一个名为Woodstox的库,并描述了Stream与基于NIO的解析器的状态以及一些模拟流的可能方法:

http://markmail.org/message/ogqqcj7dt3lwkbov

答案 3 :(得分:1)

检查openfire's XMLLeightweightParser以及它如何因单个NIO而从单个块生成XML消息。整个项目是有关NIO和XMPP问题答案的重要来源。

答案 4 :(得分:1)

添加另一个答案,因为此问题仍然适用于相关的Google搜索 - aalto-xml 0。9。7(2011年3月)具有异步XML功能。这允许您传递文档的任意大小的块以继续解析,并允许新的StaX事件类型EVENT_INCOMPLETE以指示输入缓冲区已用尽且文档仍然不完整。

这是Tatu Salorant's(作者的)例子:

     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);

答案 5 :(得分:1)

NioSax与ByteBuffers一起使用

http://blog.retep.org/2010/06/25/niosax-sax-style-xml-parser-for-java-nio/

我能找到的最新版本的源代码(2010年10.6)在 Sonatype Maven存储库:

https://oss.sonatype.org/content/repositories/releases/uk/org/retep/

答案 6 :(得分:0)

对不起,我没有设法解决这个问题。 我找不到像我需要的解析器。 但我正想着自己写一个。 一个非常简单的问题:就像可行性研究一样,但足以解决我的问题并且很快就能解决问题。 不合时宜我非常吵,接下来的两个星期我都会出去, 但也许在七月我会开始研究它。 我一有工作就立刻通知你。

MT