2009-11-21 90 views
18

我面临的问题是如何马歇尔大名单的对象到一个XML文件,过大我不能马歇尔一步到位的完整列表。我有一个方法以块的形式返回这些对象,但是然后我使用JAXB编组这些对象,编组器返回一个例外,即这些对象不是根元素。这对于你想在一个步骤中编组完整文档的正常情况是可以的,但如果将JAXB_FRAGMENT属性设置为true,也会发生这种情况。如何使用JAXB Marshaller流式传输大型文件?

这是所期望的XML输出:

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

所以我想我需要一些听众的动态加载repeatingElements下一块给它喂编组之前,他会写的结束标记rootElement的。但如何做到这一点?到目前为止,我只使用JAXB来编组小文件,而JAXB文档并没有提供太多的提示。

回答

-8

我不知道很多JAXB的,所以我也没有办法。但如果你不介意,我有一个建议。

编写XML比读它轻松了很多,所以你的问题的解决方案可能是使用更“低水平”的做法。只需使用XML的一个可用开源库编写自己的编组器。我想你可以用dom4j轻松做到你想要的。

9

正如你已经发现,如果一个类没有@XmlRootElement注解,那么你不能在类的实例传递给编组。但是,有一个简单的方法 - 将对象包装在JAXBElement中,并将其传递给编组。

现在JAXBElement是一个相当笨拙的野兽,但它的作用是包含该元素的名称和它通常会包含在@XmlRootElement注释要当元帅的对象,信息的命名空间。只要你有名字和名字空间,你可以构造一个JAXBElement来包装你的POJO,并编组它。

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

你仍然必须使用JAXB_FRAGMENT属性的重复内部元素,否则将JAXB生成的东西像每一次的XML序言,你不想要的。

15

我知道,这是一个老问题,但我碰到它,同时寻找另一个类似的问题重复。

由于@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(); 
    } 
} 
+0

需要在构造函数中设置编组。 this.marshaller =米; –