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

使用Jaxb2Marshaller编组时如何为非根XML元素添加schemaLocation

解决OAI-PMH编组时<oai:oai-identifier>元素自动添加schemaLocation的问题

问题背景

使用Spring Boot 3/Java 17开发符合Open Archives Harvesting规范的OAI-PMH服务,通过OAI-PMH.xsd等Schema文件生成Java类,借助Spring的MarshallingHttpMessageConverter结合Jaxb2Marshaller输出XML响应。但编组后的XML无法通过验证,报错信息如下:

cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'oai:oai-identifier'.xml(cvc-complex-type.2.4.c)

经排查,问题出在非根元素<oai:oai-identifier>缺少正确的xsi:schemaLocation声明,手动为该元素添加后验证通过,现需实现编组过程中自动为该元素注入schemaLocation。

当前配置代码:

@Configuration
class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(
            @NonNull List<HttpMessageConverter<?>> converters) {

        var marshaller = new Jaxb2Marshaller();
        marshaller.setContextPaths(
                "org.openarchives.oai",
                "org.openarchives.oai_dc",
                "org.openarchives.oai_identifier",
                "org.purl.dc.elements");

        Map<String, ?> marshallerProperties = new HashMap<>() {
            {
                put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                put(Marshaller.JAXB_SCHEMA_LOCATION,
                        "http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd");
            }
        };

        marshaller.setMarshallerProperties(marshallerProperties);

        var converter = new MarshallingHttpMessageConverter(marshaller);
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        
        converters.add(0, converter);

    }
}

解决方案

1. 补充完整的schemaLocation映射

当前仅配置了OAI-PMH主Schema的位置,需将oai-identifier对应的命名空间和Schema地址加入Marshaller.JAXB_SCHEMA_LOCATION属性,多组映射用空格分隔:

put(Marshaller.JAXB_SCHEMA_LOCATION,
        "http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd " +
        "http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd");

2. 验证JAXB生成类的命名空间注解

检查org.openarchives.oai_identifier包下的生成类(如OaiIdentifier)是否带有正确的命名空间注解,示例如下:

@XmlRootElement(name = "oai-identifier", namespace = "http://www.openarchives.org/OAI/2.0/oai-identifier")
public class OaiIdentifier {
    // 类内容
}

若生成类无正确注解,需重新通过XJC工具生成(指定命名空间参数)或手动补充注解。

3. 修改后的完整配置代码

@Configuration
class WebConfig implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(
            @NonNull List<HttpMessageConverter<?>> converters) {

        var marshaller = new Jaxb2Marshaller();
        marshaller.setContextPaths(
                "org.openarchives.oai",
                "org.openarchives.oai_dc",
                "org.openarchives.oai_identifier",
                "org.purl.dc.elements");

        Map<String, ?> marshallerProperties = new HashMap<>() {
            {
                put(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                put(Marshaller.JAXB_SCHEMA_LOCATION,
                        "http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd " +
                        "http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd");
            }
        };

        marshaller.setMarshallerProperties(marshallerProperties);

        var converter = new MarshallingHttpMessageConverter(marshaller);
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        
        converters.add(0, converter);

    }
}

原理说明

JAXB的JAXB_SCHEMA_LOCATION属性支持同时配置多组命名空间与Schema文件的映射关系,当编组过程中遇到对应命名空间下的元素时,会自动在根元素(或对应元素的父节点)注入包含该映射的xsi:schemaLocation属性,确保XML验证时能找到<oai:oai-identifier>对应的Schema定义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:10:59