Java 编组时如何向 JAXB 中的元素添加命名空间属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1751048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:17:19  来源:igfitidea点击:

How do I add a namespace attribute to an element in JAXB when marshalling?

javaxmljaxbxml-namespaces

提问by Ryan Elkins

I'm working with eBay's LMS (Large Merchant Services) and kept running into the error:

我正在使用 eBay 的 LMS(大型商家服务)并不断遇到错误:

org.xml.sax.SAXException:
SimpleDeserializer encountered a child
element, which is NOT expected, in
something it was trying to
deserialize.

org.xml.sax.SAXException:
SimpleDeserializer

它试图
反序列化的内容中遇到了意外的子元素。

After a lotof 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.

不同之处在于 .xml 文件上的 XML 命名空间属性AddFixedPriceItemRequest。我的所有 XML 目前都通过 JAXB 进行编组,我不确定将第二个 xmlns 属性添加到我文件中的不同元素的最佳方法是什么。

So that's the question. How do I add an xmlns attribute to another element in JAXB?

所以这就是问题所在。如何将 xmlns 属性添加到 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 BulkDataExchangeRequestsTypeclass. I tried throwing a namespace="urn:ebay:apis:eBLBaseComponents"into the @XmlElementfor AddFixedPriceItemRequestbut it didn't do anything.

这是BulkDataExchangeRequestsType课程的片段。我尝试将 anamespace="urn:ebay:apis:eBLBaseComponents"放入@XmlElementforAddFixedPriceItemRequest但它没有做任何事情。

@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;

采纳答案by skaffman

As far as I can tell, your XML fragments are semantically identical. The xmlnsattribute on the AddFixedPriceItemRequestelement 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.

据我所知,您的 XML 片段在语义上是相同的。在xmlns该属性上的AddFixedPriceItemRequest元件是多余的,因为它暗示继承父元素的命名空间。JAXB 知道这一点,因此不会费心将名称空间添加到其中AddFixedPriceItemRequest- 这只是没有必要。

If the ebay server is only working when the AddFixedPriceItemRequestxmlnsis 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 xmlnsdeclarations is not exposed to the API, since it shouldn't be needed.

如果 ebay 服务器仅在AddFixedPriceItemRequestxmlns存在时才工作,那么它就坏了,并且对输入的要求超出了 XML 和模式的要求。如果情况确实如此(这很难相信,但可能),那么使用像 JAXB 这样的 Java XML 文档模型将是一场斗争,因为这将假设 XML is XML is XML。关于哪些元素获得xmlns声明的低级放屁不会暴露给 API,因为它不应该被需要。

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

这些都没有帮助你。我的方法是将 JAXB 模型编组为 DOM 对象(使用DOMResult传递给Marshaller),然后查看您是否可以对 DOM 进行一些手动调整以将其强制xmlns插入到文档中的适当位置。然后,您可以将该 DOM 序列化为 XML 并发送。

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.

你不应该这样做,我怀疑你可能在其他地方做错了什么;这比 ebay 网络服务被破坏的可能性更大。



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.

编辑:这是另一个建议,比 JAXB-to-DOM-to-XML 解决方案更糟糕。如果您的请求 XML 在结构上是合理的静态结构,只有数字/字符串值发生变化,则将其定义为字符串模板,然后在运行时替换这些值,然后发送。然后您可以使用 JAXB 解释结果。我已经在 oast 中使用 Web 服务完成了这项工作,因为 thyat 需要非常精确的命名空间前缀,而说服 Java XML 库遵守这一点是非常困难的。

回答by Mykola Golubyev

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

如果您只想在某些特定情况下指定命名空间,则使用属性注释

回答by Tushar

Check if the fields in a generated classed are missing the @XmlElementannotation 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.

检查生成的类中的字段是否缺少@XmlElement注释,如果存在,它们是否缺少命名空间属性。这两个必须存在,以便为您的编组 xml 中的每个元素获取命名空间前缀。