# jaxb Vector (oder ähnliches) von Elementen generieren



## Gast (17. Nov 2008)

Hallo,

folgendes Problem. Ich habe eine XML - Datei, in der die Elemente (SAND, WASSER, ZEMENT) beliebig oft in vorher nicht bekannter Reihenfolge erscheinen. Mir ist bisher keine Umsetzung in ein xml-Schema gelungen, welches die Reihenfolge und das mehrmalige Auftreten der Elemente berücksichtigt, so das jaxb java-Klassen generieren kann. Weiss jemand Rat? Ich habe mal ein Beispiel rangehangen:

<ROOT>
 <VERSUCH>
  <SAND gewicht="50g" körnung="grob"/> 
  <WASSER gewicht="100g"/>
  <SAND gewicht="50g" körnung="fein"/>
  <SAND gewicht="10g" körnung="sehrfein"/>
  <ZEMENT gewicht="200g" farbe="weiß">W21</ZEMENT>
 </VERSUCH>
 <VERSUCH>
  <SAND gewicht="50g"/>
  <SAND gewicht="50g"/> 
  <ZEMENT gewicht="75g" farbe="grau">W22</ZEMENT>
  <WASSER gewicht="100g"/>
  <ZEMENT gewicht="25g" farbe="weiß">W21</ZEMENT>
 </VERSUCH>
</ROOT>


----------



## ralfz (18. Nov 2008)

Hi, willst du "nur" die Objekte nach Java holen, oder brauchst du ein XML Schema? Reicht nicht evtl. auch eine DTD?

Wenn du die Daten nur einlesen willst, dann würde ich einfach die Klassenstruktur per Hand aufbauen, dass ist ja schnell gemacht. (Ich bin allerdings noch ziemlich neu, was JAXB angeht).

Die Struktur wäre dann ja einfach mal kurz überlegt nur: (ohne Gewähr)



```
@XmlRootElement(name="ROOT")
class Store{

List<Versuch> listv;
}

class Versuch{

List<Wasser> listw;
List<Zement> listz;
List<Sand> lists;
}

class Wasser{
@XmlAttribute
String gewicht
}

class Sand{
@XmlAttribute
String gewicht
@XmlAttribute
String körnung
}

class Zement{
@XmlAttribute
String gewicht
@XmlAttribute
String farbe
String wert
}
```

ODER?

Gruß
Zirni


----------



## Gast (18. Nov 2008)

Hallo ralfz,

das allerliebste wäre eine automatische Generierung der java-Klassen mittels einem XML-Schema. Aber so geht es auch. Die Reihenfolge der Elemente WASSER, ZEMENT und SAND ist wichtig, vermutlich muss ich die Klasse VERSUCH ändern nach: 


```
class Versuch{
Vector vecWZS;
}
```

um beliebige Objekte vom Typ WASSER, ZEMENT und SAND in einer vorgeschriebenen Reihenfolge abzuspeichern?!

Gruß,
uf


----------



## ralfz (18. Nov 2008)

Hi,

also um die Order der Elemente bei der Ausgabe festzulegen, gibt es eine Annotation:
@XmlType( propOrder={  ...}

Bei Versuch wäre das dann wohl:


```
@XmlType( propOrder="listw","listz","lists"})
class Versuch{

// jetzt noch nen paar bessere Namen
@XmlElement(name="WASSER")
List<Wasser> listw;
@XmlElement(name="ZEMENT")
List<Zement> listz;
@XmlElement(name="SAND")
List<Sand> lists;
}
```

Dann sollte das schon gehen... 

Viel Erfolg

Falls du übrigens eine "Ebene" zu viel hast kannst du die Annotation "@XmlValue" nutzen. 
Die habe ich gerade den halben Tag gesucht 

also um bei Zement aus:

```
class Zement{
@XmlAttribute
String gewicht
@XmlAttribute
String farbe
String wert
} 

// mit
 <ZEMENT gewicht="25g" farbe="weiß">
      <wert>W21</wert>
</ZEMENT>

// das hier zu machen:
 <ZEMENT gewicht="25g" farbe="weiß">W21</ZEMENT> 

// brauchst du:
 class Zement{
@XmlAttribute
String gewicht
@XmlAttribute
String farbe
@XmlValue  // <------
String wert
}
```

Gruß
Zirni


----------



## ralfz (18. Nov 2008)

Ohh,

jetzt hab ich gerade erst deine Aussage richtig erfasst....

Du musst die Zutaten nicht gruppiert erfassen, sondern genau so wie sie vorkommen...

Hmm, da hab ich doch eben noch was gelesen... wo war das bloss....

Ahh hier:

https://jaxb.dev.java.net/nonav/jaxb20-pfd/api/index.html

du brauchst "@XmlElementRef" für eine allgemeine Liste:

Schau mal bei Example1:


```
@XmlRootElement(name="target")
     class Target {
         // The presence of @XmlElementRef indicates that the XML
         // element name will be derived from the @XmlRootElement 
         // annotation on the type (for e.g. "jar" for JarTask). 
         @XmlElementRef
         List tasks;
     }

     abstract class Task {
     }

     @XmlRootElement(name="jar")
     class JarTask extends Task {
         ...
     }

     @XmlRootElement(name="javac")
     class JavacTask extends Task {
         ...
     }
```

daraus sollte dann:


```
// mit:
Target target = new Target();
     target.tasks.add(new JarTask());
     target.tasks.add(new JavacTask());
     
     marshal(target);

//das hier werden:

<target>
       <jar>
         ....
       </jar>
       <javac>
         ....
       </javac>
</target>
```

Sollte so gehen, oder?

Gruß
Zirni


----------



## Gast (18. Nov 2008)

super, das ist es, vielen Dank!

uf


----------



## ralfz (18. Nov 2008)

Noch besser:

Das hier sollte gehen:


```
//Liste mit verschiedenen Elementen
@XmlElementWrapper(name="Sammlung")
@XmlElements({
    @XmlElement(name="Book", type=Book.class),
    @XmlElement(name="Paper", type=Paper.class)
    })
public List getLoseSammlung(){
 return lose;
}

/* dazu hatte ich 
lose.add(paper);
lose.add(book);
lose.add(paper);
lose.add(paper);
lose.add(book);
*/
```

Und bekomme:


```
<Sammlung>
     <Paper id="999">loses Paper_999</Paper>
     <Book>
         <isbn>978-0060554736</isbn>
         <name>The Game</name>
         <author>Neil Strauss</author>
         <publisher>Harpercollins</publisher>
     </Book>
     <Paper id="999">loses Paper_999</Paper>
     <Paper id="999">loses Paper_999</Paper>
     <Book>
         <isbn>978-0060554736</isbn>
         <name>The Game</name>
         <author>Neil Strauss</author>
         <publisher>Harpercollins</publisher>
     </Book>
 </Sammlung>
```



Gruß
Zirni


----------

