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

Spring Batch生成XML报xmlns重复绑定错误该如何解决

错误原因

该异常是由于StaxEventItemWriter和Jaxb2Marshaller同时尝试声明默认命名空间,值冲突导致:你在StaxEventItemWriter的根节点属性中指定了默认命名空间为http://entreprise.uk/ns,但Person类没有配置对应命名空间,JAXB序列化时会默认将默认命名空间绑定为空值,XML规范不允许同一上下文重复绑定默认命名空间,因此抛出错误。

解决方案

按照以下步骤修改配置即可生成符合要求的XML:

步骤1:修改Person类注解

给@XmlRootElement增加namespace属性,和目标命名空间保持一致:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Person", namespace = "http://entreprise.uk/ns")
public class Person {
  // 原有属性和逻辑保持不变
}

步骤2:调整Writer配置

移除StaxEventItemWriter中setRootElementAttributes配置的xmlns属性,改为给JAXB marshaller配置命名空间前缀映射,确保默认命名空间正确生效:

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Person.class);
// 配置JAXB序列化属性
Map<String, Object> marshallerProps = new HashMap<>();
marshallerProps.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// 适配JAXB实现的命名空间前缀映射,让目标命名空间作为默认无前缀的命名空间
marshallerProps.put("com.sun.xml.bind.namespacePrefixMapper", new com.sun.xml.bind.marshaller.NamespacePrefixMapper() {
    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        if ("http://entreprise.uk/ns".equals(namespaceUri)) {
            return "";
        }
        return suggestion;
    }
});
marshaller.setMarshallerProperties(marshallerProps);

StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<>();
itemWriter.setRootTagName("Persons");
itemWriter.setMarshaller(marshaller);
// 不需要单独配置根节点的xmlns属性,JAXB会自动生成
itemWriter.setResource(new FileSystemResource(Paths.get("personOutput.xml").toFile()));
itemWriter.afterPropertiesSet();

return itemWriter;

可选兼容方案

如果你不想修改Person类的注解,可通过自定义StaxEventItemWriter根节点写入逻辑实现,避免命名空间重复声明冲突:

StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<>() {
    @Override
    protected void startDocument(XMLEventWriter writer) throws XMLStreamException {
        super.startDocument(writer);
        // 手动创建带命名空间的根元素
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();
        Namespace defaultNs = eventFactory.createNamespace("http://entreprise.uk/ns");
        StartElement root = eventFactory.createStartElement("", "http://entreprise.uk/ns", "Persons", null, Collections.singleton(defaultNs).iterator());
        writer.add(root);
    }

    @Override
    protected void endDocument(XMLEventWriter writer) throws XMLStreamException {
        XMLEventFactory eventFactory = XMLEventFactory.newInstance();
        writer.add(eventFactory.createEndElement("", "http://entreprise.uk/ns", "Persons"));
        super.endDocument(writer);
    }
};
// 不需要配置setRootTagName和setRootElementAttributes
itemWriter.setMarshaller(marshaller);
itemWriter.setResource(new FileSystemResource(Paths.get("personOutput.xml").toFile()));
itemWriter.afterPropertiesSet();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:27:04