当前位置: 首页 > 知识库问答 >
问题:

用JAXB在两个不同的名称空间中重用对象

夏宪
2023-03-14

我需要创建和解析一组结构非常相似但不幸的是在几个不同的命名空间中定义的xml。我通常能够使用JAXB解析和创建所有XML,但似乎在让JAXB处理命名空间定义方面存在一些问题。下面的简单示例应该可以说明这个问题。

如果我定义一个带有类似如下命名空间的带注释的类:

@XmlRootElement(name = "Bus", namespace = "http://www.example.org/bus")
@XmlAccessorType(XmlAccessType.FIELD)
public class Bus {
    @XmlElement(name = "Driver")
    Driver driver;
}

并定义该类使用的另一个类,而不指定命名空间

@XmlAccessorType(XmlAccessType.FIELD)
public class Driver {
    @XmlElement(name = "DriverName")
    String driverName;
}

同时,我有以下包级定义,允许我在<code>总线

@XmlSchema(namespace = "http://www.example.org/bus", 
  xmlns = { @XmlNs(prefix = "", namespaceURI = "http://www.example.org/bus") }
, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)

我有一个这样的xml:

String xml = "<Bus xmlns=\"http://www.example.org/bus\">" + 
             "  <Driver>" +
             "    <DriverName>Bob</DriverName>" +
             "  </Driver>" + 
             "</Bus>";

然后,我可以简单地使用以下内容解析/重新创建xml:

JAXBContext context = JAXBContext.newInstance(Bus.class);

// parse xml
Unmarshaller um = context.createUnmarshaller();
Object xmlObj = um.unmarshal(new StringReader(xml));

// recreate xml 
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
marshaller.marshal(xmlObj, sw);
String recreatedXml = sw.toString();

System.out.println("recreatedXml);

这给了:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Bus xmlns="http://www.example.org/bus">
    <Driver>
        <DriverName>Bob</DriverName>
    </Driver>
</Bus>

但是,我如何在另一个名称空间中重用< code>Driver类呢?

@XmlRootElement(name = "Car", namespace = "http://www.example.org/car")
@XmlAccessorType(XmlAccessType.FIELD)
public class Car {
    @XmlElement(name = "Driver")
    Driver driver;
}

package-info.java只允许一个XmlSchema,如果没有它,每个字段似乎都需要一个显式命名空间。

共有2个答案

司徒焕
2023-03-14

您已经编写了另一个包和包信息,您应该在其中为Car定义xml模式。您可以轻松使用该包中的公共类。

从同一个包中,您无法按预期更改命名空间。

法弘亮
2023-03-14

抽象概念

查看xml lens来自< code > http://www . example . org/bus 的< code>Driver与来自< code > http://www . example . org/car 的< code>Driver不同。你不能简单地重复使用它们,这是你的问题。

您正在使用 JAXB,它允许您在 Java 类和 xml 元素之间建立映射。这使您可以从 Java 类的角度看待相同的问题。

现在,当谈到Java中的代码重用(以及通常的OOP)时,最流行的代码重用方式之一是继承。

因此,核心思想是使用继承在来自不同名称空间的驱动程序之间共享“代码”(在您的示例中仅为属性定义)。

履行

我建议这样构建您的类:

└───xml
    │   DriverBase.java
    │
    ├───bus
    │       Bus.java
    │       Driver.java
    │       package-info.java
    │
    └───car
            Car.java
            Driver.java
            package-info.java

...其中< code>xml。DriverBase是< code>xml.bus.Driver和< code>xml.car.Driver的基础,看起来像:

package xml;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlTransient
@XmlAccessorType(XmlAccessType.PROPERTY)
abstract public class DriverBase {
    @XmlElement(name = "DriverName")
    String driverName;
}

注意@XmlTransient的使用,因为我们实际上不希望JAXB映射< code>DriverBase,只映射它的子类。

xml.bus.Driver 只是继承 xml.DriverBase,应如下所示:

package xml.bus;

import xml.DriverBase;

public class Driver extends DriverBase {
}

< code>xml.bus.Bus与之前大致相同:

package xml.bus;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Bus", namespace = "http://www.example.org/bus")
@XmlAccessorType(XmlAccessType.FIELD)
public class Bus {
    @XmlElement(name = "Driver")
    Driver driver;
}

...以及< code>xml.bus的< code>package-info.java:

@javax.xml.bind.annotation.XmlSchema(
        namespace = "http://www.example.org/bus",
        xmlns = { @javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "http://www.example.org/bus") },
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED
)
package xml.bus;

xml.car.类类似于xml.bus.类。

这应该对你有用。

 类似资料:
  • 我得到了(超过)两个Api POSTendpoint。每一个都需要一个json作为参数。但是当我在两个endpoint参数类中使用相同的类名负载时,Swagger就不起作用了。当我改变其中的一个,例如从有效载荷到有效载荷1时,它就不起作用了。当然,我在包装类中设置了正确的名称空间,以便它找到负载。但我希望每次都使用相同的名称“有效载荷”。如何使用相同的类名负载?在这两种情况下,我都可以保留json

  • 问题内容: [随着理解的进展进行大量编辑] 是否有可能让Spring Jaxb2Marshaller使用一组自定义的名称空间前缀(或至少尊重模式文件/注释中给出的名称空间)而不必使用NamespacePrefixMapper的扩展? 想法是让一个类与另一个类具有“具有”关系,而另一个类又包含一个具有不同名称空间的属性。为了更好地说明这一点,请考虑以下使用JDK1.6.0_12的项目大纲(我可以使用

  • 我是XML和JAXB的新手。我读了很多关于XML、名称空间声明等的文章,但我目前面临着一个无法解决的JAXB问题。EPO上有一个关于响应文档的XSD文件。我可以与客户端一起调用EPO web服务并获取返回文档。我将显示这样一个返回文档的第一行。 正如您所看到的,定义了多个名称空间,但在文档正文中使用的名称空间只有两个,即ns2和NS3。我的问题是解组ns3:register-documents实体

  • 我需要加载XML文件,但存在两种相同的文件格式,只是名称空间不同-在我的简化示例中,: : 引用了一个特定的名称空间,因此我不能以相同的方式处理这两个文件: 给出输出: 目前,我已经以一种次优的方式进行了工作,通过使用https://stackoverflow.com/a/50800021-但如果可能的话,我想将其转移到JAXB中。 输出:

  • 我有一个简单的xml要解组。但是我在输出中只得到一个空列表。不会引发任何异常。这是一个第三方生成的xml,我需要使这一工作没有任何变化的xml。 XML: 用于动物的POJO豆: 猫咪的POJO豆 非马歇尔代码是: 最后一行给出了空指针异常。 我是否对 BEAN 类中的命名空间执行了操作?我是Jaxb的新手,这个问题现在困扰了我3天!我之前问过这个问题,但无法得到正确的答案,这是一个更准确的问题。

  • 我已经阅读了这里的文章和在使用JAXB时处理数字签名的示例代码,并且遇到了一个问题,我认为是JAXB封送将名称空间引入“signedinfo”元素。 我定义了一个XSD,它将被用不同编程语言实现的多个应用程序使用。我将XSD编译为JAXB注释类,供我的实现(Jersey JAX-RS和JAX-WS)使用。我目前拥有的流量如下: JAXB对象使用适当的数据创建或从远程应用程序传递。 按照Blaise