如何使用XOM流式传输XML数据?

时间:2009-06-08 22:14:40

标签: java xml streaming xom

假设我想使用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然后编写它)。

一次输出一个<result>的粒度很好,所以我想生成一个又一个<result>,并将其写入流中。换句话说,我只想做一些像这样的伪代码(启用自动刷新,所以不用担心):

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),{{1比较XOM的writeClose(Element),其中唯一的公共writeDocType(DocumentType)方法是整个Serializer的方法。

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

2 个答案:

答案 0 :(得分:7)

我遇到了同样的问题,但发现做你提到的选项和子类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);
    }

}

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

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

答案 1 :(得分:5)

据我所知,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();
}