【问题标题】:How to stream XML data using XOM?如何使用 XOM 流式传输 XML 数据?
【发布时间】:2010-11-01 07:46:17
【问题描述】:

假设我想使用XOM 将大量搜索结果以XML 格式输出到PrintWriter 或OutputStream。生成的 XML 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<resultset>
    <result>
       [child elements and data]
    </result>
    ...
    ...
    [1000s of result elements more]
</resultset>

因为生成的 XML 文档可能很大(可能有数百兆字节),所以我想以流式方式输出它(而不是在内存中创建整个 Document 然后再写入)。

一次输出一个&lt;result&gt;的粒度是可以的,所以我想一个接一个地生成一个&lt;result&gt;,写入到流中。换句话说,我只是想做一些类似这样的伪代码(启用自动刷新,所以不用担心):

open stream/writer
write declaration
write start tag for <resultset>
while more results:
    write next <result> element
write end tag for <resultset> 
close stream/writer

我一直在看Serializer,但是必要的方法,writeStartTag(Element)writeEndTag(Element)write(DocType) 是受保护的,而不是公开的!除了将 Serializer 子类化以便能够使用这些方法,或者将开始和结束标记作为字符串直接写入流中,完全绕过 XOM 之外,没有其他方法吗? (在这个简单的例子中后者不会太糟糕,但在一般情况下它会变得很丑。)

是我遗漏了什么还是 XOM 不是为此而生的?

使用dom4j,我可以使用XMLWriter 轻松做到这一点——它具有采用WriterOutputStream 的构造函数,以及writeOpen(Element)writeClose(Element)writeDocType(DocumentType) 等方法。与XOM 的@ 相比987654340@,其中唯一的公共 write 方法是采用整个 Document 的方法。

(这与my question about the best dom4j replacement 有关,XOM 是一个强有力的竞争者。)

【问题讨论】:

    标签: java xml streaming xom


    【解决方案1】:

    据我所知,XOM 不支持直接流式传输。

    当我想流式传输我的 XML 文档时使用的是 NUX,它具有 Streaming XML Serializer,类似于 XOM 中的标准 Serializer 类。 NUX 与 XOM 兼容。我下载了 NUX 源,提取了几个 NUX 类(StreamingSerializer 接口、StreamingXMLSerializer——适用于 XOM 文档、StreamingVerifier 和 NamespacesInScope),将它们放入我的项目中,它就像一个魅力。太糟糕了,这不是直接在 XOM 中 :-(

    NUX 是 XOM 非常好的伴侣:http://acs.lbl.gov/software/nux/,工作镜像下载:nux-1.6.tar.gz

    API 链接:http://acs.lbl.gov/software/nux/api/nux/xom/io/StreamingSerializer.html

    这里是示例代码(按顺序调用方法:start()、n*nextResult()finish(),序列化器是来自 NUX 的 StreamingXMLSerializer):

    void start() {
        serializer.writeXMLDeclaration();
    
        Element root = new Element("response");
        root.addAttribute(new Attribute("found", Integer.toString(123)));
        root.addAttribute(new Attribute("count", Integer.toString(542)));
    
        serializer.writeStartTag(root);
    
        serializer.flush();
    }
    
    void nextResult(Result result) {
        Element element = result.createXMLRepresentation();
        serializer.write(element);
        serializer.flush();
    }
    
    void finish() {
        serializer.writeEndTag();
        serializer.flush();
    }
    

    【讨论】:

    • 另外,这是一个下载链接,因为他们的网站已损坏且可能未维护:openbsd.mirrors.tds.net/pub/FreeBSD/distfiles/nux-1.6.tar.gz
    • @Ed: 顺便说一句,堆栈溢出就像 wiki,你可以修改帖子......但你可能首先需要更多的“声誉”点 :-(
    • @Peter:我知道,是的——我还没有足够的代表;否则我会为你编辑它。总有一天! :)
    【解决方案2】:

    我遇到了同样的问题,但发现执行您提到的作为选项和子类 Serializer 的操作非常简单,如下所示:

    public class StreamSerializer extends Serializer {
    
        public StreamSerializer(OutputStream out) {
            super(out);
        }
    
        @Override
        public void write(Element element) throws IOException {
            super.write(element);
        }
    
        @Override
        public void writeXMLDeclaration() throws IOException {
            super.writeXMLDeclaration();
        }
    
        @Override
        public void writeEndTag(Element element) throws IOException {
            super.writeEndTag(element);
        }
    
        @Override
        public void writeStartTag(Element element) throws IOException {
            super.writeStartTag(element);
        }
    
    }
    

    然后您仍然可以利用各种 XOM 配置,例如 setIdent 等,但可以像这样使用它:

    Element rootElement = new Element("resultset");
    StreamSerializer serializer = new StreamSerializer(out);
    serializer.setIndent(4);
    serializer.writeXMLDeclaration();
    serializer.writeStartTag(rootElement);
    while(hasNextElement()) {
        serializer.write(nextElement());
    }
    serializer.writeEndTag(rootElement);
    serializer.flush();
    

    【讨论】:

    • 是的,我认为这样应该可行,但一直没有尝试过。感谢您对此进行验证!在某种程度上,我认为这比引入另一个 3rd 方库(参见彼得的回答)更可取,只是简单的流式传输。 (不过,遗憾的是 XOM 没有内置此功能。)
    • 不错。我喜欢您的解决方案,下次需要时会尝试。
    猜你喜欢
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    相关资源
    最近更新 更多