# XML Parsing von Paketen



## mariusmeier (22. Jun 2010)

Hallo zusammen

Meine Ausgangslage ist folgende. Ich erhalte als Client über einen Socket von einem fernen Rechner XML Strings. Diese XML Strings muss ich parsen. Je nach XML String sollen die Attribute in unterschiedliche Modelle abgespeichert werden.
Also Beispielsweise erhalte ich:


[XML]
<dev0>
<get>
<voltage>2.2</voltage>
</get>
</dev0>
[/XML]

Dies soll nun in das Model 1 abgespeichert werden. Falls ich aber beispielsweise folgendes erhalte

[XML]
<control>
<get>
<name>blabla</name>
</get>
</control>
[/XML]

dann soll dies in das Model 2 abgespeichert werden. Insgesamt habe ich etwa 40 unterschiedliche solche XML Statements und 3 Models. Solch ich beispielsweise mit XMLUnit die erhaltenen Strings mit einem File vergleichen, in welchem ich die Antrworten des Servers abspeichere und danach mit if-else je nach dem in das jeweilige Model schreiben oder gibt es da viel elegantere Möglichkeiten?

Für die Hilfe schon mal besten Dank!

Mit freundlichen Grüssen


----------



## Niki (22. Jun 2010)

Anhand welcher Kriterien wird entschieden welches Model für welches XML verwendet wird? (z.B. Name des Root Elements, ein bestimmtes Attribut muss einen bestimmten Wert haben....)


----------



## mariusmeier (22. Jun 2010)

Es wird anhand von Root Element entschieden wohin die Daten kommen. Die Werte zwischen den Tags sind dafür nicht relevant (Dürfen es nicht sein).

MFG


----------



## Noctarius (22. Jun 2010)

Hast du ein XSD? Dann nehm z.B. JAXB


----------



## mariusmeier (22. Jun 2010)

Nein ich müsste für alle 30 XML-Packete (XML-Strings) eigene XSD's schreiben. Du meinst dann, dass ich mit JAXP den XML String in ein Objekt wandle. Wie soll ich das Objekt nachher prüfen, wo die Daten hingehen? Das ist irgendwie mein Hauptproblem. Einfach nur dumm if/else schreiben wirds wohl nicht sein?


----------



## Niki (22. Jun 2010)

Ich würds einfach mit XPath das Root Element abfragen und dann einfach in einer Map nachschauen welches Root Element welches Model hat:

XPath um den Namen des Root Elementes herauszufinden

```
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse("test.xml");

		XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();

		XPathExpression expr = xpath.compile("name(/*)");

		String result = (String)expr.evaluate(doc, XPathConstants.STRING);
```


----------



## Noctarius (22. Jun 2010)

Alternative ist Lycia (siehe Link in der Signatur), da kannst du Parent-Hierarchien und Regex zum Matchen von Tags nutzen :-D


----------



## mariusmeier (23. Jun 2010)

Ok eigentlich ist es kein Problem das root element zu finden und danach zu entscheiden in welches Model die Daten gehen.
Wenn man sich jetzt entschieden hat, in welches Model die Daten gespeichert werden, wie macht man dass dann am besten. Also Beispielsweise habe ich folgende XML Elemente:

<Voltage>
<Current>
<Resistor>
<unit>
<bliablablu>
....

wenn die werte dieser Elemente jetzt nun in das Model 1 geladen werden sollen, muss man da ja trotzdem wieder mit if-else Abfragen, ob man einen neuen Spannungswert (Voltage), Stromwert (Current) etc, hat.... ich finde diesen Approach doch ein wenig aufwendig da ich eben 30 solche Tags habe. Sprich wenn dann später wieder neue dazu kommen muss man den Code wieder anpassen. Gibt es nicht andere Möglichkeiten?

MFG


----------



## Murray (23. Jun 2010)

Wenn die Namen der Tags irgendwelchen Membern des Models entsprechen, oder wenn es in der Model-Klasse zu einem Tag XYZ immer eine Methode setXYZ( String value) gibt, dann könnte man das vielleicht mit Reflection lösen.

Möglicherweise solltest Du Dir aber mal XStream ansehen...


----------



## mariusmeier (23. Jun 2010)

Hallo

Also mit Collections kann man so was bestimmt realisieren, aber ich habe noch keine Erfahrung damit gemacht. Ich weiss auch nicht wie lange ich dafür bräuchte, um was sinnvoll zu programmieren.

Aber die XStream Bibliothek sieht noch interessant aus. Ich bin gerade die Tutorials am lesen und finde, dass die Bibliothek sehr einfach zum bedienen ist (Hoffe dass es beim programmieren wirklich dann auch so einfach ist wie beim lesen ) 
Also beispielsweise erhalte ich folgendes via Netzwerkschnittstelle:

[XML]
<kontrolle>
<erhalte>
<xml_version>2.0</xml_version>
</erhalte>
</kontrolle>
[/XML]

und

[XML]
<kontrolle>
<erhalte>
<hardware_schnittstelle>USB 2.0</hardware_schnittstelle>
<status>0x45</status>
</erhalte>
</kontrolle>
[/XML]

Das sind zwei "unterschiedliche" XML Packete. Wenn ich nun Java Klassen dazu schreibe, danach den XML Code in KLassen wandle... kann ich dann mit "instanceof" überprüfen, ob das entsprechende XML eine Klasse von beispielsweise KontrolleHardware oder KontrolleXMLVersion ist? Weil dann würde ich zu diesen XML Paketen einfach alles Klassen schreiben, die in eine Map abspeichern, und wenn ich solche Pakete via Netzwerk erhalte, kann ich durch die Liste iterieren und erstelle das entsprechende Model dazu und kann es dann auch gleich an den bestimmten Ort speichern. Umgekehrt hätte ich auch den Vorteil, dass wenn ich über die Netzwerkschnittstelle etwas schreiben möchte, dass ich die gleichen Klassen verwenden kann und diese einfach mit Inhalt füllen.....
Oder gibt es irgendwie auch Möglichkeiten, eine Klasse zu schreiben (MainClass), welche alle Attribute enthält also:

- xmlVersion
- HardwareSchnittstelle
- deviceName
- FirmwareVersion 
etc.

wenn ich nun entschieden habe, in welches model das jeweilige Packet speichern möchte, kann ich das XML Paket in ein Objekt wandeln, und dieses einfach der "MainClass" übergeben und die weiss dann wie sie die Werte von den Objekten extrahieren muss ums ins eigene Modell zu legen... ? Wenn ja gibt es dazu irgendwo hinweise im Internet ?

MFG


----------



## Tomate_Salat (23. Jun 2010)

Wieso machst du es nciht einfach so: root-element Filtern, dann weist du ja anscheinend das Model. Dann das ganze mit JAXB als Objekte erstellen und behandeln. Ich bin mir nicht 100% sicher, aber in der XML müssen ja nicht zwangsläufig alle Beans gesetzt werden. DAnn sollte das auch mit den Übergaben kein Thema sein.

Mfg

Tomate_Salat


----------



## evil_one (21. Sep 2010)

Hallo,

ist hier jetzt eine sinnvolle Lösung raus gekommen?

Ich hab eine Vorgegebene XSD. In dieser sind ca. 600 verschiedene XML Dateien modelliert.
Ich muss nun diese Dateien auch parsen und und einzelne Elemente auslesen.

Das Thema Collections wurde angesprochen.
Wie müsste ich da ran gehen?

grüße


----------



## Noctarius (21. Sep 2010)

Dann nehm JAXB. Lass dir passend zum Schema die Java-Files generieren und benutz einen JAXB-Context zum marshallen / unmarshallen.


----------

