Generated XSD does not unmarshall the XML - java

I have an XML string, and I could not use the supplied XSD to unmarshal the object in java. So I tried to use an online tool (www.freeformatter.com/xsd-generator.html) to generate a valid xsd and got the same error. I don't understand what I'm seeing.
Here's the XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message xmlns:ns1="http://www.domain.com/ws" xmlns="http://www.domain.com/ws/protocol">
<HeaderMessage>
<MSGTYPE>reply</MSGTYPE>
<ORIGINATOR>XXXX</ORIGINATOR>
<SENDER>XXXX</SENDER>
<TIMESTAMP>2013-12-12 17:48:09.649</TIMESTAMP>
<IDPROCESS>2013-12-12 17:48:09.649</IDPROCESS>
<IDMESSAGE>AN-1386866889649</IDMESSAGE>
<IDREQUEST>AN-1386866889649</IDREQUEST>
<SERVICENAME>RESULT</SERVICENAME>
<ERRORFLAG>OK</ERRORFLAG>
<ERRORCODE>300</ERRORCODE>
<ERRORMSG>Success</ERRORMSG>
</HeaderMessage>
<BodyMessage>
<ns1:ServiceResultObject isin="XX0000000000">
<ns1:ResultObject value="true" codIsin="XX0000000000" />
</ns1:ServiceResultObject>
</BodyMessage>
</Message>
And here's the XSD I got from the tool:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.domain.com/ws" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ServiceResultObject">
<xs:complexType>
<xs:sequence>
<xs:element name="ResultObject">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="value"/>
<xs:attribute type="xs:string" name="codIsin"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="isin"/>
</xs:complexType>
</xs:element>
</xs:schema>
After I generate the classes, I get the error
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.domain.com/ws/protocol", local:"Message"). Expected elements are <{http://www.domain.com/ws}ServiceResultObject>
Why do I lose all this header information? Why does the XSD not result in a schema that actually unmarshals the object? The XSD supplied by the service guys here also only defined the inner object.

Since your XML document has 2 namespaces (http://www.domain.com/ws/protocol & http://www.domain.com/ws) you are going to need 2 XML schemas to represent it. One schema can reference another with an import element.
XML Schemas
Below I have started the XML Schemas that you will need for your XML.
ws.xsd (for http://www.domain.com/ws namespace)
This is part of the XML schema for the http://www.domain.com/ws. The whole one is what you have already generated.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.domain.com/ws"
xmlns:tns="http://www.domain.com/ws"
elementFormDefault="qualified">
<element name="ServiceResultObject">
<complexType>
<sequence/>
<attribute name="isin" type="string"/>
</complexType>
</element>
</schema>
ws_protocol.xsd (for http://www.domain.com/ws/protocol namespace)
Here is a partial version of the schema that you are missing for the http://www.domain.com/ws/protocol namespace. Note the import element that references the other XML Schema, and <element ref="ws:ServiceResultObject"/> which references an element from the other XML Schema.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.domain.com/ws/protocol"
xmlns:tns="http://www.domain.com/ws/protocol"
xmlns:ws="http://www.domain.com/ws"
elementFormDefault="qualified">
<import namespace="http://www.domain.com/ws" schemaLocation="ws.xsd"/>
<element name="Message">
<complexType>
<sequence>
<element name="HeaderMessage">
<complexType>
<sequence>
<element name="MSGTYPE" type="string"/>
</sequence>
</complexType>
</element>
<element name="BodyMessage">
<complexType>
<sequence>
<element ref="ws:ServiceResultObject"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
Creating the JAXBContext
Once you have the two XML Schemas the classes will generate to 2 different packages. Below is an example of how to bootstrap the JAXBContext. Note that the package names are delimited by the : character.
JAXBContext jc = JAXBContext.newInstance("com.domain.ws:com.domain.ws.protocol");

Related

Why spring wrong generate java classes from xsd

I have xsd schema below describe the
<xs:element name="ReqStartTest">
<xs:complexType>
<xs:sequence>
<xs:element name="Version" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
<xs:element name="Time" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
<xs:element ref="tns:StartTestRequest" minOccurs="1" maxOccurs="1"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="StartTestRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
After i generate java classes from xsd file, and recieve *.wsdl file. After i testing *.wsdl file in SOAPUI, I see just "StartTestRequest" request. My question, why/where my input data ("Version","Time") in request?
Thanks in advance.
Spring only generates request/response for the elements that has the postfixes "request" and "response". In this case, you are referencing "StartTestRequest" from "ReqStartTest". So, you will only see "StartTestRequest" which only has the name field in it. You should extend or reference "ReqStartTest" in your "StartTestRequest"
Following should work fine.
<complexType name="ReqStartTest">
<sequence>
<element name="Version" type="string"/>
<element name="Time" type="string"/>
</sequence>
</complexType>
<element name="StartTestRequest">
<complexType>
<complexContent>
<extension base="tns:ReqStartTest">
<sequence>
<element name="Name" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
</element>
Update:
Spring requires predefined suffixes to identify elements that are requests or responses of a web service. Default suffixes are "Request" and "Response". You can change it in the configuration. This thread might help you: Spring-ws: How to create Wsdl from an xsd with no "Request" element
Also this is the closest you will get without changing suffixes:
<element name="ReqStartTestRequest">
<complexType>
<sequence>
<element name="version" type="string"/>
<element name="time" type="string"/>
<element name="startTestRequest" type="tns:StartTestRequest"/>
</sequence>
</complexType>
</element>
<complexType name="StartTestRequest">
<sequence>
<element name="name" type="string"/>
</sequence>
</complexType>
I highly advise you to follow naming conventions. For example, first letter of a variable or non constant field should be lower case (camelcase notation).

Xsd conditional implementation

I am trying to validate a pdf files documentation using xsd, where I convert the given pdf to xml and parse it through the schema xsd, and it validates, but lets assume there is a heading and it has 2 subheadings how do I change to xsd schema such that for a particular type of heading it should and must have minimum 2 subheadings of particular text(words/sentences), how do I add conditions to the xsd file for it validate specifically designed documents ?
here is the xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="elements">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="element"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="element">
<xs:complexType>
<xs:sequence>
<xs:element ref="pageno"/>
</xs:sequence>
<xs:attribute name="level" use="required" type="xs:integer"/>
<xs:attribute name="title" use="required"/>
<xs:attribute name="type" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="pageno" type="xs:integer"/>
</xs:schema>
and here is the xml I used to generate this xsd:
<elements>
<element type ="Introduction" level="1" title="Introduction">
<pageno>4</pageno>
</element>
<element type ="Introduction" level="2" title="Enhancements to the HP CSA vCenter Simple Compute">
<pageno>4</pageno>
</element>
<element type ="System requirements" level="1" title="System requirements">
<pageno>5</pageno>
</element>
<element type ="System requirements" level="2" title="Software components">
<pageno>5</pageno>
</element>
<element type ="Configuration requirements" level="1" title="Configuration requirements">
<pageno>7</pageno>
</element>
<element type ="Configuration requirements" level="2" title="Installing content capsule">
<pageno>7</pageno>
</element>
<element type ="Configuring offerings in HP CSA" level="1" title="Configuring offerings in HP CSA">
<pageno>8</pageno>
</element>
<element type ="Configuring offerings in HP CSA" level="2" title="Configuring subscriber options">
<pageno>8</pageno>
</element>
<element type ="Configuring subscriber options" level="2" title="Adding providers">
<pageno>8</pageno>
</element>
<element type ="Adding providers" level="2" title="Associating resource offerings with providers">
<pageno>9</pageno>
</element>
<element type ="Associating resource offerings with providers" level="2" title="Changing component properties">
<pageno>10</pageno>
</element>
<element type ="Changing component properties" level="2" title="Creating the service offering">
<pageno>12</pageno>
</element>
<element type ="Creating the service offering" level="2" title="Publishing the service offering">
<pageno>13</pageno>
</element>
<element type ="Publishing the service offering" level="3" title="Publishing service offering to a Catalog">
<pageno>13</pageno>
</element>
<element type ="Subscribing to the service" level="1" title="Subscribing to the service">
<pageno>14</pageno>
</element>
<element type ="Subscribing to the service" level="2" title="Canceling a subscription">
<pageno>14</pageno>
</element>
<!-- <element type ="adasdasd" level = "5" title= "dasdsad">
</element> -->
<element type ="Limitations" level="1" title="Limitations">
<pageno>16</pageno>
</element>
<element type ="Appendix A: HP Operations Orchestration flows" level="1" title="Appendix A: HP Operations Orchestration flows">
<pageno>17</pageno>
</element>
<element type ="Appendix B: Integrating with IP Address Management solutions" level="1" title="Appendix B: Integrating with IP Address Management solutions">
<pageno>19</pageno>
</element>
<element type ="Additional resources" level="1" title="Additional resources">
<pageno>20</pageno>
</element>
<element type ="Send Documentation Feedback" level="1" title="Send Documentation Feedback">
<pageno>21</pageno>
</element>
</elements>
If you think I am lacking in clarity in question then please let me know I will answer any queries.
Thank you
You can define a Schema type of your own that is a heading that must contain specific text, and use the conditional type assignment feature of XSD 1.1, if your implementation supports it.
A more widely supported approach is to embed Schematron rules in your schema to do what you want.
Remember that if you over-constrain your input the schema may become fragile -- that is, hard to maintain in the event of changes.

How to override camelcase on root types in CXF (wadl2java)

I have a type defined in a wadl like so (This is from the ModelCriteria.java generated by wadl2java maven plugin):
<complexType name="ModelCriteria">
<complexContent>
<extension base="{http://www.example.com/services/v2}AbstractSearchCriteria">
<sequence>
<element name="modelNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
<element name="hasAssociation" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
<element name="manufacturerName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
<element name="type" type="{http://www.example.com/services/v2}ModelType" minOccurs="0"/>
</sequence>
</extension>
</complexContent>
</complexType>
The out-going interceptor logs the following:
Payload: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><modelCriteria xmlns="http://www.example.com/services/v2"><modelNumber>MODELNUM</modelNumber></modelCriteria>
In this case, because of the service I am using (which I can't fix to not care about case), I NEED the root type to be ModelCriteria, not modelCriteria. Is there any way of fixing this, and keeping code complexity down? Here is my example:
ModelCriteria snippet:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "ModelCriteria", propOrder = {
"modelNumber",
"hasAssociation",
"manufacturerName",
"type"
})
#XmlRootElement
public class ModelCriteria
extends AbstractSearchCriteria
{
ModelCriteriaTest snippet:
JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
bean.setAddress("https://example.com/services/v2/rest");
bean.setUsername(...);
bean.setPassword(...);
bean.setResourceClass(ModelRestService.class);
bean.getOutInterceptors().add( new org.apache.cxf.interceptor.LoggingOutInterceptor() );
ModelRestService model = bean.create(ModelRestService.class);
ModelCriteria mc = oFact.createModelCriteria();
mc.setModelNumber("CFK");
FindModelResult fmResult = model.findByCriteria(mc);
BONUS:
As a side note, even though package-info.java is present, I still have to add #XmlRootElement to ModelCriteria to get it to even transmit.
Snippet of WADL:
<application
xmlns="http://wadl.dev.java.net/2009/02"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<grammars>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.com/services/v2"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://www.example.com/services/v2">
... other types ...
<xs:element name="ModelCriteria" type="tns:ModelCriteria"/>
</xs:schema>
</grammars>
<resources> ... </resources>
</application>
Change the #XmlRootElement to be #XmlRootElement(name = "ModelCriteria")

XSD Configuration to Reference Attributes Configured in XML file at Runtime

Question: Is there a way (with something like tns:) to set up the .xsd configuration for an XML file to reference a list of attributes that are configured in XML File at runtime?
This is my situation:
I have an .xsd schema file, Labels.xsd for an xml file Labels.xml.
Labels.xsd contains the following:
<complexType name="LabelList">
<sequence>
<element name="label" type="tns:MyLabel" maxOccurs="unbounded"
minOccurs="1"/>
</sequence>
</complexType>
<complexType name="MyLabel">
<attribute name="labelName" type="token" use="required"/>
<!-- There are other attributes and sequences in MyLabel -->
</complexType>
Users can add to the Labels.xml file and add their own custom labels and change the names while my java application runs. The changes are picked up at run time.
I have another file, MyMainTable.xml that uses the schema from Tables.xsd. This file creates a table using the labels from the Labels.xml file above. The schema is in a different schema file than the schema for the Labels.xml file.
The Tables.xml file contains the following:
<complexType name="MyMainTable">
<sequence>
<element name="table" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="tableElement" maxOccurs="unbounded">
<complexType>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
This should be one of the types of
MyLabel.label.labelName that are configured in the
LabelList sequence
Users can change the names of and add to the
types in MyLabel.labelName xml file.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
</sequence>
<!-- There are other attributes in this type, but they are not relevant -->
</complexType>
</element>
</sequence>
</complexType>
Example of the Labels.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Labels xmlns="<my schema locaiton>">
<FavoriteLabels>
<label labelName="LabelA">
<!-- other attributes such as color -->
</label>
<label labelName="LabelB">
<!-- other attributes such as color -->
</label>
<label labelName="LabelC">
<!-- other attributes such as color -->
</label>
</FavoriteLabels>
<OtherLabels>
<label labelName="OtherA">
<!-- other attributes such as color -->
</label>
<label labelName="OtherB">
<!-- other attributes such as color -->
</label>
<label labelName="OtherC">
<!-- other attributes such as color -->
</label>
</OtherLabels>
</Labels>
The name in the tableElement can be in the FavoriteLabels list or the OtherLabels list
Currently I do the check in my Java code when the table is built, but I would like the check to be done when the XML file is parsed. Similar to how a check is down for an Enum configured in an .xsd file.
Is there a way in the .xsd configuration to ensure the name attribute of the tableElement is contained in the list of the labels the user has configured at runtime in the Labels.xml file?
I adapted your example below. It might capture the problem which you are trying to solve or at least show you a possible strategy.
Here is a XML file with both labels and tables.
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://my-namespace my-schema.xsd"
xmlns="http://my-namespace">
<labels>
<label label="LabelA"/>
<label label="LabelB"/>
<label label="LabelC"/>
</labels>
<tables>
<table name="LabelB"/>
<table name="LabelB"/>
<table name="LabelA"/>
<table name="LabelC"/>
</tables>
</root>
You can probably use separate files (I wasn't able to do it using only XML Schema because the key/keyref association uses XPath; but it might be possible, or you can merge the files in memory before processing them).
In the schema, I defined a key/keyref pair associating the labels to the tables. The associations are made using XPath in the context of the element where they are defined. I used ID and IDREF as token types because they are stricter and guarantee uniqueness in the whole document.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
xmlns:tns="http://my-namespace" targetNamespace="http://my-namespace">
<xs:complexType name="LabelList">
<xs:sequence>
<xs:element name="label" maxOccurs="unbounded" minOccurs="1">
<xs:complexType>
<xs:attribute name="label" type="xs:ID" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TableList">
<xs:sequence>
<xs:element name="table" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="name" type="xs:IDREF" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="labels" type="tns:LabelList"/>
<xs:element name="tables" type="tns:TableList"/>
</xs:sequence>
</xs:complexType>
<!-- These are the keys and references; they are in the current element's context -->
<xs:key name="LabelsKey">
<xs:selector xpath="labels/label"/>
<xs:field xpath="#label"/>
</xs:key>
<xs:keyref name="TablesRef" refer="tns:LabelsKey">
<xs:selector xpath="tables/table"/>
<xs:field xpath="#name"/>
</xs:keyref>
</xs:element>
</xs:schema>
Now if you add a table of a label which is not defined on the list, such as:
<table name="LabelZ"/>
You will get a validation error.

how to Convert org.apache.xmlbeans.XmlObject to my customJavaObject

I am having a method where I am receiving XmlObject as an argument in the method and now I want to convert it into the java corresponding java object , that I have to pass in other webservice.
I have tried all the possible ways but not able to get it.
Code :
public static boolean updateAddress_V2(XmlObject xmlObject) throws XmlException{
AlarsDataService dataService=new AlarsDataService();
CustomerV2 customerV2=CustomerV2.Factory.parse(xmlObject.toString());
com.alars.osb.java.customer.CustomerV2.Customer customerXML=customerV2.getCustomer();
}
but when I am checking customerXML is coming as null.
Here is the XMLObject string value :
<Customer_V2 xmlns="http://www.alars.com/osb/java/Customer">
<Customer>
<customerId>4</customerId>
<driverLicense>XBRT245</driverLicense>
<firstName>ALEX</firstName>
<lastName>CINTRA</lastName>
<dob>21-11-1986</dob>
<addressLine1>10 Florence St</addressLine1>
<city>BOSTON</city>
<zipCode>02148</zipCode>
</Customer>
</Customer_V2>
Customer XSD :
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.alars.com/osb/java/Customer"
xmlns:tns="http://www.alars.com/osb/java/Citation" elementFormDefault="qualified">
<complexType name="Customer">
<sequence>
<element name="customerId" type="long"></element>
<element name="driverLicense" type="string"></element>
<element name="firstName" type="string"></element>
<element name="lastName" type="string"></element>
<element name="dob" type="date"></element>
<element name="addressLine1" type="string"></element>
<element name="city" type="string"></element>
<element name="zipCode" type="string"></element>
</sequence>
</complexType>
<complexType name="Customer_V2">
<sequence>
<element name="Customer">
<complexType>
<sequence>
<element name="customerId" type="long"></element>
<element name="driverLicense" type="string"></element>
<element name="firstName" type="string"></element>
<element name="lastName" type="string"></element>
<element name="dob" type="date"></element>
<element name="addressLine1" type="string"></element>
<element name="city" type="string"></element>
<element name="zipCode" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</schema>
Any advise folks.. how to achieve this ??
You change the schema type of XmlObject to required CustomerV2 as follows since we do not know the type ahead.
CustomerV2 customerV2 = (CustomerV2)
xmlObject.changeType(CustomerV2.type);
To check the schema type against the required CustomerV2 schema type, you can do the following.
xmlObject.schemaType().isAssignableFrom(CustomerV2 .type);
The XML does not match to the XSD. Especially, the XSD is missing the top element entries. Use following Schema instead and re-generate your XMLBeans classes:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.alars.com/osb/java/Customer" xmlns:customer="http://www.alars.com/osb/java/Customer">
<xs:element name="CustomerParent">
<xs:complexType>
<xs:sequence>
<xs:element ref="customer:Customer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Customer">
<xs:complexType>
<xs:sequence>
<xs:element ref="customer:customerId"/>
<xs:element ref="customer:driverLicense"/>
<xs:element ref="customer:firstName"/>
<xs:element ref="customer:lastName"/>
<xs:element ref="customer:dob"/>
<xs:element ref="customer:addressLine1"/>
<xs:element ref="customer:city"/>
<xs:element ref="customer:zipCode"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="customerId" type="xs:integer"/>
<xs:element name="driverLicense" type="xs:NCName"/>
<xs:element name="firstName" type="xs:NCName"/>
<xs:element name="lastName" type="xs:NCName"/>
<xs:element name="dob" type="xs:NMTOKEN"/>
<xs:element name="addressLine1" type="xs:string"/>
<xs:element name="city" type="xs:NCName"/>
<xs:element name="zipCode" type="xs:integer"/>
</xs:schema>
Parse your XML as follows:
final CustomerParentDocument customerParentV1 = CustomerParentDocument.Factory.parse(file);

Categories