2013-04-02 28 views
11

xml'de ad alanlarını kullanıyorum, bu yüzden kafam karıştı ve biraz netleme istiyorum. Çok farklı ad alanlarına sahip xml belgeleri aldığım bir java hizmetim var ve çalışmamı sağladığımda, kontrol etmek istediğim bir şey yapmam gerekiyormuş gibi hissediyorum. ile açıklamalı sınıftaJaxb: Aynı pakette birden çok ad alanı bulunan unmarshalling xml

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

ve her alan: Bir Train.java ile sınıf düzeyinde ek not verdiğiniz

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

: gibi benim package-info.java olarak benim şema ek açıklaması :

@XmlElement(name="Color") for example 

Tren Yolcu (lar) bir listesini içermesi için bir özellik var

private Set<Passenger> passengers; 

ve bu koleksiyon ile açıklamalı edilir:

sınıf kendisi ile açıklamalı Passenger.java içinde Sonra
@XmlElementWrapper(name="Passengers") 
@XmlElements(@XmlElement(name="Passenger", namespace="http://mycompany/passenger")) 

:

Passenger.java içinde tek tek alanlar için Nihayet
@XmlElement(name="Passenger", namespace="http://mycompany/passenger") 

, bunlar aşağıdaki şekilde açıklamalı :

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

Yani gibi görünen bir xml olduğunda:

Şimdi aldığım bu xml'yi küçümsedim ve Train's Colour özelliği ayarlandı ve Passenger'ın TicketNumber özelliği ayarlandı. Ama neden çalışmak için BiletNumber üzerinde XmlElement ek açıklama üzerinde ad alanı url eklemek gerekiyor bilmiyorum ama ben Color özelliği için trende gerek yoktu. Namepace özniteliğini TicketNumber üzerindeki XmlElement ek açıklamasından kaldırırsam, xml isteğindeki ad alanı önekini de kaldırmazsam, xml değerinden alınan değer nesneye eşlenir. Yolcu için XmlRootElement üzerinde tanımlanan ad alanı özniteliğine sahip olduğumdan beri, tıpkı benim için her zaman olduğu gibi sınıftaki her alan için bunu yapmam gerekmediğini hissediyorum. yanlış bir şey kurmuş olmalı. Birisi bana doğru yönde işaret edebilir mi? Teşekkürler!

cevap

24

Aşağıda, ad alanlarınızın modelinize göre JAXB (JSR-222) içinde nasıl çalıştığı açıklanmaktadır.

JAVA MODELİ

paket-info Aşağıda

sizin @XmlSchema açıklama değiştirilmiş versiyonu. - Başka bir ad yok küresel elemanlar (elementFormDefault değerine dayalı @XmlRootElement ve @XmlElementDecl ek açıklamalar (ve yerel unsurlara karşı gelenlerden nitelemek için kullanılacak varsayılan ad)

  • namespace: Bazı önemli bilgiler içerir belirtildi.
  • elementFormDefault varsayılan olarak yalnızca global öğeler ad alanı niteliğinde kalifiye olup, değeri XmlNsForm.QUALIFIED olarak ayarlandığında, belirtilmiş açık bir ad alanı olmayan tüm öğeler namespace değeriyle nitelenecektir.
  • xmlns, JAXB impl'in bu ad alanları için kullanması gereken öneklerin (diğer önekleri kullanabilmesine rağmen) tercih edilen setidir.
@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.*; 

Tren

Train sınıfa karşılık gelen tüm unsurları @XmlSchema açıklama belirtilen namespace karşılık yana, herhangi bir ad bilgi belirtmek gerekmez.

  • Genel Öğeler - @XmlRootElement ek açıklaması, global bir öğeye karşılık gelir.
  • Yerel Öğeler - @XmlElementWrapper ve @XmlElement ek açıklamaları yerel öğelere karşılık gelir. Yolcu

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

} 

tüm unsurları http://mycompany/passenger ad olacaktır Passenger sınıfına özelliklerine tekabül ederse, o zaman @XmlSchema ek açıklamadan namespace geçersiz kılmak için @XmlType ek açıklama kullanabilirsiniz. Ad alanı özelliğini özellik düzeyinde geçersiz kılabilirsiniz. Alternatif olarak, aynı şekilde ad alanını da geçersiz kılabilirsiniz.

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

} 

aşağıdaki demo kodu her şeyin kanıtlamak için çalıştırılabilir

DEMO KOD çalışır:

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/Çıktı

Aşağıdaki XML'de, sorunuzdaki XML belgesinden eksik olan gerekli ad alanı bildirimlerini ekledim. Süper kapsamlı cevap için DAHA FAZLA BİLGİ İÇİ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> 

+1

teşekkürler. Bu benim problemimi çözdü ve hayal ettiğim gibi çalışıyor. XmlRootElement öğesini her "alt sınıfta" hatalı olarak kullanıyor ve XmlType yerine bu açıklamada ad alanını bildiriyordum. – Frequentcrasher

+0

@Blaise Doughan Lütfen, her iki ad alanı için de önek kullanmadan kullanabilir miyim, lütfen öner. –