Jaxb:在同一个包中解组带有多个名称空间的xml [英] Jaxb: Unmarshalling xml with multiple namespaces in same package
问题描述
我是新手在xml中使用命名空间,所以我有点困惑,想要澄清一下。我有一个java服务,我接收带有许多不同命名空间的xml文档,当我使用它时,我觉得我一定做错了所以我想检查。在我的package-info.java中,我有我的模式注释,例如:
I'm new to using namespaces in xml so I am kind of confused and would like some clarification. I have a java service where I am receiving xml documents with many different namespaces and while i got it working, I feel like I must have done something wrong so I want to check. In my package-info.java I have my schema annotation such as:
@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:
I have a Train.java annotated on the class level with:
@XmlRootElement(name="Train", namespace="http://mycompany/train")
并且类中的每个字段都注明:
and each field in the class annotated with:
@XmlElement(name="Color") for example
列车包含乘客列表所以有一个属性
Train contains a List of Passenger(s) so there's a property
private Set<Passenger> passengers;
此集合的注释为:
@XmlElementWrapper(name="Passengers")
@XmlElements(@XmlElement(name="Passenger", namespace="http://mycompany/passenger"))
然后在Passenger.java中,类本身注释为:
Then within Passenger.java the class itself is annotated with:
@XmlElement(name="Passenger", namespace="http://mycompany/passenger")
最后,对于Passenger.java中的各个字段,它们的注释如下:
Finally for individual fields within Passenger.java, they are annotated like this:
@XmlElement(name="TicketNumber", namespace="http://mycompany/passenger")
所以当我有一个看起来像这样的xml时:
So when I have an xml that looks like:
<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请求中删除了名称空间前缀。我觉得因为我已经在XmlRootElement for Passenger上定义了namespace属性,所以我不应该为类中的每个字段都这样做,就像我没有为Train一样,所以我假设我必须设置错误。有人能指出我正确的方向吗?谢谢!
Now I unmarshal this xml I received and Train's Color property is set and Passenger's TicketNumber property is set. But I don't know why I need to add the namespace url on the XmlElement annotation on TicketNumber for that to work but I didn't need to do so for the Color property on Train. If I remove the namespace attribute from the XmlElement annotation on TicketNumber, the value from the xml wont get mapped to the object unless I also remove the namespace prefix from the xml request. I feel like since I've got the namespace attribute defined on the XmlRootElement for Passenger, I shouldn't need to do that for every single field in the class as well just like I didn't have to for Train so I am assuming I must have setup something wrong. Can someone point me in the right direction? Thanks!
推荐答案
下面解释命名空间如何工作 JAXB(JSR-222) 基于您的型号。
Below is an explanation of how namespaces work in JAXB (JSR-222) based on your model.
JAVA模型
package-info
以下是 @XmlSchema
注释的修改版本。它包含一些关键信息:
Below is a modified version of your @XmlSchema
annotation. It contains some key information:
-
namespace
- 将使用的默认命名空间限定全局元素(对应于@XmlRootElement
和@XmlElementDecl
注释(以及基于<$ c的本地元素) $ c> elementFormDefault value)没有指定其他命名空间。 -
elementFormDefault
默认情况下全局元素是命名空间限定的,但是通过将值设置为XmlNsForm.QUALIFIED
所有未指定显式命名空间的元素将使用命名空间$进行限定c $ c> value。
-
xmlns
是JAXB impl应该用于这些命名空间的首选前缀集(尽管它们可能使用其他前缀)。
namespace
- The default namespace that will be used to qualify global elements (those corresponding to@XmlRootElement
and@XmlElementDecl
annotations (and local elements based on theelementFormDefault
value) that don't have another namespace specified.elementFormDefault
by default only global elements are namespace qualified but by setting the value to beXmlNsForm.QUALIFIED
all elements without an explicit namespace specified will be qualified with thenamespace
value.xmlns
is the preferred set of prefixes that a JAXB impl should use for those namespaces (although they may use other prefixes).
@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
Since all the elements corresponding to the Train
class correspond to the namespace
specified on the @XmlSchema
annotation, we don't need to specify any namespace info.
- 全局元素 -
@XmlRootElement
annotation对应一个全局元素。 - 本地元素 -
@XmlElementWrapper
和@XmlElement
注释对应于本地元素。
- Global Elements - The
@XmlRootElement
annotation corresponds to a global element. - Local Elements - The
@XmlElementWrapper
and@XmlElement
annotations correspond to local elements.
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
注释。
If all the elements corresponding to properties on the Passenger
class will be in the http://mycompany/passenger
namespace, then you can use the @XmlType
annotation to override the namespace
from the @XmlSchema
annotation.
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;
}
}
或者你可以覆盖命名空间属性级别。
Alternatively you can override the namespace at the property level.
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;
}
}
DEMO CODE
可以运行以下演示代码来证明一切正常:
The following demo code can be run to prove that everything works:
Demo
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文档中缺少的必要命名空间声明。
In the XML below I have added the necessary namespace declarations that were missing from the XML document in your question.
<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>
更多信息
- http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
这篇关于Jaxb:在同一个包中解组带有多个名称空间的xml的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!