I am trying to serialize an XML from a class generated via JAXB.
The class:
package ws.avail;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"pos",
"uniqueID",
"availStatusMessages"
})
#XmlRootElement(name = "OTA_HotelAvailNotifRQ")
public class OTAHotelAvailNotifRQ {
...
}
File "package-info.java":
#javax.xml.bind.annotation.XmlSchema(namespace = "http://www.opentravel.org/OTA/2003/05", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package ws.avail;
The marshaller (simplified without error handling):
context = JAXBContext.newInstance(rootElement.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(rootElement, stringWriter);
return stringWriter.toString();
This code generates:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OTA_HotelAvailNotifRQ Version="1.000" Target="TEST">
....
I expect something like this:
<?xml version="1.0" encoding="UTF-8"?>
<OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="1.000" Target="TEST">
....
I have a similar code and works correctly, but I am unable to see why this code doesn't display the namespace. Any clue? Thanks!
YOUR MAPPINGS ARE CORRECT
I tried out your model and it works for me:
Demo
package ws.avail;
import java.io.StringWriter;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
OTAHotelAvailNotifRQ rootElement = new OTAHotelAvailNotifRQ();
StringWriter stringWriter = new StringWriter();
JAXBContext context = JAXBContext.newInstance(rootElement.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(rootElement, stringWriter);
System.out.println(stringWriter.toString());
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><OTA_HotelAvailNotifRQ xmlns="http://www.opentravel.org/OTA/2003/05"/>
SOLUTION
Usually when this problem occurs the package-info class was not compiled or not packaged with the application.
FOR MORE INFORMATION
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Related
Please help!
I am trying to unmarshall the below XML STRING to a java class. The requirement is only to grab some elements and not all:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type='text/xsl' href='http://myService/rs/../xsl/searchRetrieveResponse.xsl'?>
<searchRetrieveResponse
xmlns="http://www.loc.gov/zing/srw/"
xmlns:srw5="info:srw/extension/5/restrictorSummary">
<version>1.2</version>
<numberOfRecords>1</numberOfRecords>
<records>
<record>
<recordSchema>info:srw/schema/1/CDFXML</recordSchema>
<recordPacking>xml</recordPacking>
<recordData>
<institution active="true" test="true" training="false"
xmlns="info:rfa/rfaRegistry/xmlSchemas/institution"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="info:rfa/rfaRegistry/xmlSchemas/institution http://worldcat.org/registry/xsd/collections/Institutions/institution.xsd">
<identifier>info:rfa/Institutions/113500</identifier>
<versionID>2016-02-17T20:01:22.355Z</versionID>
<nameLocation
xmlns="info:rfa/rfaRegistry/xmlSchemas/institutions/nameLocation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="info:rfa/rfaRegistry/xmlSchemas/institutions/nameLocation http://worldcat.org/registry/xsd/collections/Institutions/nameLocation.xsd">
<lastUpdated>2015-09-27</lastUpdated>
<lastUpdatedTime>03:06:43</lastUpdatedTime>
<first>First Name</first>
</nameLocation>
<identifiers
xmlns="info:rfa/rfaRegistry/xmlSchemas/institutions/identifiers"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="info:rfa/rfaRegistry/xmlSchemas/institutions/identifiers http://worldcat.org/registry/xsd/collections/Institutions/identifiers.xsd">
<lastUpdated>2016-02-17</lastUpdated>
<lastUpdatedTime>15:01:22</lastUpdatedTime>
<age>23</age>
<age>55</age>
</identifiers>
<opac available="true" intranetOnly="false"
xmlns="info:rfa/rfaRegistry/xmlSchemas/institutions/opac"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="info:rfa/rfaRegistry/xmlSchemas/institutions/opac http://worldcat.org/registry/xsd/collections/Institutions/opac.xsd">
<lastUpdated>2009-12-03</lastUpdated>
<lastUpdatedTime>17:43:52</lastUpdatedTime>
<url1>facebook</url1>
<url2>google</url2>
<prefix/>
</opac>
</institution>
</recordData>
<recordPosition>1</recordPosition>
</record>
</records>
</searchRetrieveResponse>
From this file I am only looking to map these tags in my java class below
<first> <age> <age> <url1> <url2>
Java class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "searchRetrieveResponse")
public class MyInfo {
#XmlElement(name = "first")
private String first;
#XmlElement(name = "age")
private List<String> age;
#XmlElement(name = "url1")
private String url1;
#XmlElement(name = "url2")
private String url2;
}
Unmarshalling implementation:
public static void main(String[] args) {
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(MyInfo.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MyInfo myInfo = (MyInfo) jaxbUnmarshaller.unmarshal(
new StringReader( * * MY_XML_STRING **));
catch(JAXBException ex){
log.error("Error - ", ex);
}
}
Error:
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.loc.gov/zing/srw/", local:"searchRetrieveResponse"). Expected elements are <{}searchRetrieveResponse>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:744)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:262)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1149)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:574)...
In My gradle dependencies:
jaxbApi : "javax.xml.bind:jaxb-api:2.4.0-b180830.0359",
jaxbImpl : "com.sun.xml.bind:jaxb-impl:2.4.0-b180830.0438",
jaxbCore : "org.glassfish.jaxb:jaxb-core:2.3.0.1",
And java 11 is the complier.
Add: , namespace = "http://www.loc.gov/zing/srw/"
to your #XmlRootElement:
#XmlRootElement(name = "searchRetrieveResponse", namespace = "http://www.loc.gov/zing/srw/")
...this is what the error message complains about: A mismatch in the namespace!
unexpected element (uri:"http://www.loc.gov/zing/srw/", local:"searchRetrieveResponse").
Expected elements are <{}searchRetrieveResponse>
The {} means empty ("") namespace, in this case.
If namespace omit, it defaults to "##default"...
If the value is "##default", then the XML namespace name is derived from the package of the class ( XmlSchema ). If the package is unnamed, then the XML namespace is the default empty namespace.
EDIT:
In your scenario, I would generate the classes with (built-in) xjc (command line tool ...in ${java.home}/bin)
xjc -d generated <schema>
...where gnerated will be the output folder for the classes (.java files) and <schema> can be a file URL or (structured)directory (with your (readonly) xsd(s)).
Once successfully generated, copy the content of generated into your "main source folder", check it in(, use it) and only change it, when xsd changes.
I am using following code:
JAXBContext jaxbContext = (JAXBContext) JAXBContext.newInstance(AFDType.class);
AFDType AFDType = new AFDType();
DeviceInfoType devInfoType = new DeviceInfoType();
DeviceDetailInfoType devDetailInfoType = new DeviceDetailInfoType();
devDetailInfoType.setEsnMeidDec("esn1234");
devInfoType.setBrandCode("brand123");
devInfoType.setSkuType("sku12345");
devInfoType.setDeviceDetailInfo(devDetailInfoType);
AFDType.setDeviceInfo(devInfoType);
JAXBMarshaller marshaller = jaxbContext.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(AFDType, sw);
This generates an xml of following format:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:deviceInfo>
<ns0:deviceDetailInfo>
<esnMeidDec>esn1234</esnMeidDec>
</ns0:deviceDetailInfo>
<ns0:brandCode>brand123</ns0:brandCode>
<ns0:skuType>sku12345</ns0:skuType>
</ns0:deviceInfo>
However i require following xml:
<ns0:addFD xmlns:ns0="http://ee.abc.com/interfaces/afd/v1/afd.xsd">
<ns0:deviceInfo>
<ns0:deviceDetailInfo>
<ns0:esnMeidHex>36748298746378</ns0:esnMeidHex>
</ns0:deviceDetailInfo>
<ns0:brandCode>SPR</ns0:brandCode>
<ns0:skuType>BYO</ns0:skuType>
</ns0:deviceInfo>
</ns0:addFD>
Can someone please help me how to obtain the 2nd xml.
Add package-info.java into interfaces.afd root folder with the following content
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
namespace="http://ee.abc.com/interfaces/afd/v1",
xmlns={#XmlNs(prefix="ns0",
namespaceURI="http://ee.abc.com/interfaces/afd/v1")}
)
package interfaces.afd;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Read more about it here.
The enclosing root element <ns0:addFd></ns0:addFd> can be achieved by adding #XmlRootElement(name = "addFd") tag above the AddFd.class like below :
#XmlRootElement(name = "addFd")
public class AddFd {
..
}
I am trying to unmarshal an XML.
This is what my XML looks like
<DeviceInventory2Response xmlns="http://tempuri.org/">
<DeviceInventory2Result xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Obj123 xmlns="">
<Id>1</Id>
<Name>abc</Name>
</Obj123>
<Obj456 xmlns="">
.
.
.
I am trying to get Id and Name under Obj123. However when I run my unmarshal command I get the following error.
An Error: javax.xml.bind.UnmarshalException: unexpected element (uri:"http://tempuri.org/", local:"DeviceInventory2Response"). Expected elements are (none)
My code looks like this in the main class:
Obj123 myObj123 = (Obj123) unmarshaller.unmarshal(inputSource);
And my class for Obj123 looks like this:
package com.myProj.pkg;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlRootElement(name="Obj123")
public class Obj123 {
private String Id;
private String Name;
public String getId() {
return Id;
}
public String getName() {
return Name;
}
}
I thought by setting my XMLRootElement that I should be able to skip the first 2 lines of my XML but that doesn't seem to be happening. Any ideas?
Edit:
This is how my JAXB Context is made:
JAXBContext jaxbContext = JAXBContext.newInstance();
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Obj123 obj123 = (Obj123) unmarshaller.unmarshal(xmlStreamReader);
I solved the problem by adding
#XmlRootElement(name="abc_xxx") to the Root class.(where abc_XXX is the root tag of your XML)
The JAXB classes generated by eclipse didn't add this annotation to my root class.
JAXB implementations will try to match on the root element of the document (not on a child element).
If you want to unmarshal to the middle of an XML document then you can parse the document with StAX advance the XMLStreamReader to the desired element and then unmarshal that.
For More Information
http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
UPDATE
now I am getting the following error. An Error:
javax.xml.bind.UnmarshalException - with linked exception:
[javax.xml.bind.UnmarshalException: unexpected element (uri:"",
local:"Obj123"). Expected elements are (none)].
A JAXBContext only knows about the classes you tell it about. Instead of:
JAXBContext jaxbContext = JAXBContext.newInstance();
You need to do:
JAXBContext jaxbContext = JAXBContext.newInstance(Obj123.class);
Use ObjectFactory class instead like
JAXBContext jaxbContext = null;
try {
jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
} catch (JAXBException e) {
e.printStackTrace();
}
JAXBElement<ObjectFactory> applicationElement = null;
try {
applicationElement = (JAXBElement<ObjectFactory>)
unmarshaller.unmarshal(Thread.currentThread().getClass()
.getResourceAsStream(fileName));
} catch (JAXBException e) {
e.printStackTrace();
}
Try this and will resolve above problem. My problem has been resolved.
I am using the following code to do unmarshalling:
#Override
public String marshal(Object document) throws JAXBException {
Class clazz = document.getClass();
JAXBContext context =
JAXBContext.newInstance( clazz.getPackage().getName() );
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
StringWriter sw = new StringWriter();
marshaller.marshal(document, sw);
String xml = sw.toString();
return xml;
}
The result is like this :
<IlpQuoteInput QuoteId="2888284000185" xmlns="http://www.abc.com">
<Common IlpSellerId="0001">
<Quotation QuotationDt="20130711"/>
<Product CurrencyCd="E">
etc etc
It is all good, but I actually dont want to have the xmlns in the output, what shall I do ?
Thanks
PS I am using latest version of JAXB and java 6.
In your mappings you have most likely supplied an #XmlSchema annotation on a package-info class that looks something like the following:
#XmlSchema(
namespace = "http://www.abc.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
To remove the the namespace qualification from the XML output you can simply remove the metadata you put in to cause it to happen in the first place, assuming that is what you want to do.
For More Information
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
From a common JAXB model the xml generated can be of the form
<ipi-list><ipi>1001</ipi><ipi>1002</ipi></ipi-list>
because in json we have arrays we dont need both elements, so by using MOXy's oxml extensions I can flatten the output to give
"ipi" : [ "1001", "1002" ],
but because ipi now refers to an array of things I would like it to be called ipis not ipi
"ipis" : [ "1001", "1002" ],
Is there a way to get MOXy to rename an element ?
You could use EclipseLink JAXB (MOXy)'s external mapping document to tweak the mapping for either the XML or JSON representation.
IPIList
Below is a domain class with JAXB annotations that matches the XML representation from your question:
package forum11449219;
import java.util.*;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="ipi-list")
public class IPIList {
private List<String> list = new ArrayList<String>();
#XmlElement(name="ipi")
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
oxm.xml
We can use MOXy's external mapping document to modify how the list property is mapped to JSON.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum11449219">
<java-types>
<java-type name="IPIList">
<java-attributes>
<xml-element java-attribute="list" name="ipis"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see ):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
The following demo code shows how to reference the external mapping document when creating a JAXBContext.
package forum11449219;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
IPIList ipiList = new IPIList();
ipiList.getList().add("1001");
ipiList.getList().add("1002");
// XML
JAXBContext jc = JAXBContext.newInstance(IPIList.class);
Marshaller xmkMarshaller = jc.createMarshaller();
xmkMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
xmkMarshaller.marshal(ipiList, System.out);
// JSON
Map<String, Object> properties = new HashMap<String, Object>(3);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum11449219/oxm.xml");
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jsonJC = JAXBContext.newInstance(new Class[] {IPIList.class}, properties);
Marshaller jsonMarshaller = jsonJC.createMarshaller();
jsonMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jsonMarshaller.marshal(ipiList, System.out);
}
}
Output
Here is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8"?>
<ipi-list>
<ipi>1001</ipi>
<ipi>1002</ipi>
</ipi-list>
{
"ipis" : [ "1001", "1002" ]
}
For More Information
http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
http://blog.bdoughan.com/2012/04/extending-jaxb-representing-metadata-as.html
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html