English 中文(简体)
How do I add a namespace attribute to an element in JAXB when marshalling?
原标题:

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 a lot 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?

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.

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

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;
最佳回答

As far as I can tell, your XML fragments are semantically identical. The xmlns attribute on the AddFixedPriceItemRequest element is redundant, since it implicitly inherits the namespace of its parent element. JAXB knows this, and so doesn t bother adding the namespace to AddFixedPriceItemRequest - it s just not necessary.

If the ebay server is only working when the AddFixedPriceItemRequest xmlns is present, then it s broken, and is making demands on the input over and above those required by XML and by the schema. If this is indeed the case (which is hard to believe, but possible), then using a Java XML document model like JAXB is going to be a struggle, since that will assume XML is XML is XML. Low-level farting about with which elements get the xmlns declarations is not exposed to the API, since it shouldn t be needed.

None of which is helping you. My approach would be to marshal the JAXB model to a DOM object (using a DOMResult passed to the Marshaller), and then see if you can do some manual tweaking of the DOM to force the xmlns into the document at the appropriate places. You can then serialize that DOM to XML and send that.

You shouldn t have to do this, and I suspect you may be doing something else wrong somewhere; this is more likely than the ebay web service being broken like this.


edit: here s another suggestion, a bit less awful than the JAXB-to-DOM-to-XML solution. If your request XML is reasonable static in structure, with only the numeric/string values changing, then define it as a String template, then replace the values at runtime, and send that. You can then interpret the results using JAXB. I ve done this in the oast with web services thyat required very exact namespace prefixes, when persuading the java XML libraries to conform to that was unreasonably hard.

问题回答

Try to use class annotation

@XmlType(namespace="urn:ebay:apis:eBLBaseComponents")

or

@XmlElement(namespace="urn:ebay:apis:eBLBaseComponents")

property annotation if you only want to specify namespace only in some certain cases

Check if the fields in a generated classed are missing the @XmlElement annotation and if present are they missing the namespace attribute. These two must be present in order to get the namespace prefix against every element in your marshaled xml.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签