17

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

4

7 回答 7

7

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

于 2010-08-31T05:44:45.183 回答
4

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

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

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

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

于 2009-06-21T20:09:12.197 回答
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

于 2009-06-25T20:37:26.317 回答
1

检查openfireXMLLeightweightParser 以及由于 NIO 它如何从单个块生成 XML 消息。整个项目是有关 NIO 和 XMPP 问题的答案的重要来源。

于 2009-07-31T20:04:20.263 回答
1

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

这是Tatu Salorant(作者)的示例:

     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);
于 2012-06-21T09:47:54.690 回答
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/

于 2013-06-09T19:51:42.523 回答
0

对不起,我没能解决这个问题。我找不到像我需要的那样的解析器。但是我想自己写一篇。一个非常简单的问题:就像可裂性研究一样,但足以解决我的问题,也可以解决你的问题。不幸的是,我一直很忙,接下来的两周我会出去,但也许七月份我会开始工作。一旦我有工作,我会尽快通知你。

公吨

于 2009-06-25T23:34:20.063 回答