Parsing #XmlAnyElement(lax = true) from soap response - java

I am trying to consume healthcare related webservice to validate DEA number. I have created client class using WSDL tool. I am providing the SOAP response and the client class generated by WSDL to handle SOAP response. Please provide solution to parse response XML . Especially #XmlAnyElement(lax = true) element.
Here is my response xml :
<?xml version="1.0" encoding="UTF-8"?>
<DataSet xmlns="http://tempuri.org/">
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="DEA">
<xs:complexType>
<xs:sequence>
<xs:element name="Dea" type="xs:string" minOccurs="0"/>
<xs:element name="BAC" type="xs:string" minOccurs="0"/>
<xs:element name="Drug_x0020_Schedule" type="xs:string" minOccurs="0"/>
<xs:element name="Expiration_x0020_Date" type="xs:dateTime" minOccurs="0"/>
<xs:element name="Company_x0020_Name" type="xs:string" minOccurs="0"/>
<xs:element name="Address_1" type="xs:string" minOccurs="0"/>
<xs:element name="Address_2" type="xs:string" minOccurs="0"/>
<xs:element name="Address_3" type="xs:string" minOccurs="0"/>
<xs:element name="Address_4" type="xs:string" minOccurs="0"/>
<xs:element name="State" type="xs:string" minOccurs="0"/>
<xs:element name="Zip_x0020_Code" type="xs:string" minOccurs="0"/>
<xs:element name="Drug_x0020_Codes" type="xs:string" minOccurs="0"/>
<xs:element name="BASC" type="xs:string" minOccurs="0"/>
<xs:element name="Payment_x0020_Indicator" type="xs:string" minOccurs="0"/>
<xs:element name="Activity" type="xs:string" minOccurs="0"/>
<xs:element name="siganture_date" type="xs:string" minOccurs="0"/>
<xs:element name="URL" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<DEA diffgr:id="DEA1" msdata:rowOrder="0">
<Dea>*******</Dea>
<BAC>C</BAC>
<Drug_x0020_Schedule>*******</Drug_x0020_Schedule>
<Expiration_x0020_Date>*******</Expiration_x0020_Date>
<Company_x0020_Name>*******</Company_x0020_Name>
<Address_1 xml:space="preserve"></Address_1>
<Address_2>*******</Address_2>
<Address_3 xml:space="preserve"></Address_3>
<Address_4>*******</Address_4>
<State>**</State>
<Zip_x0020_Code>****</Zip_x0020_Code>
<BASC>*</BASC>
<Payment_x0020_Indicator>*</Payment_x0020_Indicator>
<Activity>****</Activity>
<siganture_date>*****</siganture_date>
<URL/>
</DEA>
</NewDataSet>
</diffgr:diffgram>
</DataSet>
Here is my client class to handle response
package org.tempuri;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.w3._2001.xmlschema.Schema;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="GetQueryResult" minOccurs="0">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element ref="{http://www.w3.org/2001/XMLSchema}schema"/>
* <any/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"getQueryResult"
})
#XmlRootElement(name = "GetQueryResponse")
public class GetQueryResponse {
#XmlElement(name = "GetQueryResult")
protected GetQueryResponse.GetQueryResult getQueryResult;
/**
* Gets the value of the getQueryResult property.
*
* #return
* possible object is
* {#link GetQueryResponse.GetQueryResult }
*
*/
public GetQueryResponse.GetQueryResult getGetQueryResult() {
return getQueryResult;
}
/**
* Sets the value of the getQueryResult property.
*
* #param value
* allowed object is
* {#link GetQueryResponse.GetQueryResult }
*
*/
public void setGetQueryResult(GetQueryResponse.GetQueryResult value) {
this.getQueryResult = value;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element ref="{http://www.w3.org/2001/XMLSchema}schema"/>
* <any/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"schema",
"any"
})
public static class GetQueryResult {
#XmlElement(namespace = "http://www.w3.org/2001/XMLSchema", required = true)
protected Schema schema;
#XmlAnyElement(lax = true)
protected Object any;
/**
* Gets the value of the schema property.
*
* #return
* possible object is
* {#link Schema }
*
*/
public Schema getSchema() {
return schema;
}
/**
* Sets the value of the schema property.
*
* #param value
* allowed object is
* {#link Schema }
*
*/
public void setSchema(Schema value) {
this.schema = value;
}
/**
* Gets the value of the any property.
*
* #return
* possible object is
* {#link Object }
*
*/
public Object getAny() {
return any;
}
/**
* Sets the value of the any property.
*
* #param value
* allowed object is
* {#link Object }
*
*/
public void setAny(Object value) {
this.any = value;
}
}
}

Related

How to different objects into the same list using #XmlElements?

I want to use jackson xml mapper to map the following xml (that I have to control of and get from a webservice) to a java bean:
<foo>
<first><val>some</val></first>
<first><val>somemore</val></first>
<second><testval>test</testval></second>
</foo>
The schema I'm supplied with is:
<xs:schema>
<xs:include schemaLocation="firstType.xsd"/>
<xs:include schemaLocation="secondType.xsd"/>
<xs:element name="foo">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element ref="first" minOccurs="0"/>
<xs:element ref="second" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Using xsdtojava, this generates the following bean:
#XmlRootElement(name = "foo")
#XmlAccessorType(XmlAccessType.FIELD)
public class XmlTest {
#XmlElements({
#XmlElement(name = "first", type = FirstType.class),
#XmlElement(name = "second", type = SecondType.class)
})
#JsonSubTypes({
#JsonSubTypes.Type(name = "first", value = FirstType.class),
#JsonSubTypes.Type(name = "second" , value = SecondType.class)
})
private List<IType> items;
//grouping interface
interface IType {
}
#XmlRootElement(name = "first")
#XmlAccessorType(XmlAccessType.FIELD)
class FirstType implements IType {
private String val;
}
#XmlRootElement(name = "second")
#XmlAccessorType(XmlAccessType.FIELD)
class SecondType implements IType {
private String testval;
}
}
But my test fails to convert the xml!
public static void main(String[] args) throws Exception {
String xml =
"<foo>" +
"<first><val>some</val></first>" +
"<second><testval>test</testval></second>" +
"</foo>";
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
ObjectMapper mapper = builder
.modules(new JaxbAnnotationModule(), new JacksonXmlModule())
.defaultUseWrapper(false)
.createXmlMapper(true)
.build();
XmlTest unmarshal = mapper.readValue(xml, XmlTest.class);
System.out.println(unmarshal.items); //prints 'null'
}
The result list of items always null, but why?
I tried both #XmlElements and #JsonSubTypes, but none worked.
I've done a new test :
The XSD : (like yours)
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/test" xmlns:tns="http://www.example.org/test" elementFormDefault="qualified">
<element name="foo">
<complexType>
<sequence maxOccurs="unbounded">
<element name="first" type="tns:FirstType"
maxOccurs="unbounded" minOccurs="0">
</element>
<element name="second" type="tns:SecondType"
maxOccurs="unbounded" minOccurs="0">
</element>
</sequence>
</complexType>
</element>
<complexType name="FirstType">
<sequence>
<element name="val" type="string"></element>
</sequence>
</complexType>
<complexType name="SecondType">
<sequence>
<element name="testval" type="string"></element>
</sequence>
</complexType>
</schema>
The JAVA generated by xjc plugin :
Foo.class :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"firstAndSecond"
})
#XmlRootElement(name = "foo")
public class Foo {
#XmlElements({
#XmlElement(name = "second", type = SecondType.class),
#XmlElement(name = "first", type = FirstType.class)
})
protected List<Object> firstAndSecond;
/**
* Gets the value of the firstAndSecond property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the firstAndSecond property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getFirstAndSecond().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link SecondType }
* {#link FirstType }
*
*
*/
public List<Object> getFirstAndSecond() {
if (firstAndSecond == null) {
firstAndSecond = new ArrayList<Object>();
}
return this.firstAndSecond;
}
public Foo withFirstAndSecond(Object... values) {
if (values!= null) {
for (Object value: values) {
getFirstAndSecond().add(value);
}
}
return this;
}
public Foo withFirstAndSecond(Collection<Object> values) {
if (values!= null) {
getFirstAndSecond().addAll(values);
}
return this;
}
}
FirstType class :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "FirstType", propOrder = {
"val"
})
public class FirstType {
#XmlElement(required = true)
protected String val;
/**
* Gets the value of the val property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getVal() {
return val;
}
/**
* Sets the value of the val property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setVal(String value) {
this.val = value;
}
public FirstType withVal(String value) {
setVal(value);
return this;
}
}
SeconType class :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "SecondType", propOrder = {
"testval"
})
public class SecondType {
#XmlElement(required = true)
protected String testval;
/**
* Gets the value of the testval property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getTestval() {
return testval;
}
/**
* Sets the value of the testval property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setTestval(String value) {
this.testval = value;
}
public SecondType withTestval(String value) {
setTestval(value);
return this;
}
}
The unmarshalling works perfectly in JAXB :
String xml = "<foo>" + "<first><val>some</val></first><second><testval>test</testval></second>" + "</foo>";
Unmarshaller un = JAXBContext.newInstance(Foo.class).createUnmarshaller();
Foo unmarshal = (Foo) un.unmarshal(new StringReader(xml));
System.out.println(unmarshal.getFirstAndSecond());
System.out.println(unmarshal.getFirstAndSecond().size());
But it doesn't works with Jackson2 ...
I have done some research on the web, I have seen discussion about a bug in Jackson on handling XmlElements annotation
You see the link https://github.com/FasterXML/jackson-databind/issues/374
The solution was to make use of:
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
</dependency>
And using -Xsimplify during xsdtojava generation.
And define a binding for that element explicit:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
jaxb:extensionBindingPrefixes="xjc simplify"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="xsd/test.xsd">
<jaxb:bindings multiple="true" node="//xs:element[#name='foo']//xs:complexType//xs:sequence">
<simplify:as-element-property/>
</jaxb:bindings>
</jaxb:binding>
</jaxb:bindings>
This will generate two single elements, for each type:
private List<FirstType> firstType;
private List<SecondType> secondType;

how to generate wsdl client in intelij idea

this is the most simplified version of my problem I could generate.
I got a web service :
#WebService()
public class Service {
#WebMethod
public IsLoggedInResponse IsLoggedIn() {
return new IsLoggedInResponse();
}
}
this is the class I return:
#XmlRootElement
public class IsLoggedInResponse {
private boolean isLoggedIn;
public IsLoggedInResponse(boolean isLoggedIn) {
this.isLoggedIn = isLoggedIn;
}
public IsLoggedInResponse() {
// TODO Auto-generated constructor stub
}
#XmlElement
public boolean isLoggedIn() {
return isLoggedIn;
}
public void setLoggedIn(boolean isLoggedIn) {
this.isLoggedIn = isLoggedIn;
}
}
this is the xsd generated when pressing right click on the webserivce and generate wsdl code from java:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://webservice.pubsale.com/" xmlns:tns="http://webservice.pubsale.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="IsLoggedIn" type="tns:IsLoggedIn"/>
<xs:element name="IsLoggedInResponse" type="tns:IsLoggedInResponse"/>
<xs:element name="IsLoggedInResponse" type="tns:IsLoggedInResponse"/>
<xs:complexType name="IsLoggedIn">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="IsLoggedInResponse">
<xs:sequence>
<xs:element name="return" type="tns:isLoggedInResponse" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="isLoggedInResponse">
<xs:sequence>
<xs:element name="loggedIn" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
notice isLoggedInResponse is created twice. why? how do I stop it?
alright found the problem seems for each webmethod 'METHODNAME' JAXB creates in the schema a complex type named METHODNAMEResponse
my solution was to to add "DTO" to all my requests/responses.
could also change my method name
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://webservice.pubsale.com/" xmlns:tns="http://webservice.pubsale.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="IsLoggedIn" type="tns:IsLoggedIn"/>
<xs:element name="IsLoggedInResponse" type="tns:IsLoggedInResponse"/>
<xs:element name="isLoggedInResponseDTO" type="tns:isLoggedInResponseDTO"/>
<xs:complexType name="IsLoggedIn">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="IsLoggedInResponse">
<xs:sequence>
<xs:element name="return" type="tns:isLoggedInResponse" minOccurs="0"/>
</xs:sequence>
</xs:complexType>

JAXB generated classes for fixed attribute in subtype

My java classes are being generated from xsd file.
The goal I want to accomplish is to have some "known" properties based on the type of elements. For instance, I have a list of animals. After the xml is being parsed, I want to know in the code how many legs have my animals. But the number of legs is a characteristic of the animal type, so, in case I have a cat it will have 4 legs and the kangaroo will have 2 legs.
In case I define the xsd like this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Animals" type="animals" />
<xs:complexType name="animals">
<xs:sequence>
<xs:element name="Animal" maxOccurs="unbounded" type="animal"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="animal" abstract="true">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="catType">
<xs:simpleContent>
<xs:extension base="animal">
<xs:attribute name="nbOfLegs" type="xs:integer" fixed="4" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="kangarooType">
<xs:simpleContent>
<xs:extension base="animal">
<xs:attribute name="nbOfLegs" type="xs:integer" fixed="2" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
The generated classes are as expected (I removed the annotations):
public abstract class Animal {
protected String name;
public String getName() {return name;}
public void setName(String value) {this.name = value;}
}
public class CatType extends Animal {
protected BigInteger nbOfLegs;
public BigInteger getNbOfLegs() {
if (nbOfLegs == null) {
return new BigInteger("4");
} else {
return nbOfLegs;
}
}
public void setNbOfLegs(BigInteger value) {this.nbOfLegs = value;}
}
This way, in case the user sets the number of legs for cats in the xml, it can only be 4, and if he doesn't, in code I will receive 4 anyway. Similar for kangaroo I always receive 2 legs.
But the problem with this approach is that I cannot use polymoprhism like this:
for(Animal animal : animals) {
System.out.println(animal.getNbOfLegs());
}
So I tried a different approach:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Animals" type="animals" />
<xs:complexType name="animals">
<xs:sequence>
<xs:element name="Animal" maxOccurs="unbounded" type="animal"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="animal" abstract="true">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" />
<xs:attribute name="nbOfLegs" type="xs:integer"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="catType">
<xs:simpleContent>
<xs:restriction base="animal">
<xs:attribute name="nbOfLegs" type="xs:integer" fixed="4" />
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="kangarooType">
<xs:simpleContent>
<xs:restriction base="animal">
<xs:attribute name="nbOfLegs" type="xs:integer" fixed="2" />
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
The Animal class is generated as expected:
public abstract class Animal {
protected String name;
protected BigInteger nbOfLegs;
public String getName() {return name;}
public void setName(String value) {this.name = value;}
public BigInteger getNbOfLegs() {return nbOfLegs;}
public void setNbOfLegs(BigInteger value) {this.nbOfLegs = value;}
}
But the generated CatType is empty.
I expected it to be like this:
public class CatType extends Animal {
#Override
public BigInteger getNbOfLegs() {
if (nbOfLegs == null) {
return new BigInteger("4");
} else {
return nbOfLegs;
}
}
}
Is it possible to customize the bindings file in order to achieve the desired generated CatType class?
Thank you.

XML Request Jaxb

I am trying to make a Java object out of an xml request using Jaxb but my limited knowledge of jaxb is holding me back. I have done this before but it was with simple XML documents only using basic Elements such as
<RootElement>
<Bookname>Moby Dick</Bookname>
<BookCode>1</BookCode>
</RootElement>
But now I have a bit more complicated of an xml file and any help getting me started on how to create this object would be greatly appreciated. I think I will have to use some sort of list, along with #Xmlattribute, but am just confused at the moment. Any help would be greatly appreciated! I hope I am not just overthinking this. The sample XML is found below:
<?xml version="1.0"?>
<CRMMessage language="en_US" currency="USD" >
<RequestSource name="Testsource" version="2" />
<RequestCode>GetTest</RequestCode>
<DataSet>
<DataSetColumns>
<DSColumn name="Column1" />
<DSColumn name="Column2" />
</DataSetColumns>
<Rows>
<Row>
<Col>John</Col>
<Col>Doe</Col>
</Row>
</Rows>
</DataSet>
</CRMMessage>
I have knocked you up a quick schema, this may not be exactly what you need as I cannot tell from the example data whether more than one or certain elements it allowed etc:
<xs:schema version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="CRMMessage">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="RequestSource">
<xs:complexType>
<xs:attribute name="Testsource" type="xs:string"/>
<xs:attribute name="version" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="1" name="RequestCode" type="xs:string"/>
<xs:element minOccurs="1" maxOccurs="1" name="DataSet">
<xs:complexType>
<xs:all>
<xs:element minOccurs="1" maxOccurs="1" name="DataSetColumns">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" name="DSColumn">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="1" name="Rows">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" name="Row">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded" name="Col" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="language" type="xs:string"/>
<xs:attribute name="currency" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
You should be able to use that as a starting point.
I then compiled that into a class using xjc via the maven plugin and the following in my pom:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<id>bind-crm</id>
<configuration>
<schemaDirectory>src/main/resources/</schemaDirectory>
<generatePackage>com.my.package.crm</generatePackage>
<forceRegenerate>true</forceRegenerate>
</configuration>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
This gave me the following code:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"requestSource",
"requestCode",
"dataSet"
})
#XmlRootElement(name = "CRMMessage")
public class CRMMessage {
#XmlElement(name = "RequestSource", required = true)
protected CRMMessage.RequestSource requestSource;
#XmlElement(name = "RequestCode", required = true)
protected String requestCode;
#XmlElement(name = "DataSet", required = true)
protected CRMMessage.DataSet dataSet;
#XmlAttribute(name = "language")
protected String language;
#XmlAttribute(name = "currency")
protected String currency;
/**
* Gets the value of the requestSource property.
*
* #return
* possible object is
* {#link CRMMessage.RequestSource }
*
*/
public CRMMessage.RequestSource getRequestSource() {
return requestSource;
}
/**
* Sets the value of the requestSource property.
*
* #param value
* allowed object is
* {#link CRMMessage.RequestSource }
*
*/
public void setRequestSource(CRMMessage.RequestSource value) {
this.requestSource = value;
}
/**
* Gets the value of the requestCode property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getRequestCode() {
return requestCode;
}
/**
* Sets the value of the requestCode property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setRequestCode(String value) {
this.requestCode = value;
}
/**
* Gets the value of the dataSet property.
*
* #return
* possible object is
* {#link CRMMessage.DataSet }
*
*/
public CRMMessage.DataSet getDataSet() {
return dataSet;
}
/**
* Sets the value of the dataSet property.
*
* #param value
* allowed object is
* {#link CRMMessage.DataSet }
*
*/
public void setDataSet(CRMMessage.DataSet value) {
this.dataSet = value;
}
/**
* Gets the value of the language property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getLanguage() {
return language;
}
/**
* Sets the value of the language property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setLanguage(String value) {
this.language = value;
}
/**
* Gets the value of the currency property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getCurrency() {
return currency;
}
/**
* Sets the value of the currency property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setCurrency(String value) {
this.currency = value;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <all>
* <element name="DataSetColumns">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="DSColumn" maxOccurs="unbounded">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* <element name="Rows">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Row" maxOccurs="unbounded">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Col" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </all>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
})
public static class DataSet {
#XmlElement(name = "DataSetColumns", required = true)
protected CRMMessage.DataSet.DataSetColumns dataSetColumns;
#XmlElement(name = "Rows", required = true)
protected CRMMessage.DataSet.Rows rows;
/**
* Gets the value of the dataSetColumns property.
*
* #return
* possible object is
* {#link CRMMessage.DataSet.DataSetColumns }
*
*/
public CRMMessage.DataSet.DataSetColumns getDataSetColumns() {
return dataSetColumns;
}
/**
* Sets the value of the dataSetColumns property.
*
* #param value
* allowed object is
* {#link CRMMessage.DataSet.DataSetColumns }
*
*/
public void setDataSetColumns(CRMMessage.DataSet.DataSetColumns value) {
this.dataSetColumns = value;
}
/**
* Gets the value of the rows property.
*
* #return
* possible object is
* {#link CRMMessage.DataSet.Rows }
*
*/
public CRMMessage.DataSet.Rows getRows() {
return rows;
}
/**
* Sets the value of the rows property.
*
* #param value
* allowed object is
* {#link CRMMessage.DataSet.Rows }
*
*/
public void setRows(CRMMessage.DataSet.Rows value) {
this.rows = value;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="DSColumn" maxOccurs="unbounded">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"dsColumn"
})
public static class DataSetColumns {
#XmlElement(name = "DSColumn", required = true)
protected List<CRMMessage.DataSet.DataSetColumns.DSColumn> dsColumn;
/**
* Gets the value of the dsColumn property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the dsColumn property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getDSColumn().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link CRMMessage.DataSet.DataSetColumns.DSColumn }
*
*
*/
public List<CRMMessage.DataSet.DataSetColumns.DSColumn> getDSColumn() {
if (dsColumn == null) {
dsColumn = new ArrayList<CRMMessage.DataSet.DataSetColumns.DSColumn>();
}
return this.dsColumn;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "")
public static class DSColumn {
#XmlAttribute(name = "name")
protected String name;
/**
* Gets the value of the name property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setName(String value) {
this.name = value;
}
}
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Row" maxOccurs="unbounded">
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Col" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </element>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"row"
})
public static class Rows {
#XmlElement(name = "Row", required = true)
protected List<CRMMessage.DataSet.Rows.Row> row;
/**
* Gets the value of the row property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the row property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getRow().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link CRMMessage.DataSet.Rows.Row }
*
*
*/
public List<CRMMessage.DataSet.Rows.Row> getRow() {
if (row == null) {
row = new ArrayList<CRMMessage.DataSet.Rows.Row>();
}
return this.row;
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="Col" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"col"
})
public static class Row {
#XmlElement(name = "Col", required = true)
protected List<String> col;
/**
* Gets the value of the col property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the col property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getCol().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {#link String }
*
*
*/
public List<String> getCol() {
if (col == null) {
col = new ArrayList<String>();
}
return this.col;
}
}
}
}
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="Testsource" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}integer" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "")
public static class RequestSource {
#XmlAttribute(name = "Testsource")
protected String testsource;
#XmlAttribute(name = "version")
protected BigInteger version;
/**
* Gets the value of the testsource property.
*
* #return
* possible object is
* {#link String }
*
*/
public String getTestsource() {
return testsource;
}
/**
* Sets the value of the testsource property.
*
* #param value
* allowed object is
* {#link String }
*
*/
public void setTestsource(String value) {
this.testsource = value;
}
/**
* Gets the value of the version property.
*
* #return
* possible object is
* {#link BigInteger }
*
*/
public BigInteger getVersion() {
return version;
}
/**
* Sets the value of the version property.
*
* #param value
* allowed object is
* {#link BigInteger }
*
*/
public void setVersion(BigInteger value) {
this.version = value;
}
}
}
That help?
Creating an XML schema for your XML and generating a model from it is definitely as answered by bmorris591 is definitely one way to go. But your XML document isn't so complicated that you can't start from objects.
CRMMessage
We use the #XmlRootElement annotation to map our root object to the root element of the document.
By default JAXB (JSR-222) implementations look for metadata on the public properties (get/set methods). To save space I have set #XmlAccessorType(XmlAccessType.FIELD) to specify that the metadata is on the fields (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html)
The #XmlAttribute annotation is used to specify that a field/property maps to an XML attribute.
By default all fields/properties map to XML elements. If the default XML name does not match your desired mapping then you can use the #XmlElement annotation to override the name.
import javax.xml.bind.annotation.*;
#XmlRootElement(name="CRMMessage")
#XmlAccessorType(XmlAccessType.FIELD)
public class CRMMessage {
#XmlAttribute
private String language;
#XmlAttribute
private String currency;
#XmlElement(name="RequestCode")
private String requestCode;
#XmlElement(name="DataSet")
private DataSet dataSet;
}
DataSet
One advantage of starting from Java classes is that you can leverage the #XmlElementWrapper annotation to add a grouping element on your collection fields/properties (see: http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html). Compare this with the generated DataSet class https://stackoverflow.com/a/14986770/383861.
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class DataSet {
#XmlElementWrapper(name="DataSetColumns")
#XmlElement(name="DSColumn")
private List<DSColumn> columns;
#XmlElementWrapper(name="Rows")
#XmlElement(name="Row")
private List<Row> rows;
}

Restricting XML attribute to enum values

Here is the XSD schema that i created for a WS
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="shipmentStatus" type="shipmentStatusType" />
<xs:complexType name="shipmentStatusType">
<xs:sequence>
<xs:element name="orderNumber" type="xs:int"/>
</xs:sequence>
<xs:attribute name="requestStatus">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="SHIPPED"/>
<xs:enumeration value="PENDING"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
When i generated Java classes using JAXB 2.1, it generated only one class i.e. shipmentStatusType. I was expecting that it will generate requestStatus as a JAVA Enum but it didn't. Is it an expected behaviour or did i miss something?
Just extract your enum/simple type declaration to top-level one and use it as type of the XML attribute:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.com" xmlns="http://www.example.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:simpleType name="requestStatus">
<xs:restriction base="xs:string">
<xs:enumeration value="SHIPPED" />
<xs:enumeration value="PENDING" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="shipmentStatus">
<xs:sequence>
<xs:element name="orderNumber" type="xs:int" />
</xs:sequence>
<xs:attribute name="requestStatus" type="requestStatus" />
</xs:complexType>
<xs:element name="shipmentStatus" type="shipmentStatus" />
</xs:schema>
It will give you such an enum:
/**
* <p>Java class for requestStatus.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* <simpleType name="requestStatus">
* <restriction base="{http://www.w3.org/2001/XMLSchema}string">
* <enumeration value="SHIPPED"/>
* <enumeration value="PENDING"/>
* </restriction>
* </simpleType>
* </pre>
*
*/
#XmlType(name = "requestStatus")
#XmlEnum
public enum RequestStatus {
SHIPPED,
PENDING;
public String value() {
return name();
}
public static RequestStatus fromValue(String v) {
return valueOf(v);
}
}
and class having it:
/**
* <p>Java class for shipmentStatus complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="shipmentStatus">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="orderNumber" type="{http://www.w3.org/2001/XMLSchema}int"/>
* </sequence>
* <attribute name="requestStatus" type="{http://www.example.com}requestStatus" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "shipmentStatus", propOrder = {
"orderNumber"
})
public class ShipmentStatus {
protected int orderNumber;
#XmlAttribute(name = "requestStatus")
protected RequestStatus requestStatus;
/**
* Gets the value of the orderNumber property.
*
*/
public int getOrderNumber() {
return orderNumber;
}
/**
* Sets the value of the orderNumber property.
*
*/
public void setOrderNumber(int value) {
this.orderNumber = value;
}
/**
* Gets the value of the requestStatus property.
*
* #return
* possible object is
* {#link RequestStatus }
*
*/
public RequestStatus getRequestStatus() {
return requestStatus;
}
/**
* Sets the value of the requestStatus property.
*
* #param value
* allowed object is
* {#link RequestStatus }
*
*/
public void setRequestStatus(RequestStatus value) {
this.requestStatus = value;
}
}
I think that you're asking the same thing as this SO post. You need to create a custom binding file to map this simple type to an enumeration.
The binding file:
<jaxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" version="2.1">
<jaxb:globalBindings generateIsSetMethod="true" fixedAttributeAsConstantProperty="true">
<xjc:serializable/>
</jaxb:globalBindings>
<jaxb:bindings schemaLocation="file:/..../restricting-xml-attribute-to-enum-values.xsd">
<jaxb:bindings node="//xs:complexType[#name='shipmentStatusType']/xs:attribute[#name='requestStatus']/xs:simpleType">
<jaxb:typesafeEnumClass name="MyEnumType"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
The generated class (the relevant part):
/**
* <p>Java class for null.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* <simpleType>
* <restriction base="{http://www.w3.org/2001/XMLSchema}string">
* <enumeration value="SHIPPED"/>
* <enumeration value="PENDING"/>
* </restriction>
* </simpleType>
* </pre>
*
*/
#XmlType(name = "")
#XmlEnum
public enum MyEnumType {
SHIPPED,
PENDING;
public String value() {
return name();
}
public static ShipmentStatusType.MyEnumType fromValue(String v) {
return valueOf(v);
}
}

Categories

Resources