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 {
..
}
Related
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
I have been trying to generate XML file from lists of object of type Customer class.
Which i have done successfully.But the structure of my XML file is nested and i want to flatten it out.
Following is my XML file content:
<Customers>
<customer>
<accessRole>
<name>Customer Center</name>
<internalId>14</internalId>
</accessRole>
<aging>0.0</aging>
<category>
<name>Individual</name>
<internalId>2</internalId>
</category>
<companyName>Wolfe Electronics</companyName>
<consolAging>0.0</consolAging>
<consolBalance>0.0</consolBalance>
<consolDepositBalance>0.0</consolDepositBalance>
<consolOverdueBalance>0.0</consolOverdueBalance>
<consolUnbilledOrders>2705.23</consolUnbilledOrders>
<creditHoldOverride/>
<dateCreated>2011-06-22T12:30:00+05:30</dateCreated>
<defaultAddress>US</defaultAddress>
<displaySymbol>$</displaySymbol>
<email>suresh#ldbsystems.com</email>
<emailPreference/>
<emailTransactions>false</emailTransactions>
<entityId>A Wolfe</entityId>
<entityStatus>
<name>CUSTOMER-Closed Won</name>
<internalId>13</internalId>
</entityStatus>
<externalId>entity-5</externalId>
<faxTransactions>false</faxTransactions>
<firstName>A</firstName>
<firstVisit>2012-02-25T05:43:18+05:30</firstVisit>
<giveAccess>true</giveAccess>
<globalSubscriptionStatus/>
<internalId>-5</internalId>
<isBudgetApproved>false</isBudgetApproved>
<isInactive>false</isInactive>
<isPerson>true</isPerson>
<lastModifiedDate>2012-12-19T07:12:03+05:30</lastModifiedDate>
<lastName>Wolfe</lastName>
<lastPageVisited>login-register</lastPageVisited>
<lastVisit>2013-02-23T06:10:44+05:30</lastVisit>
<overrideCurrencyFormat>false</overrideCurrencyFormat>
<phone>650-555-9788</phone>
<priceLevel>
<name>Employee Price</name>
<internalId>3</internalId>
</priceLevel>
<printTransactions>false</printTransactions>
<receivablesAccount>
<name>Use System Preference</name>
<internalId>-10</internalId>
</receivablesAccount>
<salesRep>
<name>Clark Koozer</name>
<internalId>23</internalId>
</salesRep>
<shipComplete>false</shipComplete>
<stage/>
<symbolPlacement/>
<taxItem>
<name>CA-SAN MATEO</name>
<internalId>-112</internalId>
</taxItem>
<taxable>false</taxable>
<unbilledOrders>2705.23</unbilledOrders>
<visits>150</visits>
<webLead>No</webLead>
</customer>
<customer>
<accessRole>
<name>Customer Center</name>
<internalId>14</internalId>
</accessRole>
<aging>0.0</aging>
<category>
<name>Corporate</name>
<internalId>1</internalId>
</category>
<consolAging>0.0</consolAging>
<consolBalance>0.0</consolBalance>
<consolDepositBalance>0.0</consolDepositBalance>
<consolOverdueBalance>0.0</consolOverdueBalance>
<consolUnbilledOrders>76.8</consolUnbilledOrders>
<creditHoldOverride/>
<customFieldList>
<customField/>
</customFieldList>
<dateCreated>2011-06-26T12:30:00+05:30</dateCreated>
<defaultAddress>Anderson Boughton Inc.<br>1488 Main<br>Apt 113<br>Seattle WA 98106<br>US</defaultAddress>
<displaySymbol>$</displaySymbol>
<email>boughton751#cscatering.com</email>
<emailPreference/>
<emailTransactions>false</emailTransactions>
<entityId>Anderson Boughton Inc.</entityId>
<entityStatus>
<name>CUSTOMER-Closed Won</name>
<internalId>13</internalId>
</entityStatus>
<faxTransactions>false</faxTransactions>
<firstVisit>2012-07-12T01:30:49+05:30</firstVisit>
<giveAccess>false</giveAccess>
<globalSubscriptionStatus/>
<internalId>75</internalId>
<isBudgetApproved>false</isBudgetApproved>
<isInactive>false</isInactive>
<isPerson>false</isPerson>
<lastModifiedDate>2012-12-19T11:50:14+05:30</lastModifiedDate>
<lastPageVisited>HP xw4100</lastPageVisited>
<lastVisit>2012-07-12T01:30:49+05:30</lastVisit>
<leadSource>
<name>Partner Referral</name>
<internalId>99993</internalId>
</leadSource>
<overrideCurrencyFormat>false</overrideCurrencyFormat>
<partner>
<name>Online electronics</name>
<internalId>171</internalId>
</partner>
<phone>206-555-1302</phone>
<priceLevel>
<name>Base Price</name>
<internalId>1</internalId>
</priceLevel>
<printTransactions>false</printTransactions>
<receivablesAccount>
<name>Use System Preference</name>
<internalId>-10</internalId>
</receivablesAccount>
<salesRep>
<name>A Wolfe</name>
<internalId>-5</internalId>
</salesRep>
<shipComplete>false</shipComplete>
<stage/>
<symbolPlacement/>
<taxable>false</taxable>
<unbilledOrders>76.8</unbilledOrders>
<webLead>No</webLead>
</customer>
</Customers>
So i have nested structure for <accessRole> which i want to flatten out like
<accessRole-name>and i don't want to display element like <internalId>.
Please find a code snippet of my model:
try {
FileWriter fileWriter = new FileWriter ("D:\\adapter-framework\\Customer_XML.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(extractedRecordsArray[0].getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
fileWriter.append("<Customers>");
fileWriter.append('\n');
for(int i = 0; i < extractedRecordsArray.length - 761 ; i++)
{
jaxbMarshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//jaxbMarshaller.marshal(extractedRecordsArray[i],fileWriter);
jaxbMarshaller.marshal(extractedRecordsArray[i],System.out);
fileWriter.append('\n');
AdapterLogger.debug(this.getClass().getName(), "Extracted record number : " + i);
}
fileWriter.append("</Customers>");
fileWriter.close();
} catch (JAXBException e) {
e.printStackTrace();
}
Please help me out if someone knows about it.
Thanks.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You can use the #XmlPath extension in MOXy to flatten the XML structure.
Customer
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
#XmlPath(".")
private AccessRole accessRole;
}
AccessRole
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class AccessRole {
#XmlElement(name="accessRoleName")
private String name;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
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
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