2013-04-02 104 views
11

我很新來在xml中使用命名空間,所以我有點困惑並想要一些解釋。我有一個java服務,我正在接收帶有許多不同命名空間的xml文檔,雖然我得到它的工作,但我覺得我一定做了錯誤的事情,所以我想檢查。在我的package-info.java我有我的模式註釋,如:Jaxb:在同一個包中使用多個命名空間解組xml

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

和每個字段與註釋類:

@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上的一流水平與註解:

@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我收到和列車的顏色屬性設置和Passenger的TicketNumber屬性設置。但我不知道爲什麼我需要在TicketNumber的XmlElement註釋上添加名稱空間url才能工作,但我並不需要爲Train的Color屬性這樣做。如果我從TicketNumber的XmlElement批註中除去名稱空間屬性,則xml的值將不會映射到對象,除非我也從xml請求中除去命名空間前綴。我覺得既然我已經獲得了Passenger的XmlRootElement上定義的名稱空間屬性,我不需要爲類中的每個字段都這樣做,就像我不需要爲Train一樣,所以我假設我必須設置錯誤的東西。有人能指引我朝着正確的方向嗎?謝謝!

回答

24

下面是根據您的模型對JAXB (JSR-222)中名稱空間的工作方式的說明。

Java模型

包信息

下面是你的@XmlSchema註釋的修改版本。它包含了一些關鍵信息:

  • namespace - 不具備另一個命名空間將被用於限定全局元素(那些基於該elementFormDefault值對應@XmlRootElement@XmlElementDecl註解(和本地元素的默認命名空間)指定。
  • 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類的元素對應的@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> 

瞭解更多信息

+1

感謝超級徹底的答覆。這解決了我的問題,並像我想象的那樣工作。我錯誤地在每個「子類」中使用XmlRootElement,並在該註釋中聲明名稱空間而不是XmlType。 – Frequentcrasher

+0

@Blaise Doughan請建議如果我可以使用相同的名稱空間沒有前綴。 –

相關問題