Einführung in die XML-Technologien XPath, XSLT und XQuery/XPath

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>XPath2</language>
Autor
* Martin Eisenhammer ([mailto:s3maeise@stud.hs-zigr.de s3maeise@stud.hs-zigr.de])

Dieser Kurs behandelt XPath, eine XML-Technologie zur gezielten Auswahl von Elementen aus XML-Dokumenten und zur Navigation in XML-Dokumenten.
Es werden Grundlagen über XPath geben und Beispiele demonstriert.

==Definition==

XPath (XML Path Language) ist eine XML-Technologie zur Addressierung von Teilen eines XML-Dokuments. Mit Hilfe dieser Sprache kann durch die hierarchische Struktur von XML-Dokumenten navigiert werden. 
XPath ist selbst keine XML-Syntax, sondern ist ähnlich, wie ein Dateipfad, mit denen man in Windows durch die Dateistrukturen navigieren kann, aufgebaut. 

==Datentypen==

XPath hat folgende Datentypen:

'''node set''': ist eine ungeordnete Knotenmenge, die auch leer sein kann.

'''String''' ist eine Zeichenfolge, die auch leer sein kann.

'''Number''' ist eine Fließkommazahl.

Mit '''boolean''' wird ein Wahrheitswert bezeichnet, der true oder false annehmen kann.

==Auswertung eines XPath-Ausdrucks und Suchprinzip==

Ein XPath-Ausdruck wird von einem Prozessor ausgewertet. Die Dokumentstruktur des XML-Dokuments kann man als Baum veranschaulichen. Es werden in der Baumstruktur die Knoten nach dem Prinzip der Tiefensuche durchlaufen. Begonnen wird am aktuellen Startknoten. Als nächstes werden die sog. Kindknoten durchlaufen und die Kindeskinder des aktuellen Startknoten durchlaufen. Es wird rekursiv vorgegangen, d.h. die Prozedur der Tiefensuche ruft sich selbst auf. Das bedeutet, dass ab dem ersten Knoten eine Tiefensuche satt findet und dann ab dem nächsten Knoten (dem Kindknoten des ersten Knoten) wieder eine Tiefensuche und beim Kindeskindknoten ebenfalls. Das wird solange fortgesetzt, bis die gesuchte Stelle gefunden wurde. Wenn an der tiefsten Stelle das Ergebnis noch nicht gefunden wurde, so wird am zweiten Kindknoten des zuletzt besuchten Knotens fortgesetzt. Ist das Ziel nicht in dem entsprechendem Teilbaum, so wird im Baum weiter zurückgegangen und dort ab den weiteren Knoten weiter gesucht.

[[Datei:Tiefensuche.jpg]]

Das Erzeugen eines XML-Dokuments aus einem Baum wird Serialisierung genannt.
Deserialisierung nennt man die Erzeugung eines Baums aus einem XML-Dokument.

In XML-Dokumenten müssen die Groß- und Kleinschreibung in den Tags, sowie in den Elementen, beachtet werden, damit die XPath-Ausdrücke korrekt laufen.
==Überblick über die Knotentypen ==

Bei der Modellierung eines XML-Dokuments als Baum gibt es sieben Knotentypen:

* Wurzelknoten
* Elementknoten
* Textknoten
* Attributknoten
* Namensraumknoten
* Processing-Instruction-Knoten
* Kommentarknoten

Der Wurzelknoten enthält das gesamte Dokument. Die Dokumenttyp-Deklaration ist
kein Kind des Wurzelknotens.
Der Elementknoten ist der Knoten für jedes Element im Dokument.
Der Attributknoten ist der Knoten für jedes Attribut, welches einem Element
zugeordnet ist.
Der Textknoten enthält die Zeichendaten.
Der Verarbeitungsanweisungsknoten (Processing Instruction Knoten) ist ein
Knoten für eine Verarbeitungsanweisung.
Der Namensraumknoten ist einem Elementknoten zugeordneter Elternknoten.
Der Kommentarknoten ist ein Knoten für einen Kommentar.

==Adressierung mit Hilfe von Lokalisierungspfaden==
===Absolute und relative Pfade===

Mit Hilfe von Lokalisierungspfaden kann man gezielt Teile eines XML-Dokuments
auswählen. Die Ausdrücke ähneln sich der Syntax von Dateipfaden, so wie man sie
von Windows zur Navigation durch die Dateistruktur her kennt. Man kann zwei
Schreibweisen unterscheiden: eine ausführliche Schreibweise und eine Kurzform.

Zur Veranschaulichung wird als Beispiel einen Auszug aus einer Filmsammlung genommen, die als XML-Datei realisiert wurde.


<code id="4f041740674fb">

<filmliste>
       <film id="1">
           <titel>Die Rueckkehr der Jedi-Ritter</titel>
           <genre>Science-Fiction</genre>
           <oscars>1</oscars>
           <regie>
                  <regisseur>Richard</regisseur>
           </regie>
           <jahr>1983</jahr>
       </film>
       <film id="2">
           <titel>Sin City</titel>
           <genre>Thriller</genre>
           <oscars>0</oscars>
           <regie>
                  <regisseur>Frank Miller</regisseur>
                  <regisseur>Robert Rodriguez</regisseur>
                  <regisseur>Quentin Tarantino</regisseur>
    
          </regie>
          <jahr>2005</jahr>   
	</film>
        <film id="3">
           <titel>Forrest Gump</titel>
           <genre>Drama</genre>
           <oscars>6</oscars>
           <regie>
                  <regisseur>Robert Zemeckis</regisseur>
           </regie>
           <jahr>1994</jahr>
	</film>
        <film id="4">
           <titel>The Dark Knight</titel>
           <genre>Action</genre>
           <oscars>2</oscars>
           <regie>
                  <regisseur>Christopher Nolan</regisseur>
           </regie>
           <jahr>2008</jahr>
        </film>
        <film id="5">
           <titel>Avatar</titel>
           <genre>Science-Fiction</genre>
           <oscars>3</oscars>
           <regie>
                  <regisseur>James Cameron</regisseur>
           </regie>
           <jahr>2009</jahr>
          </film>
</filmliste>
</code>

Anhand dieses Beispiels wird der Zugriff auf Knoten mit Hilfe von XPath-Ausdrücken demonstriert.

Um beispielsweise auf dem Knoten film zuzugreifen, wird folgender Ausdruck in ausführlicher Schreibweise angegeben:

<run id="4f0418998b4d6">

/child::filmliste/child::film

</run>

Der Ausdruck beginnt mit einem Schrägstrich und wird auch '''absoluter Pfad''' genannt.
Absolute Pfade gehen vom '''Wurzelknoten''' aus. Als Wurzelknoten wird das erste Tag
bezeichnet, mit dem das XML-Dokument beginnt.
Nach dem Schrägstrich folgt die Angabe der Lokalisierungsstufe. Ein
Lokalisierungspfad ist aus mehreren Lokalisierungsstufen zusammengesetzt, die
durch Schrägstriche getrennt sind. Eine Lokalisierungsstufe besteht aus einer '''Achse'''
und einem '''Knotentest'''. Auf Achsen und Knotentest wird später eingegangen. Im obigen Beispiel lautet die Achse "child" und der Knotentest "filmliste" in der ersten Lokalisierungsstufe. Hinter dem Knotentest können noch sogenannte
Prädikate folgen, die an späterer Stelle noch behandelt werden.

Die allgemeine Syntax einer ausführlichen Pfadangabe lautet:


 Achsenbezeichner::Knotentest[Prädikat1][Prädikat2]

Außer der ausführlichen Angabe existiert auch noch die verkürzte Schreibweise, die die Achsenbezeichnung nicht mit angibt:


 /Knotentest1/Knotentest2...

Bezogen auf das Beispiel (siehe oben) lautet die Kurzform:

<run id="4f041ccc59006">
/filmliste/film
</run>

Außer absoluten Pfaden kann man auch '''relative Pfade''' angeben. Ein relativer Pfad
geht von einem '''Kontextknoten''' aus. Das ist jeweils der Knoten, der durch die
vorausgehenden Schritte erreicht worden ist.

Beispiel für einen relativen Pfad:

<run id="4f041d84bb349">
film/titel
</run>

Hierbei ist der Kontextknoten filmliste.

Man kann auch eine verkürzte Form formulieren ohne immer die vollständige Hierarchie angeben zu müssen. Das ist einfacher und spart eine Menge Tipparbeit. 

Beispiel:

<code id="4f041f4d31eca">
//titel
</code>

Diese Kurzform kann auch innerhalb eines Ausdrucks stehen:

<code id="4f041f4d31f6d">
/filmliste//titel
</code>

Hier muss der Prozessor mehr Knoten des Dokuments prüfen.

Mit Hilfe von Wildcards können alle Kinder eines Elements angegeben werden. Hierbei wird ein Stern angegeben.

Beispiel:

<run id="4f041f4d32020">
/filmliste/film/*
</run>

Dieses Beispiel liefert alle Kinder des Elements Film. Es listet alle Informationen zu einem Film auf.

===Auswählen von Attributen===

Um auf Attribute zugreifen zu können, wählt man sie mit Hilfe von Attributknoten aus.
Die Attributknoten werden anders addressiert, als die Elementknoten. Sie beginnen
mit einen @-Zeichen und danach folgt der Name des Attributs.

Allgemeine Syntax:

<code id="4f042620264af">
@attributname
</code>

Im folgendem Beispiel wird auf das Attribut "id" zugegriffen:

<run id="4f0426202658f">
filmliste/film/@id
</run>

Man kann auch mit Hilfe von Wildcards auf Attribute eines Elements zugreifen.

Beispiel:

<run id="4f04262026620">
/filmliste/film/@*
</run>

Es können auch alle Elementknoten ausgewählt werden, bei denen das angebene Attribut einen bestimmten Wert hat.

Das Beispiel wählt genau den Film aus, dessen ID gleich 3 ist.
<run id="4f042620266b5">
/filmliste/film[@id="3"]
</run>

===Übungsaufgabe===

Selektieren Sie

1. alle Ressigeure

<run id="4f0ada1463be4">

</run>

<popup name="Lösung">
<run id="4f0ada1463cb3">
/child:filmliste/child:film/child:regie/*
</run>
</popup>

2. alle Filmtitel

<run id="4f0ada1463d69">

</run>

<popup name="Lösung">
<run id="4f0ada1463e2e">
/child:filmliste/child:film/child:titel
</run>
</popup>

==Achsen==

Wie schon bereits erwähnt setzt sich der Lokalisierungspfad aus mindestens 2 Lokalisierungsstufen zusammen. Die erste Lokalisierungsstufe ist die Bezeichnung der Achse. Im Folgendem werden die möglichen Achsenbezeichnungen vorgestellt. Die Begriffe stammen aus der Verwandschaftsterminologie.

Die Knoten haben, ähnlich wie in einem Stammbaum, Beziehungen untereinander. Mit Hilfe von Achsen kann angegeben werden, welche Beziehungen von einem Kontextknoten angesteuert werden sollen, zum Beispiel die Eltern oder die Nachkommen des Kontextknotens. Die Achsen liefern immer eine bestimmte Knotenmenge.

Es gibt folgende Achsenbezeichnungen:

* self
* child
* parent
* descendant
* descendant-or-self
* anchestor
* anchestor-or-self
* following
* following-sibling
* preceding
* preceding-sibling
* attribute
* namespace


'''self''': Die Achse self liefert den Kontextknoten selber.

'''child''': Die child-Achse liefert genau die Kinder des Kontextknotens.

'''parent''': Die Achse parent lefert den übergeordneten Elternknoten des Kontextknotens, falls es einen Elternknoten gibt.

'''descendant''': Die Achse descendant liefert die Nachkommen des Kontextknotens.

'''descendant-or-self''': Die Achse descendant-or-self liefert die Nachfahren und den Kontextknoten
selbst.

'''anchestor''': Die Achse anchestor des Kontextknotens liefert die Vorfahren, also die Eltern und
deren Vorfahren des Kontextknotens. Des Weiteren enthält sie außerdem den
Wurzelknoten, aber nur, wenn der Wurzelknoten nicht der Kontextknoten selber ist.

'''anchestor-or-self''': Die Achse anchestor-or-self liefert den Kontextknoten einschließlich dessen
Vorfahren.

'''following''': Die following-Achse liefert die Nachfolgerknoten des Kontextknotens. Es werden
außerdem noch die Kinderknoten der Nachfolgerknoten geliefert, falls es welche gibt.

'''following-sibling''': Die Achse following-sibling liefert die nachfolgenden Geschwisterknoten des
Kontextknotens.

'''preceding''': Die Achse preceding liefert die vorhergehenden Geschwisterknoten des
Kontextknotens einschließlich ihre Kinder.

'''preceding-sibling''': Die Achse preceding-sibling liefert die Geschwisterknoten des Kontextknotens
ohne deren Kinderknoten.

'''attribute''': Die Achse attribute liefert den Attributknoten des Kontextknotens.

'''namespace''': Die Achse namespace liefert den Namensraumknoten des Kontextknotens.

===Übungsaufgaben===

1. Wählen Sie alle Nachfolgerknoten des Knotens Regie aus!

<run id="4f0ada1463ef6">

</run>

<popup name="Lösung">
<run id="4f0ada1463ff1">
/child:filmliste/child:film/descendant:regie
</run>
</popup>

2. Wählen Sie die Vorgängerknoten des Knotens genre aus!

<run id="4f0ada14640ea">

</run>

<popup name="Lösung">
<run id="4f0ada14641ea">
/child:filmliste/child:film/preceding:genre
</run>
</popup>



==Knotentests==

Ein Knotentest gehört zu einem Lokalisierungspfad. Er ist die Angabe hinter der Achsenbezeichnung. Damit kann man die durch die Achse ausgewählte Knotenmenge noch weiter filtern. Als Kriterium wird ein Knotenname oder Knotentyp angegeben.

Es gibt folgende Arten von Knotentests , bei denen das Kriterium der Knotentyp ist:

* text()
* comment()
* processing-instruction()
* node()

Der Knotentest text() wählt alle Textknoten aus. Mit comment() werden die
Kommentarknoten ausgewählt. Verarbeitungsanweisungsknoten werden mit
processing-instruction() ausgewählt. Alle Knoten können mit node()
ausgewählt werden.

Auch ein Knotenname kann als Kriterium angegeben werden.

Beispiel:

<run id="4f0ab75ea0efd">
following::titel
</run>

Mit der Achse following werden die Knoten ausgewählt, die dem Kontextknoten
folgen. Aus diesen Knoten wird dann der Knoten mit dem Namen Titel
herausgefiltert.
Der Knotentyp des benannten Knotens muss mit dem Knotentyp der Achse
übereinstimmen.

Soll beispielsweise auf ein Attribut zugegriffen werden, wird beispielsweise folgendes
angegeben:

<run id="4f0ab75ea104f">
attribute::id
</run>

Um zum Beispiel die Textknoten auszuwählen, die Eltern des Kontextknotens sind,
kann man den Ausdruck parent::text() angeben.

===Übungsaufgabe===

Geben Sie alle Filmtitel aus!

<run id="4f0af6e2a9a5d">

</run>

<popup name="Lösung">
<run id="4f0af6e2a9b77">
/filmliste/film/text()
</run>
</popup>


==Prädikate==

Mit Hilfe von Prädikaten kann man die Filterung von Knotenmengen noch weiter
verfeinern. Das Prädikat ist eine Angabe einer Bedingung, die erfüllt sein muss,
damit eine entsprechende Knotenmenge auswählt werden kann. Ein
Prädikatausdruck wird in eckigen Klammern angegeben. Es handelt sich um einen
logischen Ausdruck.
Prädikate unterstützen folgende Operatoren: <,>,<=,>=,=,!=.
Die Operatoren < und > dürfen in dieser Form in einem XPath-Ausdruck nicht erscheinen, da sonst der Prozessor sie als Teil eines Tags versteht. Dafür werden sogenannte '''Entitätsreferenzen''' eingesetzteingesetzt, die die
Auswertung eines XML-Dokuments unterdrücken. Eine Entitätsreferenz beginnt mit
einem kauffmännischen Und-Zeichen & und es folgt eine Art Abkürzung für das
entsprechende Zeichen. Für > lautet die Entitätsreferenz &gt und für < &lt.

Es sind auch mathematische Operationen, wie +,-,*,div und mod möglich.
Die Resultate werden hierbei von einem String-Wert in einen Zahlwert umgewandelt.

Beispiel:

<run id="4f0ac81bdfa90">
/child::filmliste/child::film[attribute::id="3"]
</run>

===Übungsaufgabe===

Geben Sie den Film mit der ID 5 aus!

<run id="4f0ac81bdfb5e">

</run>

<popup name="Lösung">
<run id="4f0ac81bdfc03">
/child::filmliste/child::film[attribute::id="5"]
</run>
</popup>


==Literatur==

*  Helmut Vonhoegen: ''Einstieg in XML- Grundlagen, Praxis, Referenz'' - Galileo Computing, 619 S., 6.Auflage 2011
*  Götz Bürkle, Thomas J Sebestyen: X-Path Syntax: http://de.selfhtml.org/xml/darstellung/xpathsyntax.htm (10.12.2011)
*  Götz Bürkle, Thomas J Sebestyen: Die Aufgaben von XPath http://de.selfhtml.org/xml/darstellung/xpathsyntax.htm#achsen (17.12.2011)
*  Seite des W3C: http://www.w3.org/TR/xpath/ (09.01.2012)