# Zugriff auf XML per XPath



## DarthShader (15. April 2008)

Hallo,

ich würde gerne meine XML Daten über XPath ansprechen. Ich habe folgende Beispiel-XML:


```
<?xml version="1.0" encoding="UTF-8"?>
<LocalConfiguration>
    <gui>
        <splash show="true" />
    </gui>
</LocalConfiguration>
```

Ich spreche die XML Daten folgendermaßen an:


```
ByteArrayInputStream in = new ByteArrayInputStream( xml.getBytes() );  
Document document = builder.parse( in );
		
System.out.println( document.getFirstChild().getNodeName() );
```

Als Ausgabe erhalte ich "LocalConfiguration" - funktioniert also 

Nun per XPath:


```
XPath x = XPathFactory.newInstance().newXPath();
String res = x.evaluate( "/LocalConfiguration/gui", document );

System.out.println( res );
```

Hier gibt es leider keine Ausgabe, der String "res" ist nicht null, aber leer.

Nun die einfache Frage: was mache ich hier falsch? Ist vielleicht meine XPath Notation fehlerhaft?


Vielen Dank für Eure Hilfe!


----------



## Oliver Gierke (15. April 2008)

Tut "//LocalConfiguration/gui"? Mit der absoluten Adressierung hatte ich auch schon so meine Problemchen.

Gruß
Ollie


----------



## DarthShader (15. April 2008)

Hallo,

danke für Deine Antwort. Leider funktionioert "//LocalConfiguration/gui" auch nicht, der zurückgegebene String bleibt leer.

Ich weiß jetzt gar nicht, wie ich weiter investigieren soll  Ich meine, es wird ja auch keine Exception geworfen, weil der XPath Ausdruck falsch sein könnte oder Ähnliches. Die alternative Notation mit z.B. "/child::LocalConfiguration" klappt auch nicht.

Ich habe das Gefühl, da ist irgendwas grundlegendes falsch. Ist es überhaupt richtig, dass ich das "document" als Parameter übergebe (es handelt sich um ein "org.w3c.dom.Document")?


----------



## Oliver Gierke (15. April 2008)

Ähm, moment... ich glaube das rootelement brauchst du nicht mit angeben, da ein XML Dokument nur ein Rootelement haben darf. D.h. "/gui" bzw. "//gui" sollte tun.

Gruß
Ollie


----------



## DarthShader (15. April 2008)

Oliver Gierke hat gesagt.:


> Ähm, moment... ich glaube das rootelement brauchst du nicht mit angeben, da ein XML Dokument nur ein Rootelement haben darf. D.h. "/gui" bzw. "//gui" sollte tun.


oh

leider kein Glück :-/ Das scheint es auch nicht zu sein. Ich glaube immernoch, das hier irgendwas grundlegendes nicht simmt. Ich überlege, einfach JDOM einzusetzen, da ist das handling von XPath etwas einfacher. Aber dennoch würde mich mal interessieren, was hier schief läuft


----------



## Adrian_Broher (15. April 2008)

Lass zuerst einmal den selektierten Node als Node Objekt zurückgeben.

Was du mit dem 


```
/LocalConfiguration/gui
```

XPath selektiert hast nämlich folgender Knoten:


```
<gui>
    <splash show="true" />
</gui>
```

Und ich kann mir gut vorstellen, das dieser Knoten in der String Repräsentation als leerer String zurückgegeben wird weil er weder PCDATA noch CDATA enthält.

Wenn du den true Wert aus dem splash Node extrahieren möchtest sollte der XPath so aussehen:


```
/LocalConfiguration/gui/splash/@show/text()
```

Damit extrahierst du den string "true" aus dem splash Node. Diesen müsstest du dann noch mit einem java.lang.Boolean wrappen.


```
String xmlShowSplash = x.evaluate("/LocalConfiguration/gui/splash/@show/text()", document);
boolean showSplash = Boolean.valueOf(xmlShowSplash).booleanValue();
```

alternativ sollte es auch funktionieren direkt den zurückgegebenen String auf ein Boolean Objekt mappen zu lassen.


```
Boolean xmlShowSplash = (Boolean)x.evaluate("/LocalConfiguration/gui/splash/@show/text()", document, XPathConstants.BOOLEAN);
boolean showSplash = xmlShowSplash.booleanValue();
```


----------



## DarthShader (15. April 2008)

Adrian_Broher hat gesagt.:


> Und ich kann mir gut vorstellen, das dieser Knoten in der String Repräsentation als leerer String zurückgegeben wird weil er weder PCDATA noch CDATA enthält.



Ah, so habe ich das noch gar nicht gesehen, das ist natürlich gut möglich.

Mein Code sieht nun so aus:


```
ByteArrayInputStream in = new ByteArrayInputStream( xml.getBytes() );  
Document document = builder.parse( in );
		
System.out.println( document.getFirstChild().getNodeName() );
		
XPath x = XPathFactory.newInstance().newXPath();
String res = x.evaluate( "/LocalConfiguration/gui/splash/@show/text()", document );

System.out.println( "res: '" + res + "'" );
```

Wobei der String "xml" so aussieht:


```
<?xml version="1.0" encoding="UTF-8"?>
<LocalConfiguration>
	
	<gui>
		<splash show="true" duration="3000" />
	</gui>

</LocalConfiguration>
```

Die Ausgabe des Programmes ist


```
LocalConfiguration
res: ''
```

Der String ist also immernoch leer. Ich finde es irgendwie sehr unschön, dass man so wenig Rückmeldungen bekommt. Diese XPath Implementierung kommt mir sehr tollerant vor, was den Ausdruck angeht. Allerdings sind die Ausdrücke sicher recht komplex, was wohl viele Möglichkeiten zulässt.

Wie dem auch sei, ich erreiche immer noch nicht den Wert des Attributs "show" vom "splash" Element. Noch irgendeine Idee?

Vielen Dank!


----------



## Adrian_Broher (15. April 2008)

DarthShader hat gesagt.:


> Wie dem auch sei, ich erreiche immer noch nicht den Wert des Attributs "show" vom "splash" Element. Noch irgendeine Idee?



Jop, entweder nimmst du einen XPath editor zur hand und entwickelst den entsprechenden XPath oder du lässt einzelne Knoten statt einem String zurückgeben und schreibst den XPath Stück für Stück selbst zusammen.

Wobei ein XPath Editor sicher die sinnvollere Alternative ist. Bei Sourceforge lässt sich da sicher was passendes finden.


----------



## DarthShader (15. April 2008)

Ich glaube langsam, dass man mit XPath gar nicht direkt den Wert eines Attributes auslesen kann (sicher liege ich da falsch  ).

Aber so funktioniert es:


```
NodeImpl res = (NodeImpl)x.evaluate( "/LocalConfiguration/gui/splash/@show", document, XPathConstants.NODE );
		
System.out.println( res.getTextContent() );
```

Ich hole also erst den Knoten, wobei hier das Attribut "show" wohl auch als Knoten gehandhabt wird, und dann den Text des Knotens, was in diesem Fall der Wert des Attributs ist.


----------



## Oliver Gierke (15. April 2008)

Hm, okay... das bringt für mein XPathproblemkind hier auch schonmal etwas weiter. Und "/text()" hinter @show tut dann nicht?

Gruß
Ollie


----------



## DarthShader (15. April 2008)

Oliver Gierke hat gesagt.:


> Hm, okay... das bringt für mein XPathproblemkind hier auch schonmal etwas weiter. Und "/text()" hinter @show tut dann nicht?



XPathproblemkind? 

Nein, ein "/text()" hinter "@show" bringt leider nichts.


----------

