java - 如何使用相同的 JAXB 类将其编码和解码到不同的命名空间中?

标签 java xml jaxb xml-serialization xml-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 中,它是属于不同 namespace 的消息的一部分。 p>

我首先尝试编写一个根本没有提及命名空间的 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 正在从流或文件中读取或写入。同样,为了解码,我使用 org.w3c.dom.Element 对象,为了编码,我使用 SOAPBody 对象。

最佳答案

我看到以下选项:

  • 使用MOXy XML Bindings并将映射从注释移至 XML 资源。然后,您可以为不同的命名空间定义和加载不同的资源。
  • 在解码之前使用 XSLT 预处理 XML/在编码之后进行后处理。在 XSLT 中,重新映射 namespace 是一项微不足道的任务。
  • 使用 JAXB RI 的自定义 AnnotationReader 来“伪造”从注释中读取的命名空间。您只需调整从包中读取的命名空间即可,应该不会太难。

AnnotationReader 解决方案有点“hacky”,也将您与 JAXB RI 联系在一起。 XML 绑定(bind)需要您以 XML 形式重写注释,并将您与 MOXy 联系起来(我认为)。 XSLT 相当优雅,但会使处理速度变慢。而且您必须使用 XSLT 侵入处理链。

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

关于java - 如何使用相同的 JAXB 类将其编码和解码到不同的命名空间中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29438194/

相关文章:

json - 使用 jackson-dataformat-xml 自定义根元素的 XML 反序列化?

java - 如何在 Eclipse 中运行程序参数包含空格的应用程序?

java - 为什么初始化 Twig 用于在 GWT 应用程序中存储数据会崩溃?

xml - 无法在 Swift 中使用 SWXMLHash 返回解析 XML 的值

javascript - 如何在 Javascript 中写双引号

java - 部署 spring-ws Web 服务时出现 JAXB 异常

java - 如何根据收到的 XML 解码到不同的对象?

java - 使用gradle编译时如何在intellij中包含构建目录作为源目录

java - 使用哪个 Maven 原型(prototype)?

wpf - 每个 WPF 文件中的 xmlns 是什么?