【问题标题】:java jaxb fatal validation error using namespace extensions使用命名空间扩展的 java jaxb 致命验证错误
【发布时间】:2023-03-23 07:25:01
【问题描述】:

我有一个基本的 XML 模式,我必须使用 xs:redefine 对其进行扩展,然后从第二个模式添加一些扩展。当我解组时遇到致命错误: cvc-complex-type.2.4.d:发现以元素“base:TypeTwo”开头的无效内容。此时不应有子元素。 即使其他解析器说 XML 完全有效。

所以我的基本标签是

<xs:element name="Root">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="TypeThree" minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:complexType name="TypeTwo">
</xs:complexType>
<xs:element name="TypeTwo" type="TypeTwo" />

<xs:group name="TypeThreeExtension">
    <xs:sequence />
</xs:group>

<xs:complexType name="TypeThree">
    <xs:sequence>
        <xs:group maxOccurs="unbounded" minOccurs="0" ref="TypeThreeExtension" />
    </xs:sequence>
</xs:complexType>
<xs:element name="TypeThree" type="TypeThree" />

只有一个根和两个元素,一个带有一个用于扩展的组。

我的扩展标签是:

<xs:schema targetNamespace="http://www.example.com/extension"
       elementFormDefault="qualified" 
       xmlns="http://www.example.com/extension"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:base="http://www.example.com/base"
        xmlns:ext="http://www.example.com/extension"
    >

<xs:import schemaLocation="base.xsd" namespace="http://www.example.com/base"/>

 <xs:complexType name="ExtTypeOne">
    <xs:sequence>
         <xs:element ref="base:TypeTwo" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>  
</xs:complexType>
<xs:element name="ExtTypeOne" type="ExtTypeOne" />

所以只有一种附加类型,它包含 base 类型之一(这似乎是重要因素)。

redefine.xsd 是

<xs:schema targetNamespace="http://www.example.com/base"
elementFormDefault="qualified" xmlns="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension" xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:import schemaLocation="extension.xsd" namespace="http://www.example.com/extension" />

<xs:redefine schemaLocation="base.xsd">
    <xs:group name="TypeThreeExtension">
        <xs:sequence>
            <xs:element ref="ext:ExtTypeOne" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:group>
</xs:redefine>

所以这里我只是扩展了基本的 TypeThreeExtension 组,以便我现在可以在下面添加 ExtTypeOne 标记。这基本上允许标签的结构是:

  • 基地
    • 分机
      • 基础

当我加载以下 XML 进行解组时...

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root 
xmlns="http://www.example.com/base" 
xmlns:base="http://www.example.com/base"
xmlns:ext="http://www.example.com/extension">   
    <TypeThree>
        <ext:ExtTypeOne>
            <base:TypeTwo/>
        </ext:ExtTypeOne>
    </TypeThree>
</Root>

我收到以下错误:

ValidationEvent 1 - 行:8,严重性:2,cvc-complex-type.2.4.d:发现以元素“base:TypeTwo”开头的无效内容。此时不需要子元素。

无论我做什么,我都无法摆脱这个错误。事实上 - 即使我将对象 编组 到 XML 中,JAXB 实际上会创建 XML,然后它(在解组时)报告是无效的。这是一个 JAXB 错误吗?

FWIW - 我可以说它是导致它的 base-ext-base 嵌套。将重新定义的模式中的类型嵌套在第二个模式的标记下是否无效?我需要创建不同的目标命名空间吗?

这可要了我的命……

【问题讨论】:

    标签: xml jaxb xml-namespaces jaxp


    【解决方案1】:

    我最近弄清楚这里发生了什么。我在解组器中使用的 Schema 对象是从 JaxbContext 对象动态生成的。代码看起来像这样......

    CONTEXT = JAXBContext.newInstance(Root.class);
            final Collection<StreamResult> results = new ArrayList<StreamResult>();
            CONTEXT.generateSchema(new SchemaOutputResolver() {
                @Override
                public Result createOutput(String arg0, String suggestedFileName) throws IOException {
                    System.out.println("create output: "+arg0+" "+suggestedFileName);
                    StreamResult result = new StreamResult();
                    result.setSystemId(suggestedFileName);
                    results.add(result);
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    result.setOutputStream(baos);
                    return result;
                }
            });
            Collection<StreamSource> sss = new ArrayList<StreamSource>();
            for(StreamResult r : results){
                ByteArrayOutputStream baos = ((ByteArrayOutputStream)( r.getOutputStream()));
                StreamSource ss = new StreamSource(new ByteArrayInputStream(baos.toByteArray()),r.getSystemId());
                sss.add(ss);
            }
            Schema sm = schemaFactory.newSchema(sss.toArray(new StreamSource[]{}));
    

    然而,动态生成的模式似乎没有包含足够的细节来对这种类型的模式扩展执行正确的验证。所以我不得不用一种更直接的技术来替换这种技术,这种技术直接在类路径上引用 XSD。此方法的代码如下所示:

    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(new Source[]{
                        new StreamSource(new File("./src/main/resources/redefine.xsd"))
                });
    

    这个新的 Schema 对象验证 XML,没有任何验证错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 2013-12-06
      相关资源
      最近更新 更多