2010-09-08 11 views
21

Ho una classe con un'annotazione XmlElementWrapper come:Come posso aggiungere gli attributi xml alla classe annotata jaxb XmlElementWrapper?

...

@XmlElementWrapper(name="myList") 
    @XmlElements({ 
    @XmlElement(name="myElement") } 
    ) 
    private List<SomeType> someList = new LinkedList(); 

... Questo codice produce XML come

<myList> 
    <myElement> </myElement> 
    <myElement> </myElement> 
    <myElement> </myElement> 
</myList> 

finora tutto bene.

Ma ora ho bisogno di aggiungere attributi al tag lista per ottenere XML come

<myList number="2"> 
    <myElement> </myElement> 
    <myElement> </myElement> 
    <myElement> </myElement> 
</myList> 

C'è un 'modo intelligente per raggiungere questo obiettivo senza creare una nuova classe che contiene rappresenta l'elenco?

risposta

22

Ho una soluzione migliore per la tua domanda .

Per rendere oggetto XML Java, utilizzare il seguente codice:

import java.util.*; 
import javax.xml.bind.annotation.*; 

@XmlRootElement(name="myList") 
public class Root { 

    private String number; 
    private List<String> someList; 

    @XmlAttribute(name="number") 
    public String getNumber() { 
     return number; 
    } 

    public void setNumber(String number) { 
     this.number = number; 
    } 

    @XmlElement(name="myElement") 
    public List<String> getSomeList() { 
     return someList; 
    } 

    public void setSomeList(List<String> someList) { 
     this.someList = someList; 
    } 

    public Root(String numValue,List<String> someListValue) { 
     this(); 
     this.number = numValue; 
     this.someList = someListValue; 
    } 

    /** 
    * 
    */ 
    public Root() { 
     // TODO Auto-generated constructor stub 
    } 

}

Per eseguire il codice sopra utilizzando JAXB, utilizzare il seguente:

import java.util.ArrayList; 
import java.util.List; 

import javax.xml.bind.*; 

public class Demo { 

     public static void main(String[] args) throws Exception { 
      List<String> arg = new ArrayList<String>(); 
      arg.add("FOO"); 
      arg.add("BAR"); 
      Root root = new Root("123", arg); 

      JAXBContext jc = JAXBContext.newInstance(Root.class); 
      Marshaller marshaller = jc.createMarshaller(); 
      marshaller.marshal(root, System.out); 
     } 
} 

questo produrrà il XML seguente come output:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
    <myList number="123"> 
     <myElement>FOO</myElement> 
     <myElement>BAR</myElement> 
    </myList> 

Penso che questo sia più utile per te.

Grazie ..

+2

La soluzione di Noby funziona bene se hai solo un tipo di raccolta da incartare (nell'esempio, è una stringa). Se si desidera estendere la soluzione per creare una classe di wrapper di elenchi più generica con attributi, è possibile utilizzare l'annotazione @XmlElements per creare associazioni aggiuntive. Sto esaurendo lo spazio in questo commento, quindi posterò il codice di esempio in un'altra risposta. –

11

L'implementazione JAXB (io sono in vantaggio Tech) ha un'estensione (@XmlPath) per gestire questo caso:

import java.util.*; 
import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Root { 

    @XmlPath("myList/@number") 
    private int number; 

    @XmlElementWrapper(name="myList") 
    @XmlElement(name="myElement") 
    private List<String> someList = new LinkedList<String>(); 

    public int getNumber() { 
     return number; 
    } 

    public void setNumber(int number) { 
     this.number = number; 
    } 

    public List<String> getSomeList() { 
     return someList; 
    } 

    public void setSomeList(List<String> someList) { 
     this.someList = someList; 
    } 

} 

produrrà il seguente codice XML:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <myList number="123"> 
     <myElement>FOO</myElement> 
     <myElement>BAR</myElement> 
    </myList> 
</root> 

Quando questo codice viene eseguito:

import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Root.class); 

     Root root = new Root(); 
     root.setNumber(123); 
     root.getSomeList().add("FOO"); 
     root.getSomeList().add("BAR"); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 
} 

Per farlo funzionare con rigorosamente standard Codice d JAXB sarà necessario utilizzare un adattatore XML:

Nota:

Per utilizzare moxy JAXB è necessario aggiungere un file chiamato jaxb.properties con il tuo classi modello con la seguente voce:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 
+0

Ottima risposta! C'è un modo per mettere un attributo hardcoded costante a un elemento? Ad esempio, solo aggiungendo qualcosa come 'drawable =" true "' in fase di progettazione ad alcuni degli @XmlElement senza la necessità di creare un campo speciale per ognuno di essi? – NumberFour

4

Se non si utilizza moxy o semplicemente si vuole attenersi a standard di annotazioni JAXB, è possibile estendere alla risposta di Noby per aggiungere il supporto per una classe wrapper generico.La risposta di Noby solo al momento supporta un elenco di stringhe, ma ad esempio stai per utilizzare la stessa classe wrapper generica per diverse classi diverse. Nel mio esempio, voglio creare una classe generica "PagedList" che eseguirà il marshalling verso qualcosa che assomiglia a un elenco, ma contiene anche informazioni sull'offset della pagina e il numero totale di elementi nell'elenco non aperto.

Uno svantaggio di questa soluzione è che è necessario aggiungere ulteriori mapping @XmlElement per ogni tipo di classe che verrà spostato. Nel complesso, tuttavia, probabilmente è una soluzione migliore rispetto alla creazione di una nuova classe per ogni elemento pagabile.

@XmlType 
public class PagedList<T> { 
    @XmlAttribute 
    public int offset; 

    @XmlAttribute 
    public long total; 

    @XmlElements({ 
     @XmlElement(name="order", type=Order.class), 
     @XmlElement(name="address", type=Address.class) 
     // additional as needed 
    }) 
    public List<T> items; 
} 

@XmlRootElement(name="customer-profile") 
public class CustomerProfile { 
    @XmlElement 
    public PagedList<Order> orders; 
    @XmlElement 
    public PagedList<Address> addresses; 
} 

Marshalling questo esempio si otterrebbe:

<customer-profile> 
    <order offset="1" total="100"> 
     <order> ... </order> 
     <order> ... </order> 
     <order> ... </order> 
     ... 
    </orders> 
    <addresses offset="1" total="5"> 
     <address> ... </address> 
     <address> ... </address> 
     <address> ... </address> 
     <address> ... </address> 
     <address> ... </address> 
    <addresses> 
</customer-profile> 

Speranza che aiuta. Questa è la soluzione che ho risolto almeno.

Problemi correlati