2013-04-02 20 views
11

Tôi mới sử dụng không gian tên trong xml vì vậy tôi là loại bối rối và muốn làm rõ một số. Tôi có một dịch vụ java, nơi tôi nhận được tài liệu xml với nhiều không gian tên khác nhau và trong khi tôi nhận nó hoạt động, tôi cảm thấy mình phải làm điều gì sai vì vậy tôi muốn kiểm tra. Trong package-info.java của tôi, tôi có chú thích giản đồ của tôi như:Jaxb: Unmarshalling xml với nhiều không gian tên trong cùng một gói

@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 
) 

Tôi đã một Train.java chú thích vào mức độ lớp với:

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

và từng lĩnh vực trong lớp chú thích với :

@XmlElement(name="Color") for example 

Train chứa một Danh sách hành khách (s) vì vậy có một tài sản

private Set<Passenger> passengers; 

và bộ sưu tập này được chú thích với:

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

Sau đó, trong vòng Passenger.java lớp tự nó được chú thích với:

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

Cuối cùng cho các lĩnh vực cá nhân trong Passenger.java, họ được chú thích như thế này :

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

Vì vậy, khi tôi có xml trông giống như:

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

Bây giờ tôi unmarshal xml này tôi nhận được và tài sản Train Color được thiết lập và tài sản TicketNumber của hành khách được thiết lập. Nhưng tôi không biết tại sao tôi cần thêm url không gian tên trên chú thích XmlElement trên TicketNumber để làm việc nhưng tôi không cần phải làm như vậy cho thuộc tính Color trên Train. Nếu tôi loại bỏ các thuộc tính không gian tên từ chú thích XmlElement trên TicketNumber, giá trị từ xml wont được ánh xạ tới đối tượng trừ khi tôi cũng loại bỏ tiền tố không gian tên từ yêu cầu xml. Tôi cảm thấy như kể từ khi tôi đã có các thuộc tính không gian tên được xác định trên XmlRootElement cho hành khách, tôi không cần phải làm điều đó cho mỗi lĩnh vực duy nhất trong lớp cũng giống như tôi không phải cho Train vì vậy tôi giả sử tôi phải thiết lập một cái gì đó sai. Ai đó có thể chỉ cho tôi đi đúng hướng? Cảm ơn!

Trả lời

24

Dưới đây là giải thích về cách không gian tên hoạt động trong JAXB (JSR-222) dựa trên mô hình của bạn.

JAVA MODEL

gói-info

Dưới đây là một phiên bản sửa đổi của @XmlSchema chú thích của mình. Nó chứa một số thông tin quan trọng:

  • namespace - Không gian tên mặc định sẽ được sử dụng để đủ điều kiện các yếu tố toàn cầu (tương ứng với những @XmlRootElement@XmlElementDecl chú thích (và các yếu tố địa phương dựa trên giá trị elementFormDefault) mà không có không gian tên khác được chỉ định.
  • elementFormDefault theo mặc định chỉ các phần tử chung là không gian tên đủ điều kiện nhưng bằng cách đặt giá trị là XmlNsForm.QUALIFIED tất cả các phần tử không có không gian tên rõ ràng được chỉ định sẽ đủ điều kiện với giá trị namespace.
  • xmlns là bộ tiền tố ưa thích mà đoạn mã JAXB sẽ sử dụng cho các không gian tên đó (mặc dù chúng có thể sử dụng các tiền tố khác).
@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

Vì tất cả các yếu tố tương ứng với lớp Train tương ứng với namespace xác định trên @XmlSchema chú thích, chúng tôi không cần phải xác định bất kỳ thông tin không gian tên.

  • Chú thích chung - Chú thích @XmlRootElement tương ứng với phần tử chung.
  • Các yếu tố địa phương - Các chú thích @XmlElementWrapper@XmlElement tương ứng với các yếu tố địa phương.
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; 
    } 

} 

hành khách

Nếu tất cả các yếu tố tương ứng với tài sản trên lớp Passenger sẽ nằm trong namespace http://mycompany/passenger, sau đó bạn có thể sử dụng @XmlType chú thích để ghi đè lên namespace từ @XmlSchema chú thích.

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; 
    } 

} 

Hoặc bạn có thể ghi đè không gian tên ở cấp thuộc tính.

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 MÃ

Mã giới thiệu sau đây có thể được chạy để chứng minh rằng mọi thứ hoạt động:

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/Output

Trong XML bên dưới, tôi đã thêm các khai báo vùng tên cần thiết bị thiếu trong tài liệu XML trong câu hỏi của bạn.

<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> 

CHO BIẾT THÊM THÔNG TIN

+1

Cảm ơn bạn đã trả lời siêu kỹ lưỡng. Điều này giải quyết vấn đề của tôi và làm việc như tôi tưởng tượng nó nên. Tôi đã sử dụng XmlRootElement trong mỗi "lớp con" một cách sai lầm và khai báo không gian tên trong chú thích đó thay vì XmlType. – Frequentcrasher

+0

@Blaise Doughan Vui lòng đề nghị nếu tôi có thể sử dụng cùng mà không có tiền tố cho cả hai không gian tên. –