# JAXB - Problem mit Java Listen unmarshalling



## will2k (26. April 2008)

Hallo,


xml Datei:



```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settingsData>
    <Movie Format>AVI</Movie Format>
    <Movie Format>MPG</Movie Format> 
    <Movie Format>MPEG</Movie Format>
</settingsData>
```



Codeauszug aus der Klasse SettingsData:


```
@XmlElement( name = "Movie Format" )
public List<String> elements = new ArrayList<String>();
```


xml datei wird geladen:


```
JAXBContext jc = JAXBContext.newInstance(SettingsData.class);
Unmarshaller um = jc.createUnmarshaller ();
           
Object o = um.unmarshal(new FileInputStream("settings.xml"));
settingsdata = (SettingsData) o;       
          
for(int i = 0 ; i < settingsdata.getElements().size() ; i++)
System.out.println(settingsdata.getElements().get(i));
```


Die letzten beiden Zeilen sorgen für diesen Fehler:


```
javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException: Attribute name "Format" associated with an element type "Movie" must be followed by the ' = ' character.]
```


Versteht jemand die Fehlermeldung?


----------



## zeja (27. April 2008)

Du darfst so keine Leerzeichen in XML-Elementen verwenden. Ich weiß gerade nicht obs überhaupt geht, aber wenn dann nur codiert.

Im Moment hält er Movie für den Namen des Elements und Format für ein Attribut, welchem aber kein Wert zugewiesen ist. Die Fehlermeldung bezieht sich darauf dass er sowas erwartet: <Movie Format=Wert> </Movie>

Was du willst ist aber wohl <MovieFormat></MovieFormat>


----------



## will2k (27. April 2008)

zeja hat gesagt.:


> Du darfst so keine Leerzeichen in XML-Elementen verwenden. Ich weiß gerade nicht obs überhaupt geht, aber wenn dann nur codiert.
> 
> Im Moment hält er Movie für den Namen des Elements und Format für ein Attribut, welchem aber kein Wert zugewiesen ist. Die Fehlermeldung bezieht sich darauf dass er sowas erwartet: <Movie Format=Wert> </Movie>
> 
> Was du willst ist aber wohl <MovieFormat></MovieFormat>



danke jetzt gehts auch mit ein und auslesen der List elemente. Doch eine wichtige Frage habe ich noch:

das ganze sind ja beliebige elemente einer Liste müsste das ganze dann nicht eher so aussehen:


```
<settingsData>
       <list1>
              <MovieFormat>AVI</MovieFormat>
        </list
        <list2>
              <MovieFormat>MPG</MovieFormat>
        </list>
<settingsData>
```

oder so ähnlich?

Ich habe mir dieses Beispiel angeschaut:

http://www.tutego.com/blog/javainsel/2008/02/mikroformate-mit-jaxb-in-xml-abbilden.html

da werden sogar 2 Klassen benutzt nur um listeneinträge in einer xml zu speichern, OK die einträge sehen eben aufwendiger aus in der xml Datei und sind mehr unterteilt, ums kurz zu machen ich würde einfach gerne wissen ob man beliebige Einträge anders speichert als ich dies machte ganz oben!?

so lese ich die listeinträge aus in der xml_lade methode:


```
for(int i = 0 ; i < settingsdata.getElements().size() ; i++)
	     
	        myJComboBox.addItem(settingsdata.getElements().get(i));
```


----------



## zeja (27. April 2008)

Ich würde es so machen:


```
<settingsData>
    <movieFormats>
         <MovieFormat>AVI</MovieFormat>
         <MovieFormat>MPG</MovieFormat> 
         <MovieFormat>MPEG</MovieFormat>
    </movieFormats>
</settingsData>
```

Dann kannst du auch mehr als eine Einstellung in deinen settingsData ablegen und hast eine ordentliche Struktur.


----------



## will2k (27. April 2008)

zeja hat gesagt.:


> Ich würde es so machen:
> 
> 
> ```
> ...



hm... wenn ich also <movieFormats> habe als Überdingens...muss ich dann nicht auch eine eigene Javaclass MovieFormats machen und in dieser ist die Liste drin? Was ich bei deinem guten Beispiel nicht verstehe wie ich die Struktur mit Java hinbekomme


----------



## zeja (27. April 2008)

Probier mal:

```
@XmlElementWrapper(name="movieFormats")
@XmlElement( name = "MovieFormat" )
public List<String> elements = new ArrayList<String>();
```


----------



## Thomas Darimont (27. April 2008)

Hallo,


```
package de.tutorials.domain;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;

@XmlType(name = "movieFormat")
@XmlAccessorType(XmlAccessType.FIELD)
public class MovieFormat {

	@XmlValue
	private String name;

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return this.name;
	}
	
}
```


```
/**
 * 
 */
package de.tutorials.domain;

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

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

/**
 * @author Tom
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="settingsData")
@XmlRootElement(name="settingsData")

public class SettingsData {
	
	@XmlElement(name="movieFormat")
	@XmlElementWrapper(name="movieFormats")
	private List<MovieFormat> movieFormats = new ArrayList<MovieFormat>();

	public List<MovieFormat> getMovieFormats() {
		return movieFormats;
	}

	public void setMovieFormats(List<MovieFormat> movieFormats) {
		this.movieFormats = movieFormats;
	}
}
```


```
/**
 * 
 */
package de.tutorials;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import de.tutorials.domain.SettingsData;

/**
 * @author Tom
 *
 */
public class JAXBExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		JAXBContext jaxbContext = JAXBContext.newInstance(SettingsData.class);
		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		
		SettingsData settingsData = (SettingsData) unmarshaller.unmarshal(new File("data.xml"));
		System.out.println(settingsData.getMovieFormats());
	}
}
```


```
<?xml version="1.0" encoding="UTF-8"?>
<settingsData>
	<movieFormats>
		<movieFormat>AVI</movieFormat>
		<movieFormat>MPG</movieFormat>
		<movieFormat>MPEG</movieFormat>
	</movieFormats>
</settingsData>
```

Ausgabe:

```
[AVI, MPG, MPEG]
```

ansonsten schau mal hier:
http://www.tutorials.de/forum/java/263489-jaxb-tutorial.html

Gruß Tom


----------



## will2k (27. April 2008)

danke t super!

nur 1 Problem habe ich dadurch:

bisher sah die .xml so aus:


```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settingsData>
    <company>Warner Bros.</company>
    <playtime>90</playtime>
</settingsData>
```

nun sollte sie ja so aussehen:



```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settingsData>
    <company>Warner Bros.</company>
    <playtime>90</playtime>
    <movieFormats>
        <movieFormat>AVI</movieFormat>
        <movieFormat>MPG</movieFormat>
        <movieFormat>MPEG</movieFormat>
    </movieFormats>
</settingsData>
```

doch die datei sieht so aus:


```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<settingsData>
    <company>Warner Bros.</company>
    <playtime>90</playtime>
    <movieFormats/>
</settingsData>
```

Es scheint so als ob bei Schreiben sich was in die Quere kam?

Wie ist das eigentlich mit beliebigen Strings in einer JComboBox, ich lese die ja aus der .xml Datei in eine Jcombobox ein, doch speichern tue ich sie nicht, was ich ja eigentlich auch nicht muss bzw. würde das Sinn machen, denn der benutzer kann ja per GUI keine filmformate hinzufügen sondern nur per .xml Datei Zeile hinzufügen etc.?


----------



## zeja (27. April 2008)

Wenn du nicht möchtest dass der Nutzer was hinzufügt, ist es dann überhaupt sinnvoll das in der XML abzulegen? Man könnte ja die XML-Datei ändern....

Vielleicht solltest du die Formate auf ein Enum Mappen, dann kannst du dir zumindest darüber sicher sein dass nichts hinzukommt.

Und ich denke deine XML sieht nun so aus, weil du die Formate eben nicht gespeichert hast und die Liste somit irgendwie leer war.


----------



## will2k (27. April 2008)

zeja hat gesagt.:


> Wenn du nicht möchtest dass der Nutzer was hinzufügt, ist es dann überhaupt sinnvoll das in der XML abzulegen? Man könnte ja die XML-Datei ändern....
> 
> Vielleicht solltest du die Formate auf ein Enum Mappen, dann kannst du dir zumindest darüber sicher sein dass nichts hinzukommt.
> 
> Und ich denke deine XML sieht nun so aus, weil du die Formate eben nicht gespeichert hast und die Liste somit irgendwie leer war.



denke du hast mich falsch verstanden etvtl... der Nutzer darf schon was ändern nur geht das nicht über die GUI da ich dann wieder was coden müsste... (faulheit nennt man das ;-) )

ok dann mach ich halt doch ein paar comboboxen dazu mit +/- button dann kann der user das über die GUI machen... danke euch


----------



## will2k (1. Mai 2008)

Verständnisproblem:


```
public void setMovieFormats(List<MovieFormat> movieFormats) {
   
    	this.movieFormats = movieFormats;   
    }
```

gemäß obiger Methode übergebe ich ein Listobjekt welches Objekte enthält vom Typ MovieFormat. Soweit OK. Nun frage ich mich aber, wie lese ich einzelne Strings die sich nun eben in einer JComboBox befinden in das objekt MovieFormat ? Und warum benötige ich eine eigene Klasse MovieFormat wenn ich nur beliebe strings einlesen will in eine Liste?


----------



## zeja (1. Mai 2008)

Ein String ist eben nur ein String und wenn der im Sourcecode auftaucht weiß man nicht so genau was er beeinhaltet. Da ist es doch schöner wenn man von einem Objekt MovieFormat liest.

Du kannst ja noch einen Konsruktor zu der Klasse hinzufügen:

```
public class MovieFormat {

private MovieFormat(){}//Wird von JAXB benötigt

public MovieFormat(String name) {
this.name = name;
}

}
```

Dann kannst du dir mit new MovieFormat(String) ein Objekt erstellen und alles ist gut


----------



## will2k (2. Mai 2008)

zeja hat gesagt.:


> Ein String ist eben nur ein String und wenn der im Sourcecode auftaucht weiß man nicht so genau was er beeinhaltet. Da ist es doch schöner wenn man von einem Objekt MovieFormat liest.
> 
> Du kannst ja noch einen Konsruktor zu der Klasse hinzufügen:
> 
> ...



danke zeja dass du mir immer antwortest, ich weiß das echt zu schätzen, dennoch denke ich reden wir bissl einander vorbei 

Schau mal:

Ich habe eine GUI da kann der Benutzer meines Programmes selbst die filmformate hinzufügen die er auf seiner Festplatte hast. Das hinzufügen geschieht über eine editierbare jcombobox per "+" oder "-"-button sprich er kann formate der liste hinzufügen/aus liste löschen. Nun sind das einfache Strings und keine Objekte, denn diese formate wie avi,mov,wmv,mpeg usw. haben und werden keine weiteren eigenschaften haben (ein Objekt hingegen hat eigenschaften für mich). Was Ihr mir vorschlagt soweit ich JAXB bisher verstand sind eher Komplexe Typen, doch mir reicht völlig in dieser Situtation ein Simple Typ. Ich werde heute abend wenn mir die Zeit reicht nochmals ein einfaches public List<String> movieformatnames; Beispiel posten und was genau ich daran nicht verstehe 

Was mir bisher anhand meines jaxb 2.0 buches nicht klar wurde ist, WIE erstelle ich diese XML-Schemata ? und für was überhaupt denn bisher gings auch so...


----------



## zeja (2. Mai 2008)

Ich denke XML Schemata werden nicht unbedingt in einem JAXB Buch behandelt. Such mal danach. Mit einem Schema kannst du unter anderem sicherstellen dass deine XML Datei wohlgeformt ist, also einem bestimmten Aufbau entspricht. Das Schema kann man bei JAXB zur Validierung mit angeben.

Mein Beispiel war übrigens mit Strings. Mußt du wissen wie dus benutzen willst.


----------



## Oliver Gierke (3. Mai 2008)

Ich seh den Fokus eigentlich ein wenig anders bei JAXB. XSD ist eigentlich der Kern von JAXB. XSD ist eine (Programmiersprachen-)unabhängige Beschreibungssprache für XML. Wie Zeja schon geschrieben hat legst du damit den Aufbau und Restriktionen für ein XML Dokument fest. JAXB erlaubt dir nun die Verarbeitung von XML Dateien für ein XSD. Das heißt sämtliche Strukturierungsinformationen für die Javaklassen die du benötigst werden im Generierungsschritt aus dem XSD gezogen. Danach brauchst du es nicht mehr. 

Das sorgt dafür, dass du bei einer Änderung am XSD einfach die Klassen neu generieren kannst und halt die Clients entsprechen anpassen musst. JAXB kommt eigentlich aus der WebServices Ecke. Dort werden halt SChnittstellen sprachenneutral beschrieben.

Lange Rede, kurzer Sinn: du solltest für dein XML ein XSD definieren und dir dann die Klassen vom XJC generieren lassen. Dann versuchst du das XML per JAXB zu mappen und wenn Probleme auftauchen, passt du das XSD bzw. XML nach und nach an.

Gruß
Ollie


----------



## zeja (3. Mai 2008)

Hmm das sehe ich ein wenig anders. So war es früher vielleicht mal uns so mag es auch sinnvoll sein wenn man für das XML eine bestimmte Struktur haben möchte. Wenn man jedoch JAXB nur für XML-Persistenz verwendet und einem der Aufbau eigentlich egal ist, warum sollte man sich dann die Mühe machen und ne XSD schreiben, wo Java-Klassen schreiben und annotieren so viel einfacher ist.

Also jetzt jemanden dazu zwingen wollen ne XSD zu schreiben ist nun wirklich überflüssig. JAXB unterstützt beide Vorgehensweisen und das ist auch gut so.


----------



## will2k (4. Mai 2008)

zeja hat gesagt.:


> Hmm das sehe ich ein wenig anders. So war es früher vielleicht mal uns so mag es auch sinnvoll sein wenn man für das XML eine bestimmte Struktur haben möchte. Wenn man jedoch JAXB nur für XML-Persistenz verwendet und einem der Aufbau eigentlich egal ist, warum sollte man sich dann die Mühe machen und ne XSD schreiben, wo Java-Klassen schreiben und annotieren so viel einfacher ist.
> 
> Also jetzt jemanden dazu zwingen wollen ne XSD zu schreiben ist nun wirklich überflüssig. JAXB unterstützt beide Vorgehensweisen und das ist auch gut so.



danke zeja dass du das geschrieben hast hehe denn mit Olivers Aussage musst ich dann doch ganz schön schlucken :suspekt: 

und ja stimmt zeja du hast wirklich das ganze mit String mir gezeigt...habs völlig verpeilt wegen dem riesigen Beispiel von Thomas hehe. Ich melde mich nochmals in den Pfingstferien habe ne volle Woche


----------



## Oliver Gierke (4. Mai 2008)

Hm... ich seh das so. XML ohne XSD oder DTD ist wie ein Sprache ohne Grammatik. Wie oft habe ich mir schon bei diversen Tools nen Wolf gesucht, weil die irgendwelche XML Konfigurationsfiles benötigen und nirgendwo spezifiziert ist, wie Elemente geschachtelt werden dürfen, was für Attribute notwendig sind usw. XML von Hand editieren ohne Toolunterstützung ist nicht nur fehleranfällig sondern auch unheimlich mühsam. Da bist du dann in null Komma nichts wieder bei trial / error Konfiguration / Programmierung.

Eure letzte zwei Posts klingen auch etwas, als wäre XSD der Vorort der Hölle. Das XSD zu eurem Beispiel XML oben hat vielleicht 20 Zeilen. Selbst wenn man von XSD kaum Ahnung hat, zahlt sich die Zeit die man da reinsteck doppelt und dreifach aus. Gerade wenn du das XML verarbeiten willst. Ohne XSD kannst du das XMl nicht wirklich validieren und es fliegen recht schnell irgendwelche Exceptions, wenn ein Element nicht gefunden wird o.ä. Btw. glaub ich auch nicht, dass es mehr Zeit kostet sich in die Annotationen einzuarbeiten, als in XSD


```
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">

	<!-- Rootelelement -->
	<xsd:element name="settingsData">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="company" type="xsd:string" />
				<xsd:element name="playtime" type="xsd:int" />
				<xsd:element name="movieFormats" type="tns:movieFormats" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>
	
	<!-- Movie Formats list -->
	<xsd:complexType name="movieFormats">
		<xsd:sequence>
			<xsd:element name="movieFormat" type="tns:movieFormat" />
		</xsd:sequence>
	</xsd:complexType>
	
	<!-- Single movie format -->
	<xsd:simpleType name="movieFormat">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="AVI" />
			<xsd:enumeration value="MPG" />
			<xsd:enumeration value="MPEG" />
		</xsd:restriction>
	</xsd:simpleType>

</xsd:schema>
```

REINHAUN!


----------



## will2k (20. August 2008)

Oliver Gierke hat gesagt.:


> Lange Rede, kurzer Sinn: du solltest für dein XML ein XSD definieren und dir dann die Klassen vom XJC generieren lassen. Dann versuchst du das XML per JAXB zu mappen und wenn Probleme auftauchen, passt du das XSD bzw. XML nach und nach an.



so mal wieder etwas zeit für java ^^ :

ganz stupide: ich geh in mein notepad, schreib das schema rein wie du siehe unten, wo ist da aber die echtzeicht Syntax-Prüfung? Gibts das in Java nicht? Gibts kein vernüftiges Tool, welches mir die .xsd erstellt indem ich z.B. über ein Formular die elemente angeben, ob es simple/complex sind, enumerationen/listen etc 




> 1.
> <?xml version="1.0" encoding="UTF-8"?>
> 2.
> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">
> ...


----------



## Oliver Gierke (20. August 2008)

Was hat das mit Java zu tun?

Vorschlag: Installier dir Eclipse, leg das XSD File in irgendein Projekt. Dann gehts nach "Einstellungen -> XML Catalog -> Add...". Dort fügst du das File dem Catalog hinzu und machst die entsprechenden Einstellungen.

Wenn du nun ein XML File anlegst und dort auf die Schema URI verweist erkennt das Eclipse und validiert das Dokument inplace.

Gruß
Ollie


----------



## will2k (20. August 2008)

Oliver Gierke hat gesagt.:


> Was hat das mit Java zu tun?
> 
> Vorschlag: Installier dir Eclipse, leg das XSD File in irgendein Projekt. Dann gehts nach "Einstellungen -> XML Catalog -> Add...". Dort fügst du das File dem Catalog hinzu und machst die entsprechenden Einstellungen.
> 
> ...



weil Jaxb zu java gehört

Du verstehst mich nicht... ich kann das xsd file nigends hinlegen, da ich keine info darüber finde wie man diese Datei erstellt... nach welchen Regeln erstellst du die .xsd datei die du dann einfach mit notepad als .xsd speicherst?


----------



## Oliver Gierke (21. August 2008)

Dein Problem ist doch aber nicht JAXB sondern die Arbeit mit XML Dokumenten . XSD ist halt auch wieder XML, d.h. aus sich selbst heraus definiert. XML im Notepad halte ich für eine schlechte Variante. Das kann man machen, wenn man auf ner Remotekiste schnell ne Konfiguration anpassen muss, aber nicht um ein komplett neues Dokument zu gestalten.

Deshalb gilt genau mein Post von oben. Eclipse auf, Datei anlegen. Entscheidend ist der folgende Rahmen:

```
<xsd:schema xmlns="http://deine.namespace.url"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://deine.namespace.url"
	elementFormDefault="qualified" attributeFormDefault="unqualified">
  ...
</xsd:schema>
```
Du denkst dir halt einen Targetnamespace aus und los gehts .

REINHAUN!


----------



## will2k (21. August 2008)

so hab das in eclipse soweit gebacken bekommen mit new xml: dann .xsd file habe da ne tolle source/design ansicht super sache gefällt mir   konnte auch xml anhand des schemas generieren, jetzt muss ich mich nur mit xsd befasse. Danke nochmals ich komme nochmals darauf zurück in ein paar wochen  

kann mir eclipse aus der xsd/xml datei auch die Klasse dazu erstellen mit den get/set Methoden und Attributen?

Hat sich erledigt, xjc gibts ja als eclipse plugin


----------

