Im Folgenden wird beschrieben, wie man mithilfe der Open-Source-Bibliothek Simple XML einen Objektbaum in eine XML-Zeichenkette umwandelt und umgekehrt eine XML-Zeichenkette in einen Objektbaum.
Die beschriebene Vorgehensweise deckt nur einen sehr kleinen Funktionsumfang von Simple XML ab. Es wird dringend empfohlen, das sehr verständliche Tutorial durchzuarbeiten.
Auf der Downloadseite des Projekts kann ein Archiv heruntergeladen werden, das die Simple XML-Bibliothek, die Quelltexte und die Dokumentation enthält. In der Entwicklungsumgebung benötigen wir nur die Bibliothek selbst, also die Datei simple-xmml-2.7.1.jar
. Sie muss in den Ordner libs
des Projekts kopiert werden. („Reinziehen“ vom Dateiexplorer in den Package Explorer von Eclipse oder Kopieren im Dateisystem und anschließend „F5“ aufs Projekt im Package-Explorer).
Damit Objekte mit Simple XML serialisiert und deserialisiert werden können, müssen sie mit Annotations versehen werden, die angeben, welche Attribute wie umgewandelt werden sollen. Hier ein Beispiel:
@Root public class Buch { @Element private String titel; @Element private String autor; @Element private int seitenzahl; public Buch() { }; public Buch(String titel, String autor, int seitenzahl) { super(); this.titel = titel; this.autor = autor; this.seitenzahl = seitenzahl; } public String getTitel() { return titel; } public void setTitel(String titel) { this.titel = titel; } public String getAutor() { return autor; } public void setAutor(String autor) { this.autor = autor; } public int getSeitenzahl() { return seitenzahl; } public void setSeitenzahl(int seitenzahl) { this.seitenzahl = seitenzahl; } @Override public String toString() { return "[" + titel + "; " + autor + "; " + seitenzahl + "]"; } }
Die Annotation @Root
zeigt an, dass es sich um eine serialisierbare Klasse handelt. @Element
bedeutet, dass das Attribut des Klasse als XML-Unterelement serialisiert wird (im Unterschied zu @Attribute
). Enthält ein Objekt eine Liste anderer Objekte, so gibt es dazu die Annotation @ElementList
. So besteht eine Bibliothek beispielsweise aus mehreren Büchern:
@Root public class Bibliothek { @Attribute private String name; @ElementList private List<Buch> buecher = new ArrayList<Buch>(); public Bibliothek(){}; ...
Ein beispielhafter Objektbaum sieht so aus:
<bibliothek name="CSG-Schülerbücherei"> <buecher class="java.util.ArrayList"> <buch> <autor>Michael Ende</autor> <titel>Jim Knopf und Lukas der Lokomotivführer</titel> <seitenzahl>327</seitenzahl> </buch> <buch> <autor>Astrid Lindgren</autor> <titel>Pippi Langstrumpf</titel> <seitenzahl>451</seitenzahl> </buch> <buch> <autor>Benno Beispiel</autor> <titel>Mathe macht Spass</titel> <seitenzahl>1265</seitenzahl> </buch> </buecher> <verlage class="java.util.ArrayList"> <verlag> <name>Oettinger</name> <ort>Hamburg</ort> </verlag> <verlag> <name>Klett</name> <ort>München</ort> </verlag> </verlage> </bibliothek>
Hier der Code zum Serialisieren:
Bibliothek bib = BeispielFactory.getBeispielBibliothek(); Style style = new HyphenStyle(); Format format = new Format(style); Serializer serializer = new Persister(format); StringWriter writer = new StringWriter(); try { serializer.write(bib, writer); Log.i("XML", writer.getBuffer().toString()); // Statt Ausgabe ins Log kann der String bspw. auch per HttpRequest an einen Server gesendet werden ... } catch (Exception ex){ ausgabe.setText(ex.toString()); }
Hier der Code zum Deserialisieren:
String xml = ... // Von irgendwoher kommt der XML-Text... Serializer serializer = new Persister(); try { Bibliothek bib = serializer.read(Bibliothek.class, xml); // bib ist der Knoten des Objektbaums, mit dem jetzt weitergearbeitet werden kann! } catch (Exception ex){ ausgabe.setText(ex.toString()); }
Das obige Vorgehen funktioniert natürlich nur bei baumförmigen Objektstrukturen. Sobald der Objektgraph Zyklen besitzt, ist eine direkte Umsetzung in einen XML-Baum nicht mehr möglich, weil ein Objekt in mehreren anderen Objekten enthalten sein kann. Hier hält Simple XML eine Lösung bereit: Es versieht alle XML-Objekte mit einem zusätzliche Attribut „id“, das eine fortlaufende Nummerierung enthält. Ist ein Objekt in zwei anderen Objekte enthalten, so wird es nur als Unterelement des ersten serialisiert. Beim zweiten fügt Simple XML nur eine Referenz auf die id des Objekts ein. Vor dem Serialisieren muss dem Serializer nur eine CycleStrategy
mitgegeben werden:
Strategy strategy = new CycleStrategy("id", "ref"); Serializer serializer = new Persister(strategy, format); ...
Ebenso vor dem Deserialisieren:
Strategy strategy = new CycleStrategy("id", "ref"); Serializer serializer = new Persister(strategy); ...
Fügt man dem obigen Objektmodell noch eine Klasse Verlag
hinzu und referenziert man die Verlage sowohl als Liste beim Bibliothek
-Objekt als auch als Attribut jedes einzelnen Buchs, so erhält man etwa folgendes:
public class Verlag { @Element private String name; @Element private String ort; ... } @Root public class Bibliothek { @Attribute private String name; @ElementList private List<Verlag> verlage = new ArrayList<Verlag>(); @ElementList private List<Buch> buecher = new ArrayList<Buch>(); ... } @Root public class Buch { @Element private String titel; @Element private Verlag verlag; ... }
Ein Beispiel für eine als XML serialisierte Bibliothek sieht dann so aus:
<bibliothek id="0" name="CSG-Schülerbücherei"> <buecher class="java.util.ArrayList" id="1"> <buch id="2"> <autor id="3">Michael Ende</autor> <verlag id="4"> <name id="5">Oettinger</name> <ort id="6">Hamburg</ort> </verlag> <titel id="7">Jim Knopf und Lukas der Lokomotivführer</titel> <seitenzahl id="8">327</seitenzahl> </buch> <buch id="9"> <autor id="10">Astrid Lindgren</autor> <verlag ref="4"/> <titel id="11">Pippi Langstrumpf</titel> <seitenzahl id="12">451</seitenzahl> </buch> <buch id="13"> <autor id="14">Benno Beispiel</autor> <verlag id="15"> <name id="16">Klett</name> <ort id="17">München</ort> </verlag> <titel id="18">Mathe macht Spass</titel> <seitenzahl id="19">1265</seitenzahl> </buch> </buecher> <verlage class="java.util.ArrayList" id="20"> <verlag ref="4"/> <verlag ref="15"/> </verlage> </bibliothek>
Die Bibliothek Simple XML bietet noch weit mehr Möglichkeiten als oben gezeigt, bspw.: