Jaxb:如何解组xs:任何XML字符串部分?

我有一个应用程序使用Jaxb进行XML 转换,并使用maven-jaxb2-plugin自动生成类。

在我的架构深处,我有可能输入“ANY”xml。

更新:这更好地描述了我的架构。 一些已知的XML包含一个完全未知的部分(“任何”部分)。

          ....  

这将(通过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 

您对如何处理这些问题有什么建议吗?

@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在xs:any的位置遇到{urn:bar}foo元素,它将知道该元素被映射到MyClass并将尝试解组MyClass。

如果您正在根据包名创建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()); 

这种方法有时更好,特别是当您拥有相对独立的容器/有效负载模式的组合时。 取决于案件。

以上所述也适用于编组。 这一切都是整齐的双向。

我认为你需要这个“任何”部分的XSD,并为它们生成类。

以下是一些更多信息:

http://jaxb.java.net/guide/Mapping_of__xs_any___.html

编辑:如果您要编组的对象没有@XmlRootElement注释(请参阅错误消息),那么我认为您必须使用JAXBElement包装它。

  

需要一些不直观的东西才能转换为java对象。 如果没有区别,请尝试使用