0

I have a base XML schema that I have to extend using xs:redefine, and then add some extensions to from a second schema. When unmarshalling im getting a fatal error: cvc-complex-type.2.4.d: Invalid content was found starting with element 'base:TypeTwo'. No child element is expected at this point. Even when other parsers say the XML is completely valid.

So my base tags are

<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" />

Just a root, and two elements, one with a group for extension.

My extension tags are:

<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" />

So just one additional type, that contains one of the base types (this seems to be the important factor).

The redefine.xsd is

<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>

So here im just extending the base TypeThreeExtension group so that I can now add the ExtTypeOne tag below. This basically allows a structure of tags is:

  • Base
    • Extension
      • Base

When I load the following XML for unmarshalling...

<?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>

I get the following error:

ValidationEvent 1 - Line: 8, Severity: 2, cvc-complex-type.2.4.d: Invalid content was found starting with element 'base:TypeTwo'. No child element is expected at this point.

Regardless of what I do I cannot get rid of this error. In fact - even when I marshall the objects into XML, JAXB actually creates XML which it then (upon unmarshalling) reports is invalid. Is this a JAXB bug?

FWIW - I can tell that its the base-ext-base nesting that causes it. Is it invalid to nest a type from a redefined schema under a tag from a second schema? Do i need create different target namespaces or something?

This is killing me...

The Shoe Shiner
  • 697
  • 4
  • 20

1 Answers1

0

I recently figured out what was happening here. The Schema object I was using in the unmarshaller was generated dynamically off of the JaxbContext object. The code looked something like this...

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[]{}));

However it seems the dynamically generated schemas do not contain enough of the details to perform correct validation on this type of schema extension. So I had to replace this technique with a more direct technique that references the XSD directly on the classpath. The code for this method looks like this:

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"))
            });

This new Schema object validates the XML without any validation errors.

The Shoe Shiner
  • 697
  • 4
  • 20