代码之家  ›  专栏  ›  技术社区  ›  Michael Barker

有基于Java的推/非阻塞XML解析器吗?

  •  17
  • Michael Barker  · 技术社区  · 15 年前

    我正在寻找一个XML解析器,它不是从输入流或输入源进行解析,而是允许将文本块推送到解析器中。例如,我想要如下的东西:

    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网络库配合使用的东西,而不需要根据支持阻塞输入流所需的连接模型恢复到线程。

    7 回复  |  直到 9 年前
        1
  •  3
  •   StaxMan    9 年前

    这是Xerces J-Users邮件列表中(2009年4月)的一篇文章,原始海报的版本完全相同。“Jeff”给出了一个潜在的非常好的回应,但没有对原始海报的回应进行跟进:

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

    它可能是新的,足以在列表中出现,或者至少对搜索有帮助。

    编辑

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

    http://markmail.org/message/ogqqcj7dt3lwkbov

        2
  •  7
  •   StaxMan    14 年前

    令人惊讶的是,没有人提到一个Java XML解析器,它实现了非阻塞(“异步”)解析: Aalto . 部分原因可能是缺乏文件(及其活动水平低)。aalto实现了基本的stax api,但也进行了一些小的扩展,以允许推送输入(这部分尚未完成;功能存在,但api尚未完成)。 有关更多信息,请查看相关 discussion group .

        3
  •  4
  •   akarnokd    15 年前

    编辑:现在我明白了。您将接收成块的XML,并希望将其输入到适当的XML解析器中。所以您需要一个对象,一端是队列,另一端是输入流?

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

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

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

        4
  •  1
  •   daxel    15 年前

    检查 openfire's xmleightweightparser以及它如何从单个块中生成XML消息,因为NIO。整个项目是解决NIO和XMPP问题的重要来源。

        5
  •  1
  •   shuckc    12 年前

    添加另一个答案,因为这个问题对于相关的谷歌搜索仍然很高。- aalto-xml 0.9.7(2011年3月)具有异步XML Pasing。这允许您传递任意大小的文档块以继续分析,以及新的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);
    
        6
  •  1
  •   Gavilan Comun    12 年前

    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/

        7
  •  0
  •   Marco Testa    15 年前

    对不起,我没能解决这个问题。 我找不到像我需要的那样的解析器。 但我想自己写一本。 一个非常简单的:就像可行性研究一样,但足以解决我的问题,并希望你的。 不巧的是,我一直很健美,接下来的两周我会出去, 但也许在7月份我会开始研究它。 我一有工作就通知你。

    机器翻译