You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JAXB流式写入文件时如何移除重复元素的空xmlns=""?

JAXB流式编组处理大数据量XML的命名空间问题解决

我通过xjc生成了数据对象,需要将其编组为XML并写入文件,不能修改生成的对象及package-info.java等文件。MainElem对象包含一个RepeatingElem列表,最初采用常规方式编组时,输出的XML合法且可通过验证,但由于RepeatingElem数据量大、数量多达数千个,出现了内存溢出问题。

初始非流式实现

JAXBContext jaxbContext = JAXBContext.newInstance(MainElem.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(mainElemObj, sw);

输出XML示例:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<mainelem xmlns="http://schema.blah.com/xx/xxx/1">
    <repeatingelem>
        <id>123344567</id>
        <type>A</type>
    </repeatingelem>
    <repeatingelem>
        <id>98775312</id>
        <type>B</type>
    </repeatingelem>
</mainelem>

流式改造遇到的问题

为解决内存溢出,改用流式编组方案逐对象写入文件,代码如下:

JAXBContext context = JAXBContext.newInstance(RepeatingElem.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

XMLOutputFactory xof = XMLOutputFactory.newFactory();
xof.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);

XMLStreamWriter xmlOut = xof.createXMLStreamWriter(new FileOutputStream("myXmlFiel"));
xmlOut.setDefaultNamespace("http://schema.blah.com/xx/xxx/1");
xmlOut.writeStartDocument();
xmlOut.writeStartElement("mainelem");

for(RepeatingElem elem: elemList){
   JAXBElement<RepeatingElem> element = new JAXBElement<>(new QName(null, "repeatingelem"), RepeatingElem.class, elem);
   marshaller.marshal(element, xmlOut);  
}

xmlOut.writeEndDocument();
xmlOut.close();

但生成的XML不合法且无法验证,RepeatingElem元素出现空xmlns=""和ns2前缀,示例如下:

<?xml version="1.0" ?>
<mainelem xmlns="http://schema.blah.com/xx/xxx/1">
    <repeatingelem xmlns="" xmlns:ns2="http://schema.blah.com/xx/xxx/1">
        <ns2:id>123344567</ns2:id>
        <ns2:type>A</ns2:type>
    </repeatingelem>
    <repeatingelem xmlns="" xmlns:ns2="http://schema.blah.com/xx/xxx/1">
        <ns2:id>98775312</ns2:id>
        <ns2:type>B</ns2:type>
    </repeatingelem>
</mainelem>

尝试过调整IS_REPAIRING_NAMESPACES、setDefaultNamespace等命名空间相关配置,甚至将JAXB版本升级到4.0.4都无法解决空xmlns=""的问题。后来移除部分配置并添加xmlOut.writeAttribute解决了空命名空间,但ns2前缀依然存在,导致XML无法通过验证。

最终解决方案

通过修改JAXBElement的QName,指定对应命名空间和默认前缀,彻底解决了问题:

JAXBElement<RepeatingElem> element = new JAXBElement<>(new QName("http://schema.blah.com/xx/xxx/1", "repeatingelem", XMLConstants.DEFAULT_NS_PREFIX), RepeatingElem.class, elem);

对应的XSD定义

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.blah.com/xx/xxx/1" 
    targetNamespace="http://schema.blah.com/xx/xxx/1" elementFormDefault="qualified" 
    attributeFormDefault="unqualified" version="1.0.0">
  <xsd:element name="mainelem">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="repeatingelem" type="Rep" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
  </xsd:element>
  <xsd:complexType name="Rep">
        <xsd:element name="id" type="xsd:string"/>
        <xsd:element name="type" type="xsd:string"/>
        ...
  </xsd:complexType>
</xsd:schema>

内容的提问来源于stack exchange,提问作者StarMcSnow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:44:57