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

如何在xjc/JAXB生成的XML中为多份XSD配置对应schemaLocation属性

解决方案

方法1:运行时动态注入schemaLocation属性(推荐,适合多场景复用)

无需修改生成的Java类逻辑,适配20份schema的批量配置需求。

  1. 新增XJC全局绑定文件,让所有生成的元素类自动添加任意属性存储字段。创建global-binding.xjb文件,内容如下:
<jxb:bindings version="2.1"
  xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  xmlns:annox="http://annox.dev.java.net">
  <jxb:globalBindings>
    <!-- 给所有生成类添加@XmlAnyAttribute注解的Map字段,用于存储额外属性 -->
    <xjc:extraAnnotation>
      <annox:annotate>
        @javax.xml.bind.annotation.XmlAnyAttribute
        private java.util.Map<QName, Object> extraAttributes = new java.util.HashMap<>();
      </annox:annotate>
    </xjc:extraAnnotation>
  </jxb:globalBindings>
</jxb:bindings>

执行xjc命令时引入该绑定文件,生成的所有类都会自带可存储任意属性的Map字段。如果不想使用annox插件,也可以手动给生成类添加对应字段。
2. 实现Marshaller监听器,序列化前自动给对应元素注入schemaLocation属性:

import javax.xml.namespace.QName;
import javax.xml.bind.Marshaller;
import java.lang.reflect.Field;
import java.util.Map;

// 提前维护所有类和对应schemaLocation的映射
private static final Map<Class<?>, String> CLASS_SCHEMA_MAPPING = Map.of(
    GovTalkMessage.class, "http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch.xsd",
    FormSubmission.class, "http://xmlgw.companieshouse.gov.uk/v1-0/schema/forms/FormSubmission-v2-11.xsd",
    ReturnofAllotmentShares.class, "http://xmlgw.companieshouse.gov.uk/v1-0/schema/forms/ReturnofAllotmentShares-v3-0.xsd"
    // 剩余17个schema对应的类按规则补充即可
);
private static final QName XSI_SCHEMA_LOCATION = new QName("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", "xsi");

Marshaller.Listener schemaInjectListener = new Marshaller.Listener() {
    @Override
    public void beforeMarshal(Object source) {
        if (CLASS_SCHEMA_MAPPING.containsKey(source.getClass())) {
            try {
                Field extraField = source.getClass().getDeclaredField("extraAttributes");
                extraField.setAccessible(true);
                Map<QName, Object> attrMap = (Map<QName, Object>) extraField.get(source);
                attrMap.put(XSI_SCHEMA_LOCATION, CLASS_SCHEMA_MAPPING.get(source.getClass()));
            } catch (Exception e) {
                // 自行补充异常处理逻辑
                e.printStackTrace();
            }
        }
    }
};
  1. 配置Marshaller启用监听器,完成序列化:
JAXBContext context = JAXBContext.newInstance(GovTalkMessage.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// 触发xsi命名空间自动生成
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "");
marshaller.setListener(schemaInjectListener);
// 执行序列化
marshaller.marshal(yourGovTalkMessageObj, outputStream);

方法2:生成类时固定注入schemaLocation属性(适合schema固定不常变更的场景)

直接通过绑定文件给每个元素类添加固定的schemaLocation属性,无需运行时处理。绑定文件示例如下:

<jxb:bindings version="2.1"
  xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  xmlns:annox="http://annox.dev.java.net">
  <!-- 给ReturnofAllotmentShares类添加固定schemaLocation属性 -->
  <jxb:bindings schemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/forms/ReturnofAllotmentShares-v3-0.xsd" node="//xs:element[@name='ReturnofAllotmentShares']">
    <xjc:extraAnnotation>
      <annox:annotate>
        @javax.xml.bind.annotation.XmlAttribute(name = "schemaLocation", namespace = "http://www.w3.org/2001/XMLSchema-instance")
        private final String schemaLocation = "http://xmlgw.companieshouse.gov.uk/v1-0/schema/forms/ReturnofAllotmentShares-v3-0.xsd";
      </annox:annotate>
    </xjc:extraAnnotation>
  </jxb:bindings>
  <!-- 其他元素类按相同规则配置即可,20份schema可以写简单脚本批量生成绑定规则 -->
</jxb:bindings>

如果使用Jakarta JAXB高版本,只需要把代码中javax.xml.bind包名替换为jakarta.xml.bind即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:15:09