2010-09-10 27 views
50

Peut-être une question stupide: J'ai un List de type <Data> que je veux marshal dans un fichier XML. Ceci est ma classe Database contenant un ArrayList ...JAXB: Comment rassembler des objets dans des listes?

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

... ce qui est des données Classe:

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

Utilisation de la classe de test suivant ...

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

. ..J'ai obtenu le résultat:

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

Mais ce n'est pas ce à quoi je m'attendais, c'est-à-dire que toutes les étiquettes des objets <Data> sont manquantes. Je cherche un moyen d'exporter les données dans la structure suivante, mais je ne sais pas comment y parvenir:

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

Une question supplémentaire: si je veux régler le problème sans en utilisant @XmlElementWrapper et @XmlElement annotations, je peux introduire une classe intermédiaire

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

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

utilisé par la classe de base modifiée

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

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

dans une classe Test légèrement modifiée:

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

Le résultat est:

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

Est-ce le recommandé façon de créer une structure de classe Java selon la structure de fichier XML ci-dessus ?

+0

Je ne vous vois pas utiliser 'DataList' dans votre classe de test. – joschi

+0

Pardonnez-moi - j'ai copié et collé la mauvaise classe ... Il est maintenant corrigé dans l'exemple ci-dessus. – rmv

Répondre

89

Sur les dossiers propriété ajouter:

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

Pour plus d'informations sur les propriétés de JAXB et collection voir:

+1

Cool, c'est tout! Merci beaucoup. – rmv

+1

Je devais ajouter les annotations au "getter" pour que cela fonctionne ... –

+2

@LawrenceTierney - L'article suivant sur '@ XmlAccessorType' peut vous aider à annoter des champs ou des propriétés (getter/setter): http: // blog. bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html –

3

Ceci est en réponse à votre deuxième question disquised une answer:

Les deux approches généreront le même XML. Ma recommandation est d'aller avec le modèle qui convient le mieux à votre application. Pour moi, cela utilise généralement @ XmlElementWrapper/@ XmlElement. Puisque "records" est juste là pour organiser les éléments "data", il ne mérite pas vraiment sa propre classe.

Je mènent la mise en œuvre MOXy JAXB et nous offrons une extension de cartographie XPath à aller au-delà de ce qui est capable avec @XmlElementWrapper:

+0

C'est vraiment très impressionnant ce qui se passe dans ce domaine. Je pense que j'ai besoin de temps pour entrer en contact avec cette nouvelle technique de cartographie. Pouvez-vous me donner un premier indice, comment lire à nouveau les données XML exportées dans la structure de classe? Si j'utilise @ XmlElementWrapper/@ XmlElement pour l'export, le programme d'import se plaint que les classes correspondantes sont (évidemment :-) inexistantes ... – rmv

+0

L'import (unmarshal) devrait juste fonctionner, quelle exception obtenez-vous? –

+1

Je pense avoir eu une exception que la classe 'Records' n'a pas pu être trouvée. Mais pour être sûr, je vais le vérifier par un exemple demain ... – rmv

3

En réponse à votre deuxième question:

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

Techniquement, l'introduction d'une classe supplémentaire Records pour résoudre votre problème JAXB est inutile et redondante, car JAXB n'en a pas besoin. Les propriétés @XmlElementWrapper et @XmlElementname ont été conçues pour résoudre votre problème.

De vos commentaires à la réponse de Blaise, je maintiens un tutorial avec des exemples opérationnels expliquant comment faire face à des classes génériques telles que List, etc. quand unmarshalling.

+0

Excellent site de tutoriel! – rmv