使用命名空间扩展的java jaxb致命验证错误

时间:2015-03-12 20:01:36

标签: xml jaxb xml-namespaces jaxp

我有一个基本的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 - Line:8,Severity:2,cvc-complex-type.2.4.d:找到以元素'base:TypeTwo'开头的无效内容。此时不会有子元素。

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

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

这是杀了我......

1 个答案:

答案 0 :(得分:0)

我最近发现了这里发生的事情。我在unmarshaller中使用的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而没有任何验证错误。