如何使用 XOM 传输 XML 数据?

发布于 2024-07-22 20:32:06 字数 1893 浏览 6 评论 0原文

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

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

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 - 它具有采用 Writer的构造函数>OutputStream,以及方法 writeOpen(Element)writeClose(Element)writeDocType(DocumentType) 等。与 XOM 的 < code>Serializer 其中唯一的公共 write 方法是需要整个 Document 的方法。

(这与 我关于最佳 dom4j 替代品的问题有关 其中 XOM 是一个强有力的竞争者。)

Say I want to output a huge set of search results, as XML, into a PrintWriter or an OutputStream, using XOM. The resulting XML would look like this:

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

Because the resulting XML document could be big (hundreds of megabytes, perhaps), I want to output it in a streaming fashion (instead of creating the whole Document in memory and then writing that).

The granularity of outputting one <result> at a time is fine, so I want to generate one <result> after another, and write it into the stream. In other words, I'd simply like to do something like this pseudocode (automatic flushing enabled, so don't worry about that):

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

I've been looking at Serializer, but the necessary methods, writeStartTag(Element), writeEndTag(Element), write(DocType) are protected, not public! Is there no other way than to subclass Serializer to be able to use those methods, or to manually write the start and end tags directly into the stream as Strings, bypassing XOM altogether? (The latter wouldn't be too bad in this simple example, but in the general case it would get quite ugly.)

Am I missing something or is XOM just not made for this?

With dom4j I could do this easily using XMLWriter - it has constructors that take a Writer or OutputStream, and methods writeOpen(Element), writeClose(Element), writeDocType(DocumentType) etc. Compare to XOM's Serializer where the only public write method is the one that takes a whole Document.

(This is related to my question about the best dom4j replacement where XOM is a strong contender.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谷夏 2024-07-29 20:32:06

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

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

I ran in to the same issue, but found it's pretty simple to do what you mentioned as an option and subclass Serializer as follows:

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

}

Then you can still take advantage of the various XOM config like setIdent, etc. but use it like this:

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();
想你的星星会说话 2024-07-29 20:32:06

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

As far as I know, XOM doesn't support streaming directly.

What I used when I wanted to stream my XML documents was NUX, which has Streaming XML Serializer, similar to standard Serializer class in XOM. NUX is compatible with XOM. I downloaded NUX sources, extracted few NUX classes (StreamingSerializer interface, StreamingXMLSerializer -- which works for XOM documents, StreamingVerifier and NamespacesInScope), put them into my project, and it works like a charm. Too bad this isn't directly in XOM :-(

NUX is very nice companion to XOM: http://acs.lbl.gov/software/nux/, working mirror download: nux-1.6.tar.gz

Link to API: http://acs.lbl.gov/software/nux/api/nux/xom/io/StreamingSerializer.html

Here is sample code (methods are called in order: start(), n*nextResult(), finish(), serializer is StreamingXMLSerializer from NUX):

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文