Unmarshalling with multiple namespaces - java

So, lets say I have this xml with several namespaces.
<Envelope xmlns:pdi="http://www.mypage.com/schemas/pdi" xmlns:ib="http://www.mypage.com/schemas/ib" xmlns="http://www.mypage.com/schemas/envelope">
<Product>
<pdi:number>123456</pdi:number>
</Product>
<Instance>
<ib:serial>abcdefg</ib:serial>
</Instance>
</Envelope>
I'm trying to build a client for it. I have an Envelope POJO that's declared like this
#XmlRootElement(name ="Envelope", namespace = "http://www.mypage.com/schemas/envelope")
public class Envelope
and inside, it has these attributes
#XmlElement(name="Product", namespace = "http://www.mypage.com/schemas/pdi")
public Product getProduct(){...}
#XmlElement(name="Instance", namespace = "http://www.mypage.com/schemas/ib")
public Instance getInstance(){...}
Also, the Product POJO looks like this:
#XmlRootElement(name="Product", namespace = "http://www.mypage.com/schemas/pdi")
public class Product
and attribute
#XmlElement(name="pdi:number", namespace = "http://www.mypage.com/schemas/pdi")
public int getNumber(){...}
For some reason, I can't get the product number. I keep getting a request error. Am I handling the namespaces correctly, or am I missing something?

For this use case I would recommend leveraging the package level #XmlSchema annotation to specify the namespace qualification.
package-info (forum14651918/package-info.java)
#XmlSchema(
namespace="http://www.mypage.com/schemas/envelope",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(namespaceURI = "http://www.mypage.com/schemas/envelope", prefix = ""),
#XmlNs(namespaceURI = "http://www.mypage.com/schemas/ib", prefix = "ib"),
#XmlNs(namespaceURI = "http://www.mypage.com/schemas/pdi", prefix = "pdi")
}
)
#XmlAccessorType(XmlAccessType.FIELD)
package forum14651918;
import javax.xml.bind.annotation.*;
Envelope (forum14651918/Envelope.java)
Since we have specified a namespace and elementFormDefault on the #XmlSchema annotation, all the elements corresponding to the Envelope class will be automatically qualified with the http://www.mypage.com/schemas/envelope namespace.
package forum14651918;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="Envelope")
public class Envelope {
#XmlElement(name="Product")
private Product product;
#XmlElement(name="Instance")
private Instance instance;
}
Product (forum14651918/Product.java)
You can override the namespace for the Product class using the #XmlType annotation.
package forum14651918;
import javax.xml.bind.annotation.*;
#XmlType(namespace="http://www.mypage.com/schemas/pdi")
public class Product {
private int number;
}
Instance (forum14651918/Instance.java)
You can override the namespace for the Instance class using the #XmlType annotation.
package forum14651918;
import javax.xml.bind.annotation.XmlType;
#XmlType(namespace="http://www.mypage.com/schemas/ib")
public class Instance {
private String serial;
}
Demo (forum14651918/Demo.java)
Below is some code you can run to prove that everything works.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Envelope.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14651918/input.xml");
Envelope envelope = (Envelope) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(envelope, System.out);
}
}
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html

Try replacing name="pdi:number", namespace = "http://www.mypage.com/schemas/pdi" with name="number", namespace = "http://www.mypage.com/schemas/pdi". Prefix is not needed.
What is more looking at the XML it seems that namespace for both Product and Instance is http://www.mypage.com/schemas/envelope.
You should not need #XmlRootElement annotation for Product class. It is not a root element and is already configured on getProduct().
Full configuration that should be OK is:
#XmlRootElement(name ="Envelope", namespace = "http://www.mypage.com/schemas/envelope")
public class Envelope {
#XmlElement(name="Product", namespace = "http://www.mypage.com/schemas/envelope")
public Product getProduct(){...}
#XmlElement(name="Instance", namespace = "http://www.mypage.com/schemas/envelope")
public Instance getInstance(){...}
}
public class Product {
#XmlElement(name="number", namespace = "http://www.mypage.com/schemas/pdi")
public int getNumber(){...}
}
public class Instance {
#XmlElement(name="serial", namespace = "http://www.mypage.com/schemas/ib")
public String getSerial(){...}
}

Related

Unmarshalling fails with no errors when setting namespace to #XmlRootElement

I have created a JAXB object and I am trying to unmarshal an xml string into it.
The problem that I am facing is that when I put the namespace property in the #XmlRootElement and in the xml document that I am sending, the JAXB object is getting created but it is empty. If I remove the namespace it works. So here is what I mean
My JAXB Object:
#XmlRootElement(name = "incident", namespace = "http://www.ba.com/schema/BAserviceDeskAPI/incident")
#XmlAccessorType(XmlAccessType.FIELD)
public class Incident {
#XmlElement
private String eventTitle;
public Incident() {
}
public String getEventTitle() {
return eventTitle;
}
public void setEventTitle(String eventTitle) {
this.eventTitle = eventTitle;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Incident [");
builder.append("eventTitle=");
builder.append(eventTitle);
builder.append("]");
return builder.toString();
}
}
My Main:
public static void main(String[] args) throws JAXBException {
String s = "<incident xmlns=\"http://www.ba.com/schema/BAserviceDeskAPI/incident\">"
+ "<eventTitle>Test Title from BAwrapper</eventTitle>"
+ "</incident>";
JAXBContext jaxbContext = JAXBContext.newInstance(Incident.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Incident incident = (Incident) jaxbUnmarshaller.unmarshal(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
System.out.println(incident.toString());
}
}
Output:
Incident [eventTitle=null]
If I remove the , namespace = "http://www.ba.com/schema/BAserviceDeskAPI/incident" from the #XmlRootElement and the xmlns=\"http://www.ba.com/schema/BAserviceDeskAPI/incident\" from the xml sent I get the output below
Incident [eventTitle=Test Title from BAwrapper]
Any ideas why this happens?
Thanks
The namespace specified on #XmlRootElement only applies to that element. If you want it to apply to all the elements you have mapped to, you can do it at the package level using the #XmlSchema annotation.
package-info.java
#XmlSchema(
namespace = "http://www.ba.com/schema/BAserviceDeskAPI/incident",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
For More Information
I have written more about JAXB and namespace qualification on my blog:
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Additional Info
Unmarshalling fails with no errors when setting namespace to
#XmlRootElement
For JAXB we (the JSR-222 expert group) decided that an unmarshal shouldn't fail by default if there is unmapped content. Why? Because alot of XML documents contain extra content and things would be failing all the time. If you do want to see these errors then you can specify a ValidationEventHandler on the Unmarshaller.

#XmlElement with multiple names

I have a situation here, trying to act as a gateway between two APIs. What I need to do, is:
make a request to an APIa;
parse (marshal) the XML response into an java object;
make little changes to it;
and then give a response in XML (unmarshal) to the other end (APIb).
The thing is that I use the same object to parse the API response and to send the response to the other end.
public class ResponseAPI{
#XmlElement(name="ResponseCode") //I receive <ResponseCode> but I need to send <ResultCode>
private String responseCode;
//getter and setter
}
as the comment says: I receive but I need to send
Is there a way to get this done without having to create another extra class which carries ResultCode?
thanks in advance!
You can try next solution using #XmlElements annotaion
#XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAPI
{
#XmlElements(
{
#XmlElement(name = "ResponseCode"),
#XmlElement(name = "ResultCode")
})
private String responseCode;
// ...
}
In this case both ResponseCode and ResultCode will be used during unmarshalling (xml -> object) and only ResultCode during marshalling (object -> xml).
So you can unmarshall XML like
<responseAPI>
<ResponseCode>404</ResponseCode>
</responseAPI>
After marshalling object will looks like
<responseAPI>
<ResultCode>404</ResultCode>
</responseAPI>
Note:
The answer given by Ilya works but isn't guaranteed to work across all implementations of JAXB or even across versions of a single JAXB implementation. The #XmlElements annotation is useful when the decision of which element to marshal depends on the type of the value (see: http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html). In your use case both the ResponseCode and ResultCode elements correspond to type String, unmarshalling will always work fine, but the choice of which element to output is arbitrary. Some JAXB Impls may have last specified wins, but others could easily have first wins.
You could do the following by leveraging #XmlElementRef.
Java Model
ResponseAPI
We will change the responseCode property from type String to JAXBElement<String>. The JAXBElement allows us to store the element name as well as the value.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAPI{
#XmlElementRefs({
#XmlElementRef(name = "ResponseCode"),
#XmlElementRef(name = "ResultCode")
})
private JAXBElement<String> responseCode;
public JAXBElement<String> getResponseCode() {
return responseCode;
}
public void setResponseCode(JAXBElement<String> responseCode) {
this.responseCode = responseCode;
}
}
ObjectFactory
The #XmlElementRef annotations we used on the ResponseAPI class correspond to #XmlElementDecl annotations on a class annotated with #XmlRegistry. Traditionally this class is called ObjectFactory but you can call it anything you want.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
#XmlElementDecl(name="ResponseCode")
public JAXBElement<String> createResponseCode(String string) {
return new JAXBElement<String>(new QName("ResponseCode"), String.class, string);
}
#XmlElementDecl(name="ResultCode")
public JAXBElement<String> createResultCode(String string) {
return new JAXBElement<String>(new QName("ResultCode"), String.class, string);
}
}
Demo Code
input.xml
<responseAPI>
<ResponseCode>ABC</ResponseCode>
</responseAPI>
Demo
When creating the JAXBContext we need to ensure that we include the class that contains the #XmlElementDecl annotations.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(ResponseAPI.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("Scratch/src2/forum24554789/input.xml");
ResponseAPI responseAPI = (ResponseAPI) unmarshaller.unmarshal(xml);
ObjectFactory objectFactory = new ObjectFactory();
String responseCode = responseAPI.getResponseCode().getValue();
JAXBElement<String> resultCodeJAXBElement = objectFactory.createResultCode(responseCode);
responseAPI.setResponseCode(resultCodeJAXBElement);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(responseAPI, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<responseAPI>
<ResultCode>ABC</ResultCode>
</responseAPI>

Null values while un-marshalling XML with namspaces using JAXB

I have an issue while un-marshalling simple XML (a subset of CSDL) using JAXB.
Someone already tried to assist me in the past (here), however it is partially worked and I don't know what to do...
Please consider the following XML:
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0">
<Schema xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:sap="http://www.sap.com/Protocols/SAPData" xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="myNS">
</Schema>
</edmx:DataServices>
</edmx:Edmx>
As I was told, I have a package-info.java file that looks like (in the same package):
#XmlSchema(
namespace="http://schemas.microsoft.com/ado/2007/06/edmx",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(prefix="edmx", namespaceURI="http://schemas.microsoft.com/ado/2007/06/edmx"),
#XmlNs(prefix="", namespaceURI="http://schemas.microsoft.com/ado/2009/11/edm"),
#XmlNs(prefix="m", namespaceURI="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")
}
)
#XmlAccessorType(XmlAccessType.FIELD)
package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;
import javax.xml.bind.annotation.*;
In addition, I have the following data structure:
Edmx.java
package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Edmx")
public class Edmx {
#XmlElement(name = "DataServices")
private DataService dataService;
public DataService getDataService() {
return dataService;
}
}
DataService.java
package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class DataService {
#XmlElement(name = "Schema")
private Schema schema;
#XmlAttribute(name = "DataServiceVersion")
private double version;
public Schema getSchema() {
return schema;
}
}
Schema.java
package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;
#XmlRootElement
public class Schema {
....
}
Notice: in Schema.java I have some implementation which does not related to the XML so I have took it off (internal logic).
After un-marshalling the XML using the JAXB, The returned Edmx object contains null values both in 'schema' and 'version' members, although I have mentioned all xmlns parameters in my package-info.java.
Anyone? :(
UPDATE
In my answer to one of your previous questions I provider a mapping for the model from this question.
Error while trying to unmarshal EDMX with JAXB
I have updated this answer to address the following comment that you made:
Why should I declare
'namespace=schemas.microsoft.com/ado/2009/11/edm'; in my #XmlElement?
sorry for being annoying (this is my first experience with JAXB) but I
just gonna have a long XML with many #XmlElement nodes similar to the
'Schema' and I would like to declare the namespace for them only
once...
You can reduce the number of times you need to declare a namespace by organizing your model classes into different packages based on the namespace that they correspond to.
Package 1 for Namespace http://schemas.microsoft.com/ado/2007/06/edmx
package-info
For each package we will use the #XmlSchema annotation to specify the namespace qualification. In this example we only need to specify the namespace for this particular package.
#XmlSchema(
namespace="http://schemas.microsoft.com/ado/2007/06/edmx",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(
prefix="edmx",
namespaceURI="http://schemas.microsoft.com/ado/2007/06/edmx"
),
}
)
#XmlAccessorType(XmlAccessType.FIELD)
package forum14875956.edmx;
import javax.xml.bind.annotation.*;
Edmx
The XML elements corresponding to the Edmx class will be namespace qualified according to what we defined on the #XmlSchema annotation for this package.
package forum14875956.edmx;
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "Edmx")
public class Edmx {
#XmlElement(name = "DataServices")
private DataService dataService;
public DataService getDataService() {
return dataService;
}
}
DataService
The DataService class contains a reference to a class corresponding to a different XML namespace. If the Schema class was in the same package we could use the #XmlElement annotation to override the namespace qualification. Since Schema is in a different package we can use the #XmlElementRef annotation. This tells JAXB to derive the element information from the root element configured for that class.
package forum14875956.edmx;
import javax.xml.bind.annotation.*;
import forum14875956.schema.Schema;
public class DataService {
//#XmlElement(namespace="http://schemas.microsoft.com/ado/2009/11/edm", name="Schema")
#XmlElementRef
private Schema schema;
public Schema getSchema() {
return schema;
}
}
Package 2 for Namespace http://schemas.microsoft.com/ado/2009/11/edm
Again we will use the #XmlSchema to declare the namespace information for the second package.
package-info
#XmlSchema(
namespace="http://schemas.microsoft.com/ado/2009/11/edm",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
#XmlNs(
prefix="",
namespaceURI="http://schemas.microsoft.com/ado/2009/11/edm"
)
}
)
#XmlAccessorType(XmlAccessType.FIELD)
package forum14875956.schema;
import javax.xml.bind.annotation.*;
Schema
The elements in the Schema class will be namespace qualified based namespace information in the #XmlSchema annotation for its package.
package forum14875956.schema;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="Schema")
public class Schema {
}
ORIGINAL ANSWER
You need to include the namespace URI on the mapping for the schema property:
#XmlRootElement
public class DataService {
#XmlElement(name = "Schema" , namespace="http://schemas.microsoft.com/ado/2009/11/edm")
private Schema schema;
#XmlAttribute(name = "DataServiceVersion")
private double version;
public Schema getSchema() {
return schema;
}
}
Full Example
A little while I ago I answered one of your questions providing a complete mapping for this model:
Error while trying to unmarshal EDMX with JAXB

Serializing with JAXB and the Any

I have a schema that defines the following type:
<xsd:complexType name="Payload">
<xsd:sequence>
<xsd:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
And that creates an object like so:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Payload", propOrder = {
"any"
})
public class Payload {
#XmlAnyElement(lax = true)
protected List<Object> any;
}
Now I try adding another generated JAXB object to that Payload doing something like this:
Class payloadClass = ...;
JAXBContext context = JAXBContext.newInstance( WrapperRequest.class, payloadClass);
...
marshaller.marshal( wrappedRequest );
But I get a terrible exception that looks like it'll never work so I decide to serialize the payload object to XML first then add that as a string in the payload.
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance( sdoRequest.getClass() );
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(new JAXBElement(new QName("uri", sdoRequest.getClass().getSimpleName()), sdoRequest.getClass(), sdoRequest), writer);
payload.getAny().add( writer.toString() );
And this blows up with an exception saying "java.lang.String" does not contain an #XmlRootElement.
So how will the use of xs:any ever work with JAXB? Nothing seems to want to work because JAXB turns the Payload into Object, and it won't serialize just anything in Object. This is all inside Axis2 as well so it's been very challenging to get to this point.
Below I will demonstrate JAXB (JSR-222) and any with an example:
Payload
The any property is annotated with #XmlAnyElement(lax=true). This means that for that property if an element is associated with a class via #XmlRootElement or #XmlElementDecl then an instance of the corresponding object will be used to populate the property if not the element will be set as an instance of org.w3c.dom.Element.
package forum13941747;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Payload", propOrder = {
"any"
})
public class Payload {
#XmlAnyElement(lax = true)
protected List<Object> any;
}
Foo
Below is an example of a class annotated with #XmlRootElement.
package forum13941747;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Foo {
}
Bar
Below is an example of a class without the #XmlRootElement annotation. In this use case we will leverage the #XmlElementDecl annotation on a factory class (usually called ObjectFactory) annotated with #XmlRegistry.
package forum13941747;
public class Bar {
}
ObjectFactory
Below is an example of specifying an #XmlElementDecl annotation for the Bar class.
package forum13941747;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
#XmlElementDecl(name="bar")
public JAXBElement<Bar> createBar(Bar bar) {
return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar);
}
}
input.xml
Below is the input document we'll use for this example. There are 3 elements that correspond to the any property. The first corresponds to the #XmlRootElement annotation on the Foo class. The second corresponds to the #XmlElementDecl annotation for the Bar class and the third does not correspond to any of the domain classes.
<?xml version="1.0" encoding="UTF-8"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
Demo
In the demo code below we will unmarshal the input document, then output the classes of the objects in the resulting any property and then marshal the payload object back to XML.
package forum13941747;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Payload.class, Foo.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum13941747/input.xml");
Payload payload = (Payload) unmarshaller.unmarshal(xml);
for(Object o : payload.any) {
System.out.println(o.getClass());
}
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(payload, System.out);
}
}
Output
Below is the output from running the demo code. Note the classes corresponding to the objects in the any property. The foo element became an instance of the Foo class. The bar element became an instance of JAXBElement that holds an instance of Bar. The other element became an instance of org.w3c.dom.Element.
class forum13941747.Foo
class javax.xml.bind.JAXBElement
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
<foo/>
<bar/>
<other/>
</payload>
Make use of Object Factory for mashelling the object like below you no need to have #XmlRootElement in DemoType.java .,
DemoType demoServiceRequest = new DemoType();
ObjectFactory obDemo = new ObjectFactory();
Request requestObject = new Request();
requestObject.setAny(obDemo.createDemo(demoServiceRequest));
And add DemoType class at Request.java like #XmlSeeAlso({DemoType.class})
Should your payload be a XML string, I managed to solve the very same problem using the code below:
import javax.xml.parsers.DocumentBuilderFactory;
//...
String XMLPAYLOAD = "...";
Payload payload = new ObjectFactory().createPayload();
try {
payload.setAny(DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(XMLPAYLOAD)))
.getDocumentElement());
} catch (Exception e) {
e.printStackTrace();
}
//...

Serialize a Java Object

Let me know the best way to serialize my Java object Download. This is a class generated from a java wsimport tool from a WSDL.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Download", propOrder = {
"Response",
"VendorInformation",
"DownloadItem",
"DownloadCommentItem",
"DownloadIntercomItem"
})
public class Download
{
#XmlElement(name = "Response")
protected ResponseMessageManagementType Response;
#XmlElement(name = "VendorInformation")
protected DownloadVendorInformation VendorInformation;
#XmlElement(name = "DownloadItem")
protected List<DownloadDownloadItem> DownloadItem;
#XmlElement(name = "DownloadCommentItem")
protected ArrayOfDownloadDldComment DownloadCommentItem;
#XmlElement(name = "DownloadIntercomItem")
protected ArrayOfDownloadDldIntercom DownloadIntercomItem;
.........................
}
The java classes generated from the tool do not have any serlization implementation.
And I want to serialize the Download class following this kind of format:
<?xml version="1.0" encoding="utf-8"?>
<Download xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="HTTP://xyz.abc.Com//Vendor/DownloadWSE.xsd">
<Response>
.....
</Response>
<VendorInformation>
...............
</VendorInformation>
<DownloadItem>
<DownloadDownloadItem>
.......
</DownloadDownloadItem>
<DownloadDownloadItem>
.......
</DownloadDownloadItem>
<DownloadDownloadItem>
.......
</DownloadDownloadItem>
</DownloadItem>
<DownloadCommentItem>
........
</DownloadCommentItem>
<DownloadIntercomItem>
........
</DownloadIntercomItem>
</Download>
You can see the mapping between XmlElementName and the content of the XML string.
I am at loss on how to do this.
Thanks
This is JAXB. You would need:
JAXBContext ctx = JAXBConetxt.newInstance(Download.class);
Marshaller m = ctx.createMarshaller();
m.marshal(downloadObject, out);
where out can be lots of things, including OutputStream, Writer and File. If you want to get it as a String, use a StringWriter
This is JAXB, and to get your example working you need to supply root element and namespace information:
Root Element
When you marshal an object with JAXB it requires information about the root element. One way to do this is to annotate your Download class with #XmlRootElement
#XmlRootElement(name="Download")
public class Download
If you cannot do that you will need to wrap your instance of Download in a JAXBElement:
Download download = new Download();
QName qname = new QName("HTTP://xyz.abc.Com//Vendor/DownloadWSE.xsd";
JAXBElement<Download> jaxbElement = new JAXBElement(qname, "Download"), Download.class, download);
Namespace Qualification
Also to get the namespace qualification you are after you can use the package level #XmlSchema annotation:
#XmlSchema(
namespace="HTTP://xyz.abc.Com//Vendor/DownloadWSE.xsd",
elementFormDefault=XmlNsForm.QUALIFIED)
package your.model.package.containing.download;
import javax.xml.bind.annotation.*;
Demo
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Download.class);
Download download = new Download();
QName qname = new QName("HTTP://xyz.abc.Com//Vendor/DownloadWSE.xsd";
JAXBElement<Download> jaxbElement = new JAXBElement(qname, "Download"), Download.class, download);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(jaxbElement, System.out);
}
}

Categories

Resources