首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用JAXB Marshaller流式传输大文件?

如何使用JAXB Marshaller流式传输大文件?
EN

Stack Overflow用户
提问于 2009-11-21 19:19:04
回答 3查看 19.3K关注 0票数 24

我面临的问题是如何将大量的对象编组到单个XML文件中,这个文件太大了,我不能一步到位地编组完整的列表。我有一个方法可以按块返回这些对象,但随后我使用JAXB编组这些对象,编组程序返回一个异常,即这些对象不是根元素。这对于您希望在一个步骤中封送整个文档的正常情况是可以的,但是如果我将JAXB_FRAGMENT属性设置为true,也会发生这种情况。

这是所需的XML输出:

<rootElem>  
    <startDescription></startDescription>  
    <repeatingElem></repeatingElem>
    <repeatingElem></repeatingElem>...
</rootElem>

因此,在编组程序编写rootElement的结束标记之前,我假设我需要某种侦听器来动态加载下一块repeatingElements,以便将其提供给编组程序。但如何做到这一点呢?到目前为止,我只使用JAXB编组小文件,JAXB文档并没有为该用例提供太多提示。

EN

回答 3

Stack Overflow用户

发布于 2012-02-16 00:59:48

我知道这是一个老问题,但我在搜索另一个类似问题的副本时遇到了这个问题。

正如@skaffman建议的那样,您希望在启用JAXB_FRAGMENT的情况下进行编组,并将对象包装在JAXBElement中。然后,重复封送重复元素的每个实例。基本上,听起来你想要的东西大致是这样的:

public class StreamingMarshal<T>
{
    private XMLStreamWriter xmlOut;
    private Marshaller marshaller;
    private final Class<T> type;

    public StreamingMarshal(Class<T> type) throws JAXBException
    {
        this.type = type;
        JAXBContext context = JAXBContext.newInstance(type);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
    }

    public void open(String filename) throws XMLStreamException, IOException
    {
        xmlOut = XMLOutputFactory.newFactory().createXMLStreamWriter(new FileOutputStream(filename));
        xmlOut.writeStartDocument();
        xmlOut.writeStartElement("rootElement");
    }

    public void write(T t) throws JAXBException
    {
        JAXBElement<T> element = new JAXBElement<T>(QName.valueOf(type.getSimpleName()), type, t);
        marshaller.marshal(element, xmlOut);
    }

    public void close() throws XMLStreamException
    {
        xmlOut.writeEndDocument();
        xmlOut.close();
    }
}
票数 25
EN

Stack Overflow用户

发布于 2009-11-21 21:39:16

正如您已经发现的,如果一个类没有@XmlRootElement注释,那么您就不能将该类的实例传递给编组程序。但是,有一种简单的方法可以解决这个问题--将对象包装在JAXBElement中,然后将其传递给编组程序。

现在,JAXBElement是一个相当笨拙的野兽,但它所做的是包含您想要编组的对象的元素名称和名称空间,这些信息通常包含在@XmlRootElement注释中。只要您有名称和名称空间,就可以构造一个JAXBElement来包装您的POJO,并对其进行编组。

如果您的POJO是由XJC生成的,那么它还将生成一个ObjectFactory类,其中包含用于为您构建JAXBElement包装器的工厂方法,从而使事情变得更简单。

对于重复的内部元素,仍然必须使用JAXB_FRAGMENT属性,否则JAXB每次都会生成像XML prolog这样的东西,这是您不想要的。

票数 9
EN

Stack Overflow用户

发布于 2009-11-21 21:12:19

我对JAXB了解不多,所以我帮不上忙。但如果你不介意的话,我有个建议。

编写XML比读取XML容易得多,因此您的问题的解决方案可能是使用更“低级”的方法。只需使用可用的XML开源库之一编写自己的编组程序即可。我认为你可以很容易地使用dom4j来做你想做的事情。

票数 -10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1775202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档