Jaxb:如何解组xs:任何XML字符串部分? [英] Jaxb: how to unmarshall xs:any XML-string part?

查看:131
本文介绍了Jaxb:如何解组xs:任何XML字符串部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application doing XML<->conversions using Jaxb and automatically generated classes with maven-jaxb2-plugin.

在我的架构深处,我有可能输入ANYxml。

Someplace deep in my schema, I have the possibility to enter "ANY" xml.

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

Update: this better describes my schema. Some known XML wrapping a totally unknown part (the "any" part).

<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提供)这样的内部类。

This maps (by jaxb) to a inner class like this.

@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对象?

When I unmarshall the entire structure, it is no problem. The "Object any" will render into a org.apache.xerces.dom.ElementNSImpl. Now, I want to recreate the Java object manually and then go to XML. How do I take some random XML and put into the any (org.apache.xerces.dom.ElementNSImpl) element to be able to build up the Java object?

,接下来的情况是当我把这个元素作为java时,我想解组这个部分(能够提取这个元素的XML字符串)。但这是不可能的。我得到一个关于根元素的例外。但是无法注释ElementNSImpl。

Also, the next case is when I have this element as java, I want to unmarshall this very part (to be able to extract the XML string of this element). But this is not possible. I get an exception about root elements. But it is not possible to annotate ElementNSImpl.

unable to marshal type "com.sun.org.apache.xerces.internal.dom.ElementNSImpl" as an element because it is missing an @XmlRootElement annotation

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

Do you have any suggestions on how to handle these problems?

推荐答案

@XmlAnyElement(lax = true)用简单的英语表示:


亲爱的JAXB!如果您有此元素的映射,请将
解组为Java对象。如果您不知道这个元素,只需将其保留为
DOM元素。

Dear JAXB! If you have a mapping for this element, please unmarshal it into a Java object. If you don't know this element, just leave it as a DOM element.

这正是发生的事情在你的情况下。因此,如果您想要实际解组此lax的内容,请为JAXB上下文提供您要解组的元素的映射。最简单的方法是使用 @XmlRootElement

This is exactly what is happening in your case. So if you want to actually unmarshal the content of this lax any, provide JAXB context with a mapping for the element you wish to unmarshal. The easiest way to do this is to annotate your class with @XmlRootElement

@XmlRootElement(name="foo", namespace="urn:bar")
public class MyClass { ... }

现在,当您创建JAXB上下文时,将 MyClass 添加到其中:

Now when you create your JAXB context, add MyClass into it:

JAXBContext context = JAXBContext.newInstance(A.class, B.class, ..., MyClass.class);

在这种情况下,如果JAXB符合 {urn:bar} foo 元素代替 xs:any ,它会知道这个元素被映射到 MyClass 并尝试解组MyClass。

In this case, if JAXB meets the {urn:bar}foo element in the place of that xs:any, it will know that this element is mapped onto MyClass and will try to unmarshal MyClass.

如果你是根据包名创建JAXB上下文(你可能会这样做),你仍然可以添加你的类(比方说, com.acme.foo.MyClass )。最简单的方法是创建 com / acme / foo / jaxb.in​​dex 资源:

If you are creating JAXB context based on the package name (you probably do), you can still add you class (say, com.acme.foo.MyClass) to it. The easiest way is to create a com/acme/foo/jaxb.index resource:

com.acme.foo.MyClass

并将包名添加到上下文中路径:

And the add your package name to the context path:

JAXBContext context = JAXBContext.newInstance("org.dar.gee.schema:com.acme.foo");

还有其他方法可以使用 ObjectFactory 等。 ,但是 jaxb.in​​dex 的技巧可能是最简单的。

There are other ways with ObjectFactory etc., but the trick with jaxb.index is probably the easiest one.

或者,不要在一个中解组所有内容运行时,您可以将 xs:any 的内容保留为DOM,并在第二次解组时将其解组到目标对象中,并使用其他JAXB上下文(知道您的 MyClass 类)。类似于:

Alternatively, instead of unmarshalling everything in one run, you can leave the content of xs:any as DOM and unmarshal it into the target object in a second unmarshalling with anothe JAXB context (which know your MyClass class). Something like:

JAXBContext payloadContext = JAXBContext.newInstance(MyClass.class);
payloadContext.createUnmarshaller().unmarshal((Node) myPayload.getAny());

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

This approach is sometimes better, especially when you have a combination of container/payload schemas which are relatively independent. Depends on the case.

上述所有内容也适用于编组。它完全是双向的。

All said above applies to marshalling as well. It's all neatly bidirectional.

这篇关于Jaxb:如何解组xs:任何XML字符串部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆