JAXB无法将XML中的任何元素解组为JAXBElement。

10

我有一个web服务调用。在我的响应中,当我尝试将xml中的any元素转换为JAXBElement时,会抛出错误。

在模式中,我有:

<xs:complexType name="InputType">
    <xs:annotation></xs:annotation>
    <xs:sequence>           
        <xs:element name="Id" type="xs:string" />
        <xs:any namespace="##any" processContents="lax" minOccurs="0" />
    </xs:sequence>
</xs:complexType>

我正在使用的代码:

Object obj = inputType.getAny();
Object o = ((JAXBElement)obj).getValue(); 

这行代码会抛出错误:org.apache.xerces.dom.ElementNSImpl incompatible with javax.xml.bind.JAXBElement,出现在soap ui中。

为什么它不能转换成JAXBElement?我该如何使其工作?

2个回答

10

如果属性使用以下注解,则其内容将被映射为DOM节点:

@XmlAnyElement

如果设置了lax=true标志,则已知元素将被转换为域对象:

@XmlAnyElement(lax=true)

关于@XmlAnyElement的更多信息,请参见:


更新 #1

通过设置lax=true,您可以获得域对象和DOM节点的混合。以下来自Java文档:

为真时

如果为true,则当元素与已标记为 XmlAnyElement的属性匹配时 JAXBContext已知(例如,有一个类与具有相同标记名称的XmlRootElement,或者有具有相同标记名称的XmlElementDecl),则Unmarshaller将急切地将此元素取消编组到JAXB对象中, 而不是将其取消编组到DOM中。 此外,如果元素未知但具有已知的xsi:type,则Unmarshaller会急切地将元素取消编组成JAXBElement,其中包含未知元素名称,而JAXBElement值设置为已知xsi:type的JAXB映射的实例。

因此,在取消编组后,属性可以变得异构;它可以同时具有DOM节点和一些JAXB对象。


更新 #2

为了最终解决问题:

  1. 由于该属性可能包含DOM节点,因此您的代码应考虑这种可能性,并进行一些类型检查。
  2. 为了减少接收到的DOM节点数量,您需要将这些片段的可能根元素与Java类相关联。这是通过使用@XmlRootElement(name="foo", namespace="bar")或使用@XmlElementDecl来注释类来完成的。

请参阅我的博客以获取示例:


在这种情况下,它是lax=true,domain Object。但我的问题是为什么非编组抱怨与JAXBElement对象不兼容。 - valve2010
您仍然可以在使用@XmlAnyElement(lax=true)进行注释的属性中获取DOM节点。请参见更新的答案。 - bdoughan
谢谢提供的信息,我该如何从getAny()中获取值?有什么解决方法吗? - valve2010
我已经再次更新了我的答案,诀窍是使用@XmlRootElement或@XmlElementDecl将这些片段的根元素与Java类关联起来。 - bdoughan
感谢您的耐心等待,但我在@XmlRootElement方面没有什么运气,我的大部分代码都是通过工具生成的。我们有一些之前的代码示例,它们可以在不进行任何变通的情况下工作,唯一的区别是它们在枚举上下文中,并从枚举对象获取任何值,这与我尝试实现的概念类似。我正在使用websphere 6.1和soap 1.7 - jaxb 2.0 - 我想这不是问题。 - valve2010
如果没有与XML片段对应的@XmlRootElement或@XmlElementDecl,则在任何属性上都会得到一个DOM节点。如果您已经指定了此信息,但仍然无法返回域对象的实例,则您使用的JAXB实现中存在错误。 - bdoughan

1

请对你的XML文档进行模式验证。这应该是首先要检查的事项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接