如何使用 JAXB 马歇尔流传输大型文件?

2022-09-01 21:10:26

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

这是所需的 XML 输出:

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

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


答案 1

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

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

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);
        this.marshaller = context.createMarshaller();
        this.marshaller.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();
    }
}

答案 2

正如你所发现的,如果一个类没有注释,那么你就不能将该类的实例传递给元组。但是,有一个简单的方法可以解决这个问题 - 将对象包装在 中,并将其传递给元组。@XmlRootElementJAXBElement

现在是一个相当笨拙的野兽,但它的作用是包含要封送处理的对象的元素名称和命名空间,这些信息通常包含在注释中。只要您有名称和命名空间,就可以构造一个来包装POJO,并对其进行封送。JAXBElement@XmlRootElementJAXBElement

如果你的POJO是由XJC生成的,那么它还会生成一个类,其中包含为你构建包装器的工厂方法,使事情变得容易一些。ObjectFactoryJAXBElement

您仍然必须将该属性用于重复的内部元素,否则 JAXB 每次都会生成类似 XML prolog 之类的内容,而您不希望这样做。JAXB_FRAGMENT


推荐