JAXB:解组XML在同一封装中多个命名空间(Jaxb: Unmarshalling xml wit

2019-08-19 03:16发布

我是新来使用XML命名空间,所以我也有点困惑,并希望一些澄清。 我在那里,我收到了许多不同的命名空间的XML文档的Java服务,虽然我得到它的工作,我觉得我一定是做错了什么事,所以我要检查。 在我的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我收到和火车站的颜色属性设置与乘客的TicketNumber属性设置。 但我不知道为什么我需要添加上TicketNumber的XmlElement的注释为工作命名空间的网址,但我并不需要对列车Color属性这么做。 如果我从TicketNumber的注释的XmlElement删除namespace属性,从XML值不会得到映射到对象,除非我也是从XML请求删除该命名空间前缀。 我觉得,因为我已经上了XmlRootElement将客运定义的命名空间属性,我不应该需要做的是在每类单场以及就像我没有为火车,所以我假设我必须设置一些错误。 有人能指出我朝着正确的方向吗? 谢谢!

Answer 1:

下面是命名空间中是如何工作的解释JAXB(JSR-222),根据您的型号。

Java模型

包信息

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

  • namespace -这将被用于限定全局元素(默认名称空间的对应@XmlRootElement@XmlElementDecl基于注解(和当地的元素elementFormDefault值)没有指定其他命名空间。
  • elementFormDefault默认情况下,唯一的全球性元素命名空间限定的,但通过设定值进行XmlNsForm.QUALIFIED所有元素,而不指定将与合格明确的命名空间namespace值。
  • xmlns是一个JAXB IMPL应该为这些命名空间中使用(尽管它们也可以使用其他的前缀)的前缀的优选集合。
@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类对应namespace上的指定@XmlSchema注释,我们并不需要指定任何命名空间的信息。

  • 全球元素- @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注释覆盖namespace@XmlSchema注解。

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>

欲获得更多信息

  • http://blog.bdoughan.com/2010/08/jaxb-namespaces.html


文章来源: Jaxb: Unmarshalling xml with multiple namespaces in same package