gpt4 book ai didi

java - Jaxb:在同一个包中使用多个命名空间解码 xml

转载 作者:太空狗 更新时间:2023-10-29 23:03:12 30 4
gpt4 key购买 nike

我不熟悉在 xml 中使用 namespace ,所以我有点困惑,希望得到一些说明。我有一个 java 服务,我在其中接收具有许多不同命名空间的 xml 文档,当我让它工作时,我觉得我一定做错了什么所以我想检查一下。在我的 package-info.java 中,我有我的模式注释,例如:

@javax.xml.bind.annotation.XmlSchema(
xmlns={
@javax.xml.bind.annotation.XmHS(prefix="train", namespaceURI="http://mycompany/train"),
@javax.xml.bind.annotation.XmHS(prefix="passenger", namespaceURI="http://mycompany/passenger")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm=QUALIFIED
)

我有一个在类级别注释的 Train.java:

@XmlRootElement(name="Train", namespace="http://mycompany/train")

类中的每个字段用以下注释:

@XmlElement(name="Color") for example

火车包含一个乘客列表,所以有一个属性

private Set<Passenger> passengers;

并且这个集合被注释为:

@XmlElementWrapper(name="Passengers")
@XmlElements(@XmlElement(name="Passenger", namespace="http://mycompany/passenger"))

然后在 Passenger.java 中,类本身被注释为:

@XmlElement(name="Passenger", namespace="http://mycompany/passenger")

最后,对于 Passenger.java 中的各个字段,它们的注释如下:

@XmlElement(name="TicketNumber", namespace="http://mycompany/passenger")

所以当我有一个看起来像这样的 xml 时:

<train:Train>
<train:Color>Red</train:Color>
<train:Passengers>
<train:Passenger>
<passenger:TicketNumber>T101</passenger:TicketNumber>
</train:Passenger>
</train:Passengers>
</train:Train>

现在我解码收到的这个 xml,并设置了 Train 的 Color 属性和 Passenger 的 TicketNumber 属性。但是我不知道为什么我需要在 TicketNumber 上的 XmlElement 注释上添加命名空间 url 才能工作,但我不需要为 Train 上的 Color 属性这样做。如果我从 TicketNumber 上的 XmlElement 注释中删除 namespace 属性,则 xml 中的值将不会映射到对象,除非我也从 xml 请求中删除 namespace 前缀。我觉得因为我已经在 XmlRootElement 上为 Passenger 定义了 namespace 属性,所以我不需要为类中的每个字段都这样做,就像我不必为 Train 一样,所以我假设我一定是设置错了。有人能指出我正确的方向吗?谢谢!

最佳答案

下面是对命名空间如何在 JAXB (JSR-222) 中工作的解释。基于您的模型。

Java 模型

包信息

下面是您的 @XmlSchema 注释的修改版本。它包含一些关键信息:

  • namespace - 将用于限定全局元素的默认命名空间(那些对应于 @XmlRootElement@XmlElementDecl 注释(和本地基于 elementFormDefault 值的元素)没有指定其他命名空间。
  • elementFormDefault 默认情况下,只有全局元素是限定命名空间的,但是通过将值设置为 XmlNsForm.QUALIFIED,所有没有明确指定命名空间的元素都将限定为 命名空间值。
  • xmlns 是 JAXB impl 应该用于这些 namespace 的首选前缀集(尽管它们可能使用其他前缀)。
@XmlSchema(
namespace="http://mycompany/train",
elementFormDefault = XmlNsForm.QUALIFIED,
xmlns={
@XmlNs(prefix="train", namespaceURI="http://mycompany/train"),
@XmlNs(prefix="passenger", namespaceURI="http://mycompany/passenger")
}
)
package forum15772478;

import javax.xml.bind.annotation.*;

训练

由于Train类对应的所有元素都对应于@XmlSchema注解指定的namespace,我们不需要指定任何命名空间信息。

  • 全局元素 - @XmlRootElement 注释对应于一个全局元素。
  • 本地元素 - @XmlElementWrapper@XmlElement 注释对应于本地元素。
package forum15772478;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="Train")
public class Train {

private List<Passenger> passengers;

@XmlElementWrapper(name="Passengers")
@XmlElement(name="Passenger")
public List<Passenger> getPassengers() {
return passengers;
}

public void setPassengers(List<Passenger> passengers) {
this.passengers = passengers;
}

}

乘客

如果 Passenger 类的属性对应的所有元素都在 http://mycompany/passenger 命名空间中,那么您可以使用 @ XmlType 注释覆盖 @XmlSchema 注释中的 namespace

package forum15772478;

import javax.xml.bind.annotation.*;

@XmlType(namespace="http://mycompany/passenger")
public class Passenger {

private String ticketNumber;

@XmlElement(name="TicketNumber")
public String getTicketNumber() {
return ticketNumber;
}

public void setTicketNumber(String ticketNumber) {
this.ticketNumber = ticketNumber;
}

}

或者,您可以在属性级别覆盖命名空间。

package forum15772478;

import javax.xml.bind.annotation.*;

public class Passenger {

private String ticketNumber;

@XmlElement(
namespace="http://mycompany/passenger",
name="TicketNumber")
public String getTicketNumber() {
return ticketNumber;
}

public void setTicketNumber(String ticketNumber) {
this.ticketNumber = ticketNumber;
}

}

演示代码

可以运行下面的演示代码来证明一切正常:

演示

package forum15772478;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Train.class);

Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum15772478/input.xml");
Train train = (Train) unmarshaller.unmarshal(xml);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(train, System.out);
}

}

input.xml/输出

在下面的 XML 中,我添加了您问题中的 XML 文档中缺少的必要命名空间声明。

<train:Train 
xmlns:train="http://mycompany/train"
xmlns:passenger="http://mycompany/passenger">
<train:Color>Red</train:Color>
<train:Passengers>
<train:Passenger>
<passenger:TicketNumber>T101</passenger:TicketNumber>
</train:Passenger>
</train:Passengers>
</train:Train>

了解更多信息

关于java - Jaxb:在同一个包中使用多个命名空间解码 xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15772478/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com