complexContent restriction: is it XSD 1.0 or Xerces causing this behavior change? - xsd

Here is a small schema, and a sample XML file, that will validate successfully at the Xerces-J online validation service if XSD version 1.1 is selected, but not XSD 1.0.
With 1.0 selected, the schema itself is rejected, as invalidly deriving t2 from t1. (The intent is that t1 allows an optional thing and some stuff, and t2 is a restriction that keeps the stuff but forbids the thing.)
The exact complaint from Xerces-J with 1.0 selected is:
[Error] foo.xsd:19:28:rcase-Recurse.1: Group's occurrence range, (0,unbounded), is not a valid restriction of base group's occurrence range, (1,1).
[Error] foo.xsd:19:28:derivation-ok-restriction.5.4.2: Error for type 't2'. The particle of the type is not a valid restriction of the particle of the base.
I think what happens is the containing <sequence> in t2 gets considered "pointless" (2.2.2.2.1 here) because it now has only one child, but the corresponding <sequence> in t1 is not "pointless" because it has two children, and the derivation checker is trying to match the minOccurs and maxOccurs of t2's <group> against those of t1's <sequence>. Somehow, the checker for XSD 1.1 manages to be smarter than that.
So my question (ok, two questions):
Is this behavior in 1.0 an inherent known limit of XSD 1.0 that the derivation rules in 1.1 were updated to fix, or is it a limit of the Xerces-J implementation of 1.0? Does anybody have a 1.0 implementation that accepts this schema?
Given the continued deployment of tools that use 1.0, does anyone know an alternate way to write this schema that will work in 1.0? (I can make this example work by losing the <group> and inlining the <stuff> element both places, but that's not a plan if the real-life group has more than one child).
Edit: even the inlining workaround is unavailing if the element heads a substitution group. That gets reified here as a <choice> group, which again has its minOccurs and maxOccurs mismatch those of the base type's <sequence>.
foo.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="foo:bar"
xmlns="foo:bar">
<xs:group name="stuffGroup">
<xs:sequence>
<xs:element name="stuff"/>
</xs:sequence>
</xs:group>
<xs:complexType name="t1">
<xs:sequence>
<xs:element name="thing" minOccurs="0"/>
<xs:group ref="stuffGroup" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="t2">
<xs:complexContent>
<xs:restriction base="t1">
<xs:sequence>
<xs:group ref="stuffGroup" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:element name="a" type="t2"/>
</xs:schema>
foo.xml:
<a xmlns='foo:bar'/>

The Microsoft .NET XSD 1.0 based schema validator rejects your schema with an error in line 19 saying (citing first the German message I get from VS): "
Warnung Ungültige Partikelableitung durch Einschränkung - 'Gemäß All:All,Sequence:Sequence -- Recurse-Regel 1 oder Choice:Choice -- RecurseLax ist der Bereich des abgeleiteten Partikels keine gültige Einschränkung des Basispartikelbereichs.'." which I would translate roughly as "Warning invalid particle inference by restriction - according to All:All,Sequence:Sequence -- Recurse-rule 1 oder Choice:Choice -- RecurseLax is the domain of the inferred particle no valid restriction of the base particle domain".
Xmllint ("xmllint: using libxml version 20910"), on the other hand, when trying to validate the sample against the schema with e.g. command line options --schema schema1.xsd sample1.xml reports:
<?xml version="1.0"?>
<a xmlns="foo:bar"/>
sample1.xml validates
I will need to dig deeper in the schema specs the judge what is the right behaviour.

Related

JAXB: Ignore order of elements while using xs:extension

We are using JAXB for Java-xml binding.We initially created domain class and then using schemagen commandline tool the following schema has been generated. But generated schema is not valid, giving following error message.
Error Message:
cos-all-limited.1.2: An all model group must appear in a particle with {min occurs} = {max occurs} = 1, and that particle must be part of a pair which constitutes the {content type} of a complex type definition.
Use Case:
There are two classes Emp(Base class) and Dept(Child class).
1. There is no restriction on the elements sequence(means empId, deptId and deptName can appear in any order). so we used xs:all element
2. In Dept class, deptId field should appear only once(minOccurs =1, maxOccurs=1) and deptName is optional.
As per my usecase i am unable to generate valid schema. I did search on google. But i couldn't find the solution. So i am anticipating experts can answer this query. Could you please look into below classes,schema and guide me in the right direction.
NOTE: please don't suggest me to create some temporary domain classes.
Thanks in anticipation.
Emp.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name="EmpType", propOrder={})
#XmlRootElement
public class Emp {
#XmlElement(name="empId", required = true)
private String empId;
}
Dept.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name="DeptType", propOrder={})
public class Dept extends Emp
{
#XmlElement(name="deptId", required = true)
private String deptId;
private String deptName;
}
Schema1.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="emp" type="EmpType"/>
<xs:complexType name="EmpType">
<xs:sequence>
<xs:element name="empId" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="DeptType">
<xs:complexContent>
<xs:extension base="EmpType">
<xs:all> <!--showing error message, mentioned above -->
<xs:element name="deptId" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="deptName" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
The document structure that you are trying to allow is actually difficult to represent in an XML schema. You may not be able to generate it from a JAXB (JSR-222) annotated model. You do however have a couple of options:
Option #1 - Generate a Simpler XML Schema
If you are not validating XML content with your XML schema and are simply using it as documentation that people can use as a guide then I would drop the all sections and use sequence instead. This will work better with the inheritance relationship that you have. If you don't specify an instance of Schema on the Unmarshaller the order of elements is not enforced so you will be able to read all the XML documents that meet your rules.
Option #2 - Create Your Own XML Schema
If you want the XML schema to exactly reflect all the possible accepted inputs then you will need to write it yourself. You can reference this existing XML schema by using the package level #XmlSchema annotation.
#XmlSchema(location = "http://www.example.com/package/YourSchema.xsd")
package com.example;
import javax.xml.bind.annotation.XmlSchema;

Unmarshalling based on Concrete Instance

I am a new comer to JaxB World and I am facing one problem w.r.t. unmarshalling of the stored xml content into java class object. Problem description is as follows. Let me know if this is solvable
I have my xsd file which contains following content(this is just a example)
Student info
<xs:complexType name="specialization" abstract="true">
</xs:complexType>
<xs:complexType name="Engineering">
<xs:complexContent>
<xs:extension base="specialization">
<xs:sequence>
<xs:element name="percentage" type="xs:int" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Medical">
<xs:complexContent>
<xs:extension base="specialization">
<xs:sequence>
<xs:element name="grade" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Now all the corresponding java classes are generated by compiling the xsd. Now lets assume in my application i will set the specialization attribute of Student info by constructing Engineering class instance. So after all the operation when i save
the xml file that get saved will have the entry like below
<Student>
<Name>Name1</Name>
<Specialization>
<percentage>78<percentage>
</Specialization>
</Student>
Now when the above content goes for unmarshalling, unmarshalling fails saying unexpected element . I guess this is b'cos Specialization element is of type specialization it calls unmarshalling on itself rather than derived object which is stored.
I hope my explanation is clear. Is there any way that we can unmarshall based on derived class instanse type. The xsd and bindings.xjb file is completely in my control so i can add or modify any entries/info which conveys to unmarshalling rules to unmarshall on derived class.
Thanks for your Suggestion but the it still not working for me.
Here is what I tried
Option #1 - xsi:type
My xsd looks same as what is explained in the example but still the Xsi:type doesn't come in the resulted xml. Do i need to add any other setting while compiling? Which JaxB version should i use for this?
Option#2 - Substitution Groups
When i added the substitution entry part in my xsd, XSD compilation failed saying duplicate names "Engineering" and "Medical". I guess element name and type Name being same compilation cribs(All engineering, Medical,specialization being same both in type definition and element Name)
I can't modify the generated classes as we are using Model driven Architecture. Only thing that is in hand is xsd. Any modification to the xsd is allowed. Ideally First option should have worked. But can't figure out why it is not working. Let me know if you have some suggestion to narrow down the problem.
There are different ways of representing Java inheritance in XML when using JAXB:
Option #1 - xsi:type
In this representation an attribute is used to indicate the subtype being used to populate this element.
<Student>
<Name>Name1</Name>
<Specialization xsi:type="Engineering">
<percentage>78<percentage>
</Specialization>
</Student>
For a detailed example see:
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.htmlhtml
Option #2 - Substitution Groups
Here an element name is used to indicate the subtype. This corresponds to the schema concept of substitution groups and leverages JAXB's #XmlElementRef annotation:
<Student>
<Name>Name1</Name>
<Engineering>
<percentage>78<percentage>
</Engineering>
</Student>
For a detailed example see:
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html

InstantiationException during JAXB Unmarshalling (abstract base class, with #XmlSeeAlso concrete sub class)

I am running into JAXB Unmarshalling error as below.
The foo.bar.Base is an abstract class, with an #XmlSeeAlso annotation, which lists foo.bar.SubBase (which is a concrete subclass of foo.bar.Base)
Both of the above classes are statically reachable from a main/entry class: com.example.Request
The JAXBContext is create using the packages string variant viz:
JAXBContext.newInstance("com.example",...);
The above created JAXBContext correctly lists all the three classes : com.example.Request, foo.bar.Base and foo.bar.SubBase as "classes known to this JAXBContext"
But it fails at runtime during the unmarshal call below.. I am unable to figure out what is wrong here.
unmarshaller.unmarshal(<some-DOM-Element-Instance>, com.example.Request.class);
Any pointers will be appreciated!
Thanks!
The stacktrace is:
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of foo.bar.Base - with linked exception: [java.lang.InstantiationException]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:609)
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:181)
at com.sun.xml.bind.v2.runtime.unmarshaller.XsiTypeLoader.startElement(XsiTypeLoader.java:76)
at com.sun.xml.bind.v2.runtime.unmarshaller.ProxyLoader.startElement(ProxyLoader.java:55)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:481)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)
at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:71)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:148)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:239)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:276)
at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:245)
at com.sun.xml.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:122)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:314)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:293)
Caused by: java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:123)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:261)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:603)
... 69 more
EDIT #Blaise and #Ross
Thank you very much Blaise and Ross for your pointers. I think I should have included the schema that is being worked off, here.
The relevant schema looks like this:
<xs:complexType name="Request">
<xs:sequence>
<xs:element name="selectedBase" form="unqualified" nillable="true" type="xs:anyType" minOccurs="0"/>
<xs:element name="selectedSubBase" form="unqualified" nillable="true" type="ns1:SubBase" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Base">
<xs:sequence>
<xs:element name="ID" form="unqualified" nillable="true" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="SubBase">
<xs:complexContent>
<xs:extension base="ns1:Base">
<xs:sequence>
<xs:element name="subBaseElement" form="unqualified" nillable="true" type="xs:anyType" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
So the schema doesn't have substitution group definition (so I guess #XmlElementRef doesn't apply here, or would it still work?), but is using extension. The payload will be :
<ns:Request>
<selectedBase>123</selectedBase>
<selectedSubBase>
<ID>321</ID>
<subBaseElement>123</subBaseElement>
</selectedSubBase>
</ns:Request>
So , the element in the payload occuring is <selectedSubBase> and not <selectedBase xsi:type="ns:SubBase"/>
So which strategy would apply here?
The #XmlSeeAlso annotation is used as a convenience mechanism to tell your JAXB impl that metadata should also be created for the referenced classes. While it is most often used to specify subclasses it is not a mechanism to configure inheritance relationships.
Since JAXB is attempting to instantiate an instance of the abstract super class (foo.bar.Base), it appears as though your XML message does not contain enough information to specify the correct sub-type to be unmarshalled.
This can be done with the xsi:type attribute:
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html
You can also use substitution groups (#XmlElementRef), where the element name is used to determine the appropriate sub-type:
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html
JAXB implementations (such as EclipseLink JAXB (MOXy)), also contain extensions for handling inheritance:
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-moxy-extension.html
And if you would like to ignore the inheritance relationship altogether you can use the #XmlTransient annotation:
http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html
You need to be using XmlElementRef on the field containing the reference to Base, to tell JAXB that it should look at subclasses. JAXB is clearly trying to instantiate your base class (which it can't do, of course).
Have a look at XmlElementRef's docs.
try #XmlSeeAlso
#XmlSeeAlso({ExchangeFormat.class}) public abstract class MapperJsonXml <T>
#XmlRootElement(name="ExchangeFormat") public class ExchangeFormat extends MapperJsonXml<ExchangeFormat>
it works

Creating a valid XSD that is open using <all> and <any> elements

I need to specify a XSD for validating XML documents. The XSD will be used for a JAXB generation of Java bindings.
My problem is specifying optional elements which I do not know the names of and which I in general am not interested in parsing.
The structure of the XML documents is like:
<TRADE>
<TIME>12:12</TIME>
<MJELLO>12345</MJELLO>
<OPTIONAL>12:12</OPTIONAL>
<DATE>25-10-2011</DATE>
<HELLO>hello should be ignored</HELLO>
</TRADE>
The important thing is, that:
I can not assume any order, and the next XML document instance migtht have tags in a different order
I am only interested in parsing some of the tags, some are mandatory and some are optional
The XML documents can be extended with new elements which I am not interested in parsing
The structure of my XSD is like (not a valid xsd):
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- *********************************************** -->
<!-- Trade element definitions for the XML Documents -->
<!-- *********************************************** -->
<xs:complexType name="Trade">
<!-- Using the all construction ensures that the order does not matter -->
<xs:all>
<xs:element name="DATE" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="TIME" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="OPTIONAL" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:any minOccurs="0"/>
</xs:all>
</xs:complexType>
<!-- TRADE is the mandatory top-level tag -->
<xs:element name="TRADE" type="Trade"/>
</xs:schema>
So, in this example: DATE and TIME are mandatory (they must be in the XML exactly once), OPTIONAL might be present once and then I would like to specify, that all other tags are allowed. The order does not matter.
How do I specify a valid XSD for this?
This is a classic parser problem.
Basically, your BNF is:
Trade = whatever whatever*
whatever = "DATE" | "TIME" | anything
anything = a-z a-z*
But this is ambigous. The string "DATE" can both be accepted under the whatever rule as "DATE" and as anything.
So if you have
<TRADE>
<TIME>12:12</TIME>
<DATE>25-10-2011</DATE>
<DATE>25-12-2011</DATE>
</TRADE>
it is unclear whether that should be accepted or not.
It could be interpreted either one of
"TIME", "DATE", anything
anything, anything, "DATE"
anything, anything, anything
"TIME", "DATE", anything
"TIME", "DATE", "DATE"
etc.
It all boils down to: If you have a wildcard combined with random sequence, you cannot meaningfully decide which token matches which rule.
It especially does not make sense to have optional elements together with a wilcard.
You have two options:
use xs:sequence instead of xs:all
do not use wildcard
As I understand it, both options are in conflict with your wishes.
Perhaps you can construct a wildcard that matches everything except DATE, TIME etc.
Is it a hard requirement to have JAXB bindings to your "known" elements?
If not, you can basically have just <any maxoccurs="unbounded" processContents="skip"/> as your xsd, and then pick out the elements you are interested in from the DOM tree.
(See here how to use JAXB without data binding.)

XSD: difference between Element and Attribute

I'm new to XSD, and I'm quite confused as to when to use attribute, and when to use element?
Why cant we specify minOccurs and maxOccurs in attribute?
Also, why is it we cannot specify use="required" in element?
An element is an XML element - a opening tag, some content, a closing tag - they are the building blocks of your XML document:
<test>someValue</test>
Here, "test" would be an element.
Attributes is an additional info on a tag - it's an "add-on" or an extra info on an element, but can never exist alone:
<test id="5">somevalue</test>
"id" is an attribute.
You cannot have multiple attributes of the same name on a single tag --> minOccurs/maxOccurs makes no sense. You can define required (or not) for an attribute - anything else doesn't make sense.
The elements are defined by their occurrence inside complex types - e.g. if you have a complex type with a <xs:sequence> inside - you are defining that all elements must be present and must the in this particular order:
<xs:complexType name="SomeType">
<xs:sequence>
<xs:element name="Element1" type="xs:string" />
<xs:element name="Element2" type="xs:string" />
</xs:sequence>
</xs:complexType>
Inside an element of that type, the sub-elements "Element1" and "Element2" are required and must appear in this order - there's no need for "required" or not (like with attributes). Whether or not an element is required is defined by the use of minOccurs and maxOccurs; both are =1 by default, e.g. the element must occur, and can only occur once. By tweaking those settings, you can define an element to be optional (minOccurs=0), or allow it to show up several times (maxOccurs > 1).
I'd strongly recommend you check out the W3Schools Tutorial on XML Schema and learn some more about XML schema.
Marc
Example: XSD Format
<xs:complexType name="contactInformation">
<xs:all>
<xs:element name="firstName" type="xs:string" minOccurs="0"/>
<xs:element name="workCountryId" type="xs:long" minOccurs="0"/>
</xs:all>
<xs:attribute name="id" type="xs:long"/>
</xs:complexType>
XML Format
<contactInformation id=100>
<firstname>VELU</firstname>
<workCountryId>120</workCountryId>
</contactInformation>
attribute is optional by default. To specify that the attribute is required, use the use attribute:
e.g. <xs:attribute name="id" type="xs:long" use="required"/>
More about attributes and elements.
A complexType element is an XML element that contains other elements and/or attributes.
The all element specifies that the child elements can appear in any order and that each child element can occur zero or one time.
maxOccurs Optional. Specifies the maximum number of times the element can occur. The value must be 1.
minOccurs Optional. Specifies the minimum number of times the element can occur. The value can be 0 or 1. Default value is 1
An element is an XML node - and it can contain other nodes, or attributes. It can be a simple type or a complex type. It is an XML entity.
An attribute is a descriptor. It can't contain anything and can only be a simple type.
Have a look at this. Of course, you can just google something like "XML element vs attribute"
<element myAttribute="value">
<subElement />
<subElement anotherAttribute="this is an attribute's value">Element value</subElement>
</element>
You can't have more than one attribute with the same name in XML, therefore you can't use minOccurs and maxOccurs for attributes.
You don't need use="required" for elements because you can have minOccurs="1" instead.
It is your choice when to use attributes and when to use elements. Here are some guidelines: http://www.ibm.com/developerworks/xml/library/x-eleatt.html

Resources