How do I add a namespace attribute to an element in JAXB when marshalling?
- by Ryan Elkins
I'm working with eBay's LMS (Large Merchant Services) and kept running into the error:
org.xml.sax.SAXException:
SimpleDeserializer encountered a child
element, which is NOT expected, in
something it was trying to
deserialize.
After alot of trial and error I traced the problem down. It turns out this works:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
while this (what I've been sending) doesn't:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest>
The difference is the xml namespace attribute on the AddFixedPriceItemRequest . All of my XML is currently being marshalled via JAXB and I'm not sure what is the best way to go about adding a second xmlns attribute to a different element in my file.
So that's the question. How do I add an xmlns attribute to another element in JAXB?
UPDATE:
package ebay.apis.eblbasecomponents;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
extends AbstractRequestType
{
@XmlElement(name = "Item")
protected ItemType item;
public ItemType getItem() {
return item;
}
public void setItem(ItemType value) {
this.item = value;
}
}
Added class definition by request.
UPDATE 2: Edited the above class like so to no effect:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "urn:ebay:apis:eBLBaseComponents",
name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
UPDATE 3: Here is a snippet of the BulkDataExchangeRequestsType class. I tried throwing a namespace="urn:ebay:apis:eBLBaseComponents" into the @XmlElement for AddFixedPriceItemRequest but it didn't do anything.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BulkDataExchangeRequestsType", propOrder = {
"header",
"addFixedPriceItemRequest"
})
public class BulkDataExchangeRequestsType {
@XmlElement(name = "Header")
protected MerchantDataRequestHeaderType header;
@XmlElement(name = "AddFixedPriceItemRequest")
protected List<AddFixedPriceItemRequestType> addFixedPriceItemRequest;
UPDATE 4: Here's the hideous chunk of code that is updating the xml after marshalling for me. This is currently working although I'm not particulary proud of it.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
marshaller.marshal(request, doc);
NodeList nodes = doc.getChildNodes();
nodes = nodes.item(0).getChildNodes();
for(int i = 0; i < nodes.getLength(); i++){
Node node = nodes.item(i);
if (!node.getNodeName().equals("Header")){
((Element)node).setAttribute("xmlns", "urn:ebay:apis:eBLBaseComponents");
}
}
Update 5:
For anyone else that runs into this problem with eBay and wonders why - The reasoning behind this most likely has to do with how eBay is handling these requests. The BulkDataExchange probably takes the XML payload, breaks it up, and send the pieces out to the Merchant or Trading API. The inner pieces of the payload then do not have the namespace and the get the error. This is a guess on my part but I wouldn't be surprised if this is what was going on behind the scenes.
Thanks for all the help everyone.