如何使用相同的JAXB类来编组和解组到不同的命名空间?

时间:2015-04-03 19:04:52

标签: java xml jaxb xml-serialization xml-namespaces

注意:这是使用Java 7.此外,我没有使用JAXB从架构生成任何内容。我只/只想使用JAXB来反序列化现有的SOAP消息。所以JAXB bean是"手写的#34;。

我正在尝试使用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; } } 类,但根本没有提到名称空间:

Element

但是当我使用它来尝试反序列化包含HandshakeInfo元素的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"

然后我尝试将@XmlSchema添加到类中的所有元素和属性(在本例中为none)注释中。 (或者,在 package-info.java 文件中使用<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

那不是我想要的。我希望序列化的东西成为org.w3c.dom.Element

的一部分

那么有没有办法在多个名称空间中使用相同的JAXB类?或者我不得不使用多个类的副本,每个类都注释在适当的名称空间中?

我看过一些使用过滤器等技巧,但这些技巧似乎假设正在从流或文件中读取或写入XML。同样,对于解组,我正在使用SOAPBody个对象,并且为了编组,我正在使用{{1}}个对象。

1 个答案:

答案 0 :(得分:2)

我看到以下选项:

  • 使用MOXy XML Bindings并将注释中的映射移动到XML资源中。然后,您可以为不同的命名空间定义和加载不同的资源。
  • 在编组后使用XSLT在解组/后处理之前预处理XML。重新映射名称空间在XSLT中是一项微不足道的任务。
  • 将JAXB RI的自定义AnnotationReader用于&#34;假&#34;命名空间从注释中读取。你只需要调整从包中读取的命名空间,不应该太难。

AnnotationReader解决方案有点&#34; hacky&#34;还会将您绑定到JAXB RI。 XML绑定需要您以XML格式重写注释,并将您绑定到MOXy(我认为)。 XSLT非常优雅,但会使处理速度变慢。而且您必须使用XSLT进入处理链。

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