假设我想使用 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
轻松做到这一点 - 它具有采用 Writer
或 OutputStream
的构造函数,以及 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();