假设我想使用 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 文档可能很大(可能有数百兆字节),所以我想以流方式输出它(而不是在内存中创建整个文档,然后再写入)。

一次输出一个<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) 是 protected ,而不是公开的!除了将 Serializer 子类化以能够使用这些方法,或者手动将开始和结束标记作为字符串直接写入流中,完全绕过 XOM 之外,还有其他方法吗? (在这个简单的例子中,后者不会太糟糕,但在一般情况下,它会变得非常难看。)

我是不是遗漏了什么,还是 XOM 不是为此而设计的?

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

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

最佳答案

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

10-06 09:48