2010-09-10 12 views
50

Forse una domanda stupida: ho un List di tipo <Data> che voglio effettuare il marshalling in un file XML. Questa è la mia classe Database contenente un ArrayList ...JAXB: come effettuare il marshalling degli oggetti nelle liste?

@XmlRootElement 
public class Database 
{ 
    List<Data> records = new ArrayList<Data>(); 

    public List<Data> getRecords()     { return records; } 
    public void  setRecords(List<Data> records) { this.records = records; } 
} 

... e questo è di classe dati:

// @XmlRootElement 
public class Data 
{ 
    String name; 
    String address; 

    public String getName()   { return name;  } 
    public void setName(String name) { this.name = name; } 

    public String getAddress()    { return address;   } 
    public void setAddress(String address) { this.address = address; } 
} 

Utilizzando la seguente classe di test ...

public class Test 
{ 
    public static void main(String args[]) throws Exception 
    { 
     Data data1 = new Data(); 
      data1.setName("Peter"); 
      data1.setAddress("Cologne"); 

     Data data2 = new Data(); 
      data2.setName("Mary"); 
      data2.setAddress("Hamburg"); 

     Database database = new Database(); 
       database.getRecords().add(data1); 
       database.getRecords().add(data2); 

     JAXBContext context = JAXBContext.newInstance(Database.class); 
     Marshaller marshaller = context.createMarshaller(); 
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
        marshaller.marshal(database, new FileWriter("test.xml"));  
    } 
} 

. .. Ho ottenuto il risultato:

<database> 
    <records> 
     <address>Cologne</address> 
     <name>Peter</name> 
    </records> 
    <records> 
     <address>Hamburg</address> 
     <name>Mary</name> 
    </records> 
</database> 

Ma non è quello che mi aspettavo, ad esempio mancano tutti i tag per gli oggetti <Data>. Sto cercando un modo per esportare i dati nella seguente struttura, ma non so come raggiungere questo obiettivo:

<database> 
    <records> 
     <data> 
      <address>Cologne</address> 
      <name>Peter</name> 
     </data> 
     <data> 
      <address>Hamburg</address> 
      <name>Mary</name> 
     </data> 
    </records> 
</database> 

Una domanda aggiuntiva: se voglio affrontare il problema, senza utilizzando @XmlElementWrapper e @XmlElement annotazioni, posso introdurre una classe intermedia

public class Records 
{ 
    List<Data> data = new ArrayList<Data>(); 

    public List<Data> getData()    { return data; } 
    public void  setData(List<Data> data) { this.data = data; } 
} 

utilizzato dalla classe base modificata

@XmlRootElement 
public class Database 
{ 
    Records records = new Records(); 

    public Records getRecords()    { return records; } 
    public void setRecords(Records records) { this.records = records; } 
} 

in una leggermente modificata Test classe:

... 
Database database = new Database(); 
database.getRecords().getData().add(data1); 
database.getRecords().getData().add(data2); 
... 

Il risultato è anche:

<database> 
    <records> 
     <data> 
      <address>Cologne</address> 
      <name>Peter</name> 
     </data> 
     <data> 
      <address>Hamburg</address> 
      <name>Mary</name> 
     </data> 
    </records> 
</database> 

È questo il raccomandato modo per creare una struttura di classe Java in base alla struttura dei file XML di sopra ?

+0

Non vedo l'utilizzo di 'DataList' nella classe di test. – joschi

+0

Perdonami - ho copiato e incollato la classe sbagliata ... Ora è corretto nell'esempio sopra. – rmv

risposta

89

D'Aggiungi proprietà record:

@XmlElementWrapper(name="records") 
@XmlElement(name="data") 

Per ulteriori informazioni su JAXB e raccolta proprietà vedere:

+1

Fantastico, è tutto! Molte grazie. – rmv

+1

Ho dovuto aggiungere le annotazioni al "getter" per farlo funzionare ... –

+2

@LawrenceTierney - Il seguente articolo su '@ XmlAccessorType' può aiutare con annotazione di campi o proprietà (getter/setter): http: // blog. bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html –

3

Questo è in risposta alla tua seconda domanda disquised un risposta:

Entrambi gli approcci genereranno lo stesso XML. La mia raccomandazione è andare con il modello che è meglio per la tua applicazione. Per me generalmente utilizzo @ XmlElementWrapper/@ XmlElement. Poiché "i record" sono lì solo per organizzare gli elementi "dati", non merita davvero la sua classe.

conduco l'attuazione MOXy JAXB e offriamo un'estensione mappatura XPath a base di andare oltre ciò che è capace con @XmlElementWrapper:

+0

È davvero piuttosto impressionante cosa sta succedendo in quest'area. Penso di aver bisogno di tempo per entrare in contatto con questa nuova tecnica di mappatura. Puoi darmi un primo suggerimento, come leggere di nuovo i dati XML esportati nella struttura della classe? Se uso @ XmlElementWrapper/@ XmlElement per l'esportazione, il programma di importazione si lamenta che le classi corrispondenti sono (ovviamente :-) non esistenti ... – rmv

+0

L'importazione (unmarshal) dovrebbe funzionare, quale eccezione si ottiene? –

+1

Penso di avere un'eccezione che non è stato possibile trovare nella classe "Records". Ma per essere sicuro, lo verificherò domani con un esempio ... – rmv

3

In risposta alla tua seconda domanda:

Is this the recommended way to create a Java class structure 
according to the XML file structure above? 

Tecnicamente parlando, l'introduzione di una classe Records aggiuntiva per risolvere il problema JAXB è un lavoro non necessario e ridondante, poiché JAXB non ne ha bisogno. Il @XmlElementWrapper e @XmlElementname proprietà sono state progettate per risolvere il problema.

Dai commenti alla risposta di Blaise, mantengo un numero tutorial con esempi operativi che spiegano come comportarsi con classi generiche come Elenco, ecc. Quando non si esegue il marshalling.

+0

Ottimo sito di tutorial! – rmv

Problemi correlati