我正在使用eBay的LMS(大型商户服务)并一直遇到错误:
org.xml.sax.SAXException: SimpleDeserializer遇到了一个孩子 元素,这是不期望的,在 它试图尝试的东西 反序列化。
在很多的试验和错误后,我追查了问题。事实证明这是有效的:
<?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">
虽然这(我发送的内容)没有:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest>
区别在于AddFixedPriceItemRequest
上的xml名称空间属性。我的所有XML目前都是通过JAXB编组的,我不确定将第二个xmlns属性添加到文件中的其他元素的最佳方法是什么。
这就是问题所在。如何在JAXB中向另一个元素添加xmlns属性?
更新:
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;
}
}
按要求添加了类定义。
更新2:编辑上述类似乎无效:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "urn:ebay:apis:eBLBaseComponents",
name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
更新3:这是BulkDataExchangeRequestsType类的片段。我尝试在@XmlElement中为AddFixedPriceItemRequest抛出namespace="urn:ebay:apis:eBLBaseComponents"
,但它没有做任何事情。
@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;
更新4:这是在为我编组后更新xml的可怕代码块。这项工作目前正在进行中,但我并不为此感到自豪。
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");
}
}
感谢所有人的帮助。
答案 0 :(得分:5)
据我所知,您的XML片段在语义上是相同的。 xmlns
元素上的AddFixedPriceItemRequest
属性是多余的,因为它隐式继承了其父元素的命名空间。 JAXB知道这一点,所以不打算将命名空间添加到AddFixedPriceItemRequest
- 它只是没有必要。
如果ebay服务器仅在AddFixedPriceItemRequest
xmlns
存在时工作,那么它就会被破坏,并且对输入的要求超出了XML和模式所要求的要求。如果情况确实如此(很难相信,但可能),那么使用像JAXB这样的Java XML文档模型将会很困难,因为这将假设XML是XML就是XML。关于哪些元素获得xmlns
声明的低级放弃不会暴露给API,因为它不应该被需要。
这些都没有帮助你。我的方法是将JAXB模型封送到DOM对象(使用传递给DOMResult
的{{1}}),然后查看是否可以对DOM进行一些手动调整以强制{{1在适当的地方进入文件。然后,您可以将该DOM序列化为XML并发送它。
你不应该这样做,我怀疑你可能在某处做了别的错事;这比ebay网络服务更容易被破坏。
编辑:这是另一个建议,比JAXB-to-DOM-to-XML解决方案更糟糕。如果您的请求XML在结构上是合理的静态,只更改了数字/字符串值,则将其定义为String模板,然后在运行时替换值,并发送它。然后,您可以使用JAXB解释结果。我已经在网络服务中完成了这项工作,因为当说服java XML库符合这种方法时,必须使用非常精确的命名空间前缀。
答案 1 :(得分:4)
检查生成的分类中的字段是否缺少@XmlElement
注释,如果存在则缺少命名空间属性。必须存在这两个,以便为封送的xml中的每个元素获取名称空间前缀。
答案 2 :(得分:3)
尝试使用类注释
@XmlType(namespace="urn:ebay:apis:eBLBaseComponents")
或
@XmlElement(namespace="urn:ebay:apis:eBLBaseComponents")
属性注释,如果您只想在某些特定情况下指定命名空间