繁体   English   中英

如何使用相同的JAXB类编组和解编入不同的名称空间?

[英]How can I use same JAXB class to marshall and unmarshall into different namespaces?

注意:这是在Java 7中。而且,我没有使用JAXB从架构生成任何东西。 我仅/仅希望使用JAXB对现有的SOAP消息进行反序列化。 因此,JAXB bean是“手写的”。

我正在尝试使用JAXB反序列化以下XML。 没有作为字符串访问它。 相反,我将其作为org.w3c.dom.Element对象获取:

<SynchInfo xmlns="urn:InitronSOAPService">
    <HandshakeInfo>
        <dnsName>foo.bar</dnsName>
        <ip>1.2.3.4</ip>
        <id>TheId</id>
        <key>SomeKey</key>
        <version>1.0</version>
    </HandshakeInfo>
</SynchInfo>

但是我也想将HandshakeInfo实例编组到SOAPBody ,它是属于不同名称空间的消息的一部分。

我首先尝试编写一个完全不提及名称空间的HandshakeInfo类:

@XmlRootElement(name = "HandshakeInfo")
@XmlAccessorType(XmlAccessType.NONE)
final private static class HandshakeInfo
{
    private String version;
    private String id;
    private String key;
    private String ip;
    private String dnsName;

    public String getVersion() {
        return version;
    }

    @XmlElement(name = "version")
    public void setVersion(String version) {
        this.version = version;
    }

    public String getId() {
        return id;
    }

    @XmlElement(name = "id")
    public void setId(String id) {
        this.id = id;
    }

    public String getKey() {
        return key;
    }

    @XmlElement(name = "key")
    public void setKey(String key) {
        this.key = key;
    }

    public String getIp() {
        return ip;
    }

    @XmlElement(name = "ip")
    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getDnsName() {
        return dnsName;
    }

    @XmlElement(name = "dnsName")
    public void setDnsName(String dnsName) {
        this.dnsName = dnsName;
    }
}

但是,当我使用它尝试反序列化包含HandshakeInfo元素的Element对象时,出现以下异常:

javax.xml.bind.UnmarshalException: unexpected element (uri:"urn:InitronSOAPService", local:"HandshakeInfo"). Expected elements are <{}HandshakeInfo>
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
...

因此,然后我尝试将, namespace="urn:InitronSOAPService"到类中的所有元素和属性注释(在本例中为无)。 (或者,在package-info.java文件中使用@XmlSchema注释。)该方法用于反序列化该名称空间中的该元素。

但是,当我尝试使用该类序列化到另一个名称空间时,我(并非完全意外)得到了以下内容:

<SomeMessage xmlns="urn:differentNamespace">
    <ns5:HandshakeInfo xmlns:ns5="urn:InitronSOAPService">
        <ns5:dnsName>foo.bar</ns5:dnsName>
        <ns5:ip>1.2.3.4</ns5:ip>
        <ns5:id>TheId</ns5:id>
        <ns5:key>SomeKey</ns5:key>
        <ns5:version>1.0</ns5:version>
    </ns5:HandshakeInfo>
</SomeMessage>

那不是我想要的 我希望序列化的东西成为urn:differentNamespace

那么,有什么方法可以在多个名称空间中使用相同的JAXB类? 还是我不得不保留多个类的副本,而每个副本都必须标注在适当的命名空间中?

我已经看到了一些使用过滤器等的技巧,但是这些技巧似乎是假设正在从流或文件中读取XML或将XML写入其中。 再次,对于解组,我正在使用org.w3c.dom.Element对象;对于解组,我正在使用SOAPBody对象。

我看到以下选项:

  • 使用MOXy XML绑定并将映射从注释移到XML资源中。 然后,您可以为不同的名称空间定义和加载不同的资源。
  • 使用XSLT在解组之前对XML进行预处理/在进行编组之后进行后处理。 在XSLT中,重命名空间是一项琐碎的任务。
  • 使用JAXB RI的自定义AnnotationReader可以“伪造”从注解中读取的名称空间。 您只需要调整从包中读取的名称空间,就不会太难。

AnnotationReader解决方案有点“棘手”,还将您与JAXB RI绑定在一起。 XML绑定将要求您以XML格式重写注释,并将您与MOXy绑定(我认为)。 XSLT非常优雅,但是会使处理速度变慢。 而且,您必须使用XSLT进入处理链。

所有选项都各有利弊,您必须针对具体情况仔细考虑它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM