XSD inheritance causes problems in Jersey/JAXB - jaxb

I have the following XSD file (contents shown):
<xs:element name="person" type="Person"/>
<xs:element name="child" type="Child"/>
<xs:complexType name="Person">
<xs:sequence>
<xs:element name="age" type="xs:int"/>
<xs:element name="sex" type="xs:string"/>
<xs:element name="fullname" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Child">
<xs:complexContent>
<xs:extension base="Person">
<xs:sequence>
<xs:element name="grade" type="xs:string"/>
<xs:element name="school" type="xs:string"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
I'm able to marshal instances of the Child class and send them to a client browser using the Jersey REST API.
But when I try to do this for the Person class it no longer works. I get the error message:
A message body writer for Java class app.Person, and Java type class app.Person, and MIME media type application/xml was not found
By extending the Person schema type, am I somehow rendering it no longer a root-level element? When Child doesn't extend Person, it works fine.

Related

Using XSD in PySpark

I am building a datawarehouse in Azure Synapse where one of the sources are about 20 different types of XML files (with a different XSD scheme) and 1 base scheme.
What I am looking for is to get all XML elements and store them in files (1 per type) in my data lake. For that I need to have unique names per element, for example the whole path as a name. I tried to define dicts per type with all element names, but this is quite some work. To automate this (XSDs are updated yearly), I tried to code this out in Excel and VBA, but the XSDs are quite complex with nested complex types etc.
Below is a snippet of the baseschema.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.website.org/typ/1/baseschema/schema" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:iwmo="http://www.website.org/typ/1/baseschema/schema">
<xs:complexType name="Complex_Address">
...
<xs:sequence>
<xs:element name="Home" type="iwmo:Complex_House" minOccurs="0">
...
</xs:element>
<xs:element name="Postalcode" type="iwmo:Simple_Postalcode" minOccurs="0">
...
</xs:element>
<xs:element name="Streetname" type="iwmo:Simple_Streetname" minOccurs="0">
...
</xs:element>
<xs:element name="Areaname" type="iwmo:Simple_Areaname" minOccurs="0">
...
</xs:element>
<xs:element name="CountryCode" type="iwmo:Simple_CountryCode" minOccurs="0">
...
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Complex_House">
...
<xs:sequence>
<xs:element name="Housenumber" type="iwmo:Simple_Housenumber">
...
</xs:element>
<xs:element name="Houseletter" type="iwmo:Simple_Houseletter" minOccurs="0">
...
</xs:element>
<xs:element name="HousenumberAddition" type="iwmo:Simple_HousenumberAddition" minOccurs="0">
...
</xs:element>
<xs:element name="IndicationAddress" type="iwmo:Simple_IndicationAddress" minOccurs="0">
...
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Complex_MessageIdentification">
...
<xs:sequence>
<xs:element name="Identification" type="iwmo:Simple_IdentificationMessage">
...
</xs:element>
<xs:element name="Date" type="iwmo:Simple_Date">
...
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Complex_Product">
...
<xs:sequence>
<xs:element name="Categorie" type="iwmo:Simple_ProductCategory">
...
</xs:element>
<xs:element name="Code" type="iwmo:Simple_ProductCode" minOccurs="0">
...
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Complex_XsdVersion">
<xs:sequence>
<xs:element name="BaseschemaXsdVersion" type="iwmo:Simple_Version">
</xs:element>
<xs:element name="MessageXsdVersion" type="iwmo:Simple_Version">
</xs:element>
</xs:sequence>
</xs:complexType>
And here a snippet of the xsd of 1 of the message types:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:typ="http://www.website.org/typ/1/baseschema/schema" xmlns:type1="http://www.website.org/typ/1/type1/schema" targetNamespace="http://www.website.org/typ/1/type1/schema" elementFormDefault="qualified">
<xs:import namespace="http://www.website.org/typ/1/baseschema/schema" schemaLocation="baseschema.xsd"></xs:import>
<xs:element name="Message" type="type1:Root"></xs:element>
<xs:complexType name="Root">
...
<xs:sequence>
<xs:element name="Header" type="type1:Header"></xs:element>
<xs:element name="Client" type="type1:Client"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Header">
<xs:sequence>
<xs:element name="Person" type="typ:Simple_SpecialCode">
...
</xs:element>
<xs:element name="MessageIdentification" type="typ:Complex_MessageIdentification">
...
</xs:element>
<xs:element name="XsdVersion" type="typ:Complex_XsdVersion">
...
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Client">
...
<xs:sequence>
<xs:element name="AssignedProducts" type="type1:AssignedProducts"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AssignedProducts">
<xs:sequence>
<xs:element name="AssignedProduct" type="type1:AssignedProduct" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AssignedProduct">
...
<xs:sequence>
<xs:element name="ToewijzingNummer" type="typ:Simple_Nummer">
...
</xs:element>
<xs:element name="Product" type="typ:Complex_Product" minOccurs="0">
...
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Then this would be the desired output:
Header_Person
Header_MessageIdentification_Identification
Header_MessageIdentification_Date
Header_XsdVersion_BaseschemaXsdVersion
Header_XsdVersion_MessageXsdVersion
Client_AssignedProduct_ToewijzingNummer
Client_AssignedProduct_Product_Category
Client_AssignedProduct_Product_Code
In the baseschema I also added a nested complex type, to show the complexity.
Is there some kind of package or something in Python that can help me achieve this? Also a tool that can just create this list of elements in a text file would be great, I then can easily copy that into a variable.
I'm not sure if I'm clear about my requirements, if this is posted in the correct group with the correct tags, but I hope someone can point me into a good solution.
Ronald
I found a workaround after all where I put all fields from the xsds in variables. It's not ideal, but any other way would be too complex.

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

Difference between group and sequence in XML Schema?

What is the difference between an xs:group and an xs:sequence in XML Schema? When would you use one or the other?
xs:sequence - together with xs:choice and xs:all - is used to define the valid sequences of XML element in the target XML. E.g. the schema for this XML:
<mainElement>
<firstSubElement/>
<subElementA/>
<subElementB/>
</mainElement>
is something like:
<xs:element name='mainElement'>
<xs:complexType>
<xs:sequence>
<xs:element name="firstSubElement"/>
<xs:element name="subElementA"/>
<xs:element name="subElementB"/>
</xs:sequence>
</xs:complexType>
</xs:element>
xs:group is used to define a named group of XML element following certain rules that can then be referenced in different parts of the schema. For example if the XML is:
<root>
<mainElementA>
<firstSubElement/>
<subElementA/>
<subElementB/>
</mainElementA>
<mainElementB>
<otherSubElement/>
<subElementA/>
<subElementB/>
</mainElementB>
</root>
you can define a group for the common sub-elements:
<xs:group name="subElements">
<xs:sequence>
<xs:element name="subElementA"/>
<xs:element name="subElementB"/>
</xs:sequence>
</xs:group>
and then use it:
<xs:element name="mainElementA">
<xs:complexType>
<xs:sequence>
<xs:element name="firstSubElement"/>
<xs:group ref="subElements"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="mainElementB">
<xs:complexType>
<xs:sequence>
<xs:element name="otherSubElement"/>
<xs:group ref="subElements"/>
</xs:sequence>
</xs:complexType>
</xs:element>

JAXB customize bindings - skip generated classes from schema

I have a following schema:
<xs:element name="Invoice">
<xs:complexType>
<xs:sequence>
.....
<xs:element name="InvoiceLines" type="InvoiceLinesType">
</xs:element>
.....
</xs:complexType>
</xs:element>
<xs:complexType name="InvoiceLinesType">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="InvoiceLine" type="InvoiceLineType">
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="InvoiceLineType">
<xs:sequence>
.....
</xs:sequence>
</xs:complexType>
The problem is, that it generate classes:
Invoice - which contain member of InvoiceLinesType
InvoiceLinesType - which contain a collection of InvoiceLineType
InvoiceLineType
So there is one unnecessary class (InvoiceLinesType) and i prefer the following
Invoice - which contain a collection of InvoiceLineType
InvoiceLineType
Does anyone know how to tell the compiler not to generate this package (InvoiceLinesType).
My current external binding file is there
<jxb:bindings schemaLocation="invoice.xsd" node="/xs:schema">
<jxb:globalBindings>
.....
<xjc:simple/>
.....
</jxb:globalBindings>
</jxb:bindings>
Thank You for response.
You would have to modify your schema - drop InvoiceLinesType and have InvoiceLineType as unbounded element in Invoice.
<xs:element name="Invoice">
<xs:complexType>
<xs:sequence>
.....
<xs:element maxOccurs="unbounded" name="InvoiceLine" type="InvoiceLineType">
</xs:element>
.....
</xs:complexType>
</xs:element>
<xs:complexType name="InvoiceLineType">
<xs:sequence>
.....
</xs:sequence>
</xs:complexType>

XSD - Override element

I've a base class, marked as abstract:
<!-- TYPE: BASE CLASS -->
<xs:complexType name="BaseClass" abstract="true">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
<xs:element name="implementation" type="BaseClass" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
Now the class that inherits BaseClass and overrides 'implementation' with null:
<xs:complexType name="MyClass">
<xs:complexContent>
<xs:extension base="BaseClass"/>
</xs:complexContent>
</xs:complexType>
I've tried this but is invalid:
<xs:complexType name="MyClass">
<xs:complexContent>
<xs:extension base="BaseClass">
<xs:sequence>
<xs:element name="implementation" fixed="xs:nil"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Is there a way to do this?
Marking something as abstract in XSD schema basically means that it cannot appear in an instance document. It should be used with the substitutionGroup attribute.
For example
<xs:element name="replaceme" abstract="true" />
<xs:element name="replacement1" substitutionGroup="replaceme" />
<xs:element name="replacement2" substitutionGroup="replaceme" />
This means that in an instance document you would be forced to use either a "replacement1" or a "replacement2" element, ie the xsd is forcing you to substitute the "replaceme" element with one of the replacements from the substitution group.
So to achieve what you want you need to create a substitution group consisting of the types you want to use instead of your base type. I am not sure this is possible with complex types but give it a go.

Resources