Xsd recursion of complexTypes - xsd

I am just learning XML/XSD and am struggling with the implementation of an XML-schema which models a folder structure.
What I had in mind was defining a complexType for the folder which can have additional folder instances that represent subfolders. Using the xsd schema validator here always returns that the schema is invalid.
I tried defining the complexType up front and then using the ref keyword for subfolders:
<xs:complexType name="tFolder">
<xs:sequence>
<xs:element name="Path" type="tFolderType" msdata:Ordinal="0" />
<xs:element ref="Folder" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="File" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="File_Text" msdata:Ordinal="0">
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Type" type="tFolderType" />
As for the element itself:
<xs:element name="Folder" type="tFolder" />
The error returned by the validator is:
"Cannot resolve the name 'Folder' to a(n) 'element declaration' component."
and the error occurs at the line
<xs:element ref="Folder" minOccurs="0" maxOccurs="unbounded" />
Defining the complexType within the element itself yields the exact same error:
<xs:element name="Folder">
<xs:complexType>
<xs:sequence>
<xs:element name="Path" type="tFolderType" msdata:Ordinal="0" />
<xs:element ref="Folder" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="File" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="File_Text" msdata:Ordinal="0">
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Type" type="tFolderType" />
</xs:complexType>
</xs:element>
What I've read, this kind of recursion should work using ref.
Can anyone tell me what I've done wrong? Maybe the xsd validator is just faulty? If so, does anyone know a better alternative? I've tried using the one from w3.org as well, but it seems to be taken offline...

I think this is the way to do it (don't use ref):
<element name="test" type="tns:TestType"></element>
<complexType name="TestType">
<sequence>
<element name="test" type="tns:TestType"></element>
</sequence>
</complexType>

Related

Using x:anyType instead of xsi:type gives Jaxb marshalling errors

I want to avoid xsi:type in an element and add the child elements at runtime based on some condition
I have option element defined as follows of type xs:anyType
<xs:complexType name="prod">
<xs:sequence>
<xs:element type="xs:anyType" name="option" minOccurs="0" maxOccurs="1"</xs:element>
</xs:sequence>
</xs:complexType>
used in element mapping as follows
<xs:element name="mappings">
<xs:complexType>
<xs:sequence>
<xs:element type="prod" name="productionSystem" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
I have need to add following option type as one of the following
<xs:complexType name="Text">
<xs:sequence>
<xs:element type="xs:short" name="id" />
<xs:element type="xs:string" name="name" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Value">
<xs:sequence>
<xs:element type="xs:short" name="id" />
<xs:element type="xs:string" name="name" />
<xs:element name="psValue" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="value" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
so basically one element option can be either of type Text or Value.
I want to avoid xsi:type in the xml. hence defined as xs:anyType. However at runt time Jaxb Marshalling fails with error
"any of its super class is known to this context". How to ensure Text and Value are in Jaxb Context.
Can someone pls guide on same.
Thanks,
Anjana

Can xsd parent element (base) be given default value in child (extension/restriction)?

I'm trying to do something like this:
<xs:complexType name="tSomeComponent">
<xs:sequence>
<xs:element name="table" type="xs:string" />
<xs:element name="key" type="tKey" />
<xs:element name="class" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="tStation">
<xs:complexContent>
<xs:restriction base="tSomeComponent">
<xs:sequence>
<xs:element name="table" type="xs:string" default="station" />
<xs:element name="name" type="xs:string" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
I know that table default value in child should be done by restriction but i want to extend and restrict at same time. I know that this can be solved by adding more types but that's an overkill.

XSD Schema that JAXB would find acceptable

I have a REST XML response that has a chunk of data like this:
<tag>
<total-pages type="integer">5</total-pages>
<previous-page nil="true"></previous-page>
<next-page nil="true"></next-page>
<offset type="integer">5</offset>
</tag>
Now, sometimes the data can come back like this:
<tag>
<total-pages type="integer">5</total-pages>
<previous-page type="integer">0</previous-page>
<next-page type="integer">1</next-page>
<offset type="integer">5</offset>
</tag>
I have been trying to come up with a XSD schema structure that will account for both possibilities that would be acceptable to JAXB.
I have tried:
<tag>
<total-pages type="numeric-type" />
<previous-page type="numeric-type" />
<next-page type="numeric-type" />
<offset type="numeric-type" />
</tag>
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:integer">
<xsd:attribute type="xsd:string" name="type" use="optional">
<xsd:attribute type="xsd:boolean" name="nil" use="optional">
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
but JAXB blows up with an unmarshalling error.
Thoughts on what XSD schema structure I could use to account for the variability in the returning XML (I cannot change the XML, it is coming from a third-party which I have no control).
Thank you,
Perry
I've started by generating one XSD from your XML samples (two in your case):
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="tag">
<xs:complexType>
<xs:sequence>
<xs:element name="total-pages">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:unsignedByte">
<xs:attribute name="type" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="previous-page">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="nil" type="xs:boolean" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="next-page">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="xs:string" use="optional" />
<xs:attribute name="nil" type="xs:boolean" use="optional" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="offset">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:unsignedByte">
<xs:attribute name="type" type="xs:string" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
When you compare with your XSD, you'll notice the use of string instead of integer as the base type. Which explains why you have a problem with unmarshalling: an empty string is not a valid number.
If instead of "nil" you would get an xsi:nil attribute, the XSD would've been generated differently, i.e. it would've had nillable="true" for your elements.
Since you cannot change the XML, then you're stuck with the use of string; alternatively, you could create a union between an empty string and a numeric value... as to how that'll look in JAXB, you can try it...

XS:any schemavalidation

I am getting validation error in the below xsd .
cos-nonambig: "http://alert.schemas.tr.com/TriggerSynchronizationService/Data/2010-02-08/":resyncRequestID and WC[##any] (or elements from their substitution group) violate
"Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
I think i did not declare xs:any properly.
<xs:complexType name="GenerationTriggerData">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="resyncRequestID" type="xs:int" />
<xs:element minOccurs="0" maxOccurs="1" name="userID" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="alertID" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="triggerID" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="logicalType" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="version" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="state" type="q1:State_Enum" />
<xs:element minOccurs="0" maxOccurs="1" name="criteria" xmlns:q2="http://expressions.schemas.tfn.thomson.com/2006-09-04/" type="q2:ExpressionRoot" />
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="skip"/>
</xs:sequence>
</xs:complexType>
XSD doesn't allow for ambiguous content. UPA is about the parser being able to figure out where it is relative to the XSD, unambiguously; even look-ahead is not allowed.
Since your xsd:any can be (##)any namespace, then resyncRequestID would match it; in that case, is that the first (optional) one, or the wildcard? Here the content is clearly ambigous and no look-ahead would help.
One way is to have xsd:any definition changed such that it won't match any of the content preceding it. Constraining the namespace is always an easy way to do it.
Alternatively, make the particle right before xsd:any mandatory. This way the reader would know where "the wild" begins...
If that is not an option, introduce a special "marker" tag right before xs:any; it must be mandatory!
The above are typically called "refactoring an XSD" to satisfy XSD's UPA design constraint.

Question about xsd. Elements inside complex type must be allowed in any order

If you look at the following xsd fragment you can conclude that the corresponding xml will first contain cars followed by busses eg:
car,car,bus,bus
HOWEVER I want the xml to be able to contain
car,bus,car,bus
What change do I need to make in the xsd below in order to achieve this?
<xs:element name="body">
<xs:complexType>
<xs:sequence>
<xs:element name="session" type="tns:session" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="tns:car" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="tns:bus" />
</xs:sequence>
</xs:complexType>
</xs:element>
It's a bit cumbersome, but you might achieve what you're looking for like this:
create a <xs:choice> element with your car and bus elements inside; this defines that one of the contained elements can be used
make sure to have the attribtues minOccurs=1 and maxOccurs=unbounded on that <xs:choice> - this gives you any number of either car or bus elements - any number, any combination
So your XML schema would look something like this (I added some stuff just to be able to generate a sample XML and verify it works - tweak as needed):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="body">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" name="car" type="CarType" />
<xs:element minOccurs="0" maxOccurs="unbounded" name="bus" type="BusType" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="CarType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="BusType">
<xs:sequence>
<xs:element name="Maker" type="xs:string" />
<xs:element name="Capacity" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
use <xs:any> insted of <xs:sequence>

Resources