I want to create an XSD for one application and another XSD wich extends the first (only by adding elements).
I want the XML file generated by the second application to be valid with the first one.
I tried this:
First XSD:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns="example"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="example"
elementFormDefault="qualified" attributeFormDefault="qualified">
<xs:complexType name="typeA">
<xs:sequence>
<xs:element name="elA" type="xs:string" />
<xs:any namespace="##any" minOccurs="0" processContents="lax" />
</xs:sequence>
</xs:complexType>
<xs:element name="root" type="typeA" />
</xs:schema>
Second XSD:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns="example"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="example">
<xs:redefine schemaLocation="firstXSD.xsd">
<xs:complexType name="typeA">
<xs:complexContent>
<xs:extension base="typeA">
<xs:sequence>
<xs:element name="newElement" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
</xs:schema>
Example of XML which must be valid with the first XSD (but not the second):
<?xml version="1.0" encoding="UTF-8" ?>
<root xmlns="example">
<elA>MyString</elA>
</root>
Example of XML which must be valid with both XSD
<?xml version="1.0" encoding="UTF-8" ?>
<root xmlns="example">
<elA>MyString</elA>
<newElement>MyNewString</newElement>
</root>
The previous XSD violate the “Unique Particle Attribution” and I want this to be fixed.
I can edit both XSD, but I want to be able to distribute the first one before finishing the second one.
How can I make this possible (both schemas must be valid when checked by JAXB) ?
Thanks
Some people may say: if you can edit both XSDs, why bother with redefine?
I’ll show you how you can make it work with XSD redefine, at least from an XSD perspective. However, given limitations with JAXB, it’ll not work with it out of the box. If you also use automatic XSD refactoring, as an extra step, then you can make it work and, in the process, you’ll be preserving the value proposition that you see when using xsd:redefine.
So, before that, here is another way which also uses composition, but without
xsd:redefine; from a maintenance and validation perspective, you’re getting about the same value and usage.I’ll refer to your first XSD as
Model1and your second XSD asModel2. I’ll start with one XSD that will give you the “reuse-through-composition” aspect you have withxs:redefine.Common items, xsd-allow-extension-compatibility-and-validation-common-items.xsd:
Model1 “items”, xsd-allow-extension-compatibility-and-validation-model1-items.xsd:
Model2 “items”, xsd-allow-extension-compatibility-and-validation-model2-items.xsd:
If you pass Common Items and Model1, or Common Items and Model2 to JAXB compiler, it’ll create the classes exactly the way you want. For easy of use (testing) and illustration, I’ve created two more XSDs:
Model1:
Model2:
This is what you get when you run xjc agains Model1:
… and when you run xjc agains Model2:
Model1 and Model2 XSDs will validate your XMLs exactly the way you’ve intended.
Below if a diagram showing the relationship between the XSD files. Green means “xsd:include”, and the arrow points to the “included”.
UPDATE: I just noticed, based on @Kevin ‘s comment, that you don’t have a maxOccurs on your new element in the redefine. In this case, you could use one single redefine, like so:
The only problem seems to be that JAXB (latest) still generates a class using the wildcard.
Update 2: Based on Kevin’s comment, two avoid two redefines, a group should be used instead of xsd:any.
If you in fact plan to use more than one element to extend the new model, then read on. Below is the only way to do that, which requires the use of a group to further refine the any particles.
The net result is that the new XSD can be used to validate Model1, while the original file remains Model1.