我有一个应用程序使用Jaxb进行XML< - >转换,并使用maven-jaxb2-plugin自动生成类。
在我的架构深处,我有可能输入“ANY”xml。
更新:这更好地描述了我的架构。一些已知的XML包含一个完全未知的部分(“任何”部分)。
<xs:complexType name="MessageType">
<xs:sequence>
<xs:element name="XmlAnyPayload" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##any"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="OtherElements">
....
</xs:sequence>
这将(通过jaxb)映射到这样的内部类。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"any"
})
public static class XmlAnyPayload {
@XmlAnyElement(lax = true)
protected Object any;
当我拆开整个结构时,没问题。 “Object any”将呈现为org.apache.xerces.dom.ElementNSImpl。现在,我想手动重新创建Java对象,然后转到XML。我如何获取一些随机XML并放入any(org.apache.xerces.dom.ElementNSImpl)元素以构建Java对象?
另外,下一种情况是当我将这个元素作为java时,我想解组这个部分(为了能够提取这个元素的XML字符串)。但这是不可能的。我得到一个关于根元素的例外。但是不可能注释ElementNSImpl。
unable to marshal type "com.sun.org.apache.xerces.internal.dom.ElementNSImpl" as an element because it is missing an @XmlRootElement annotation
您对如何处理这些问题有任何建议吗?
答案 0 :(得分:41)
@XmlAnyElement(lax = true)
用简单的英语表示:
亲爱的JAXB!如果您有此元素的映射,请解组它 进入Java对象。如果您不知道这个元素,请将其保留为 DOM元素。
这正是您案件中发生的事情。因此,如果您想要实际解组此lax的内容,请为JAXB上下文提供您要解组的元素的映射。最简单的方法是使用@XmlRootElement
@XmlRootElement(name="foo", namespace="urn:bar")
public class MyClass { ... }
现在,当您创建JAXB上下文时,请将MyClass
添加到其中:
JAXBContext context = JAXBContext.newInstance(A.class, B.class, ..., MyClass.class);
在这种情况下,如果JAXB在{urn:bar}foo
的位置遇到xs:any
元素,它将知道此元素已映射到MyClass
并将尝试解组MyClass。 / p>
如果要根据包名创建JAXB上下文(您可能会这样做),您仍然可以向其添加类(例如,com.acme.foo.MyClass
)。最简单的方法是创建com/acme/foo/jaxb.index
资源:
com.acme.foo.MyClass
并将您的包名称添加到上下文路径:
JAXBContext context = JAXBContext.newInstance("org.dar.gee.schema:com.acme.foo");
ObjectFactory
等还有其他方法,但jaxb.index
的技巧可能是最简单的。
或者,不是在一次运行中解组所有内容,而是可以将xs:any
的内容保留为DOM,并在第二次解组时将其解组到目标对象中,使用其他JAXB上下文(知道您的MyClass
类)。类似的东西:
JAXBContext payloadContext = JAXBContext.newInstance(MyClass.class);
payloadContext.createUnmarshaller().unmarshal((Node) myPayload.getAny());
这种方法有时更好,特别是当您拥有相对独立的容器/有效负载模式的组合时。取决于案件。
上述所有内容也适用于编组。这一切都很整齐。
答案 1 :(得分:1)
我认为你需要这个“任意”部分的XSD,并为它们生成类。
以下是一些更多信息:
http://jaxb.java.net/guide/Mapping_of__xs_any___.html
编辑:如果您要编组的对象没有@XmlRootElement注释(请参阅错误消息),那么我认为您必须用JAXBElement包装它。
答案 2 :(得分:0)
<xs:any/>
需要将一些不直观的东西转换为java对象。如果没有区别,请尝试使用
<element name="any" type="xs:anyType"/>