Jede XPath-Konstruktion ist ein Ausdruck (expression), der entweder aus einer Ansammlung von Knoten des Dokuments, einem boolschen Wert, einer Zahl oder einer Zeichenfolge besteht. Der konkrete Zusammenhang (context), innerhalb dessen solche Ausdrücke ausgewertet werden, setzt sich aus dem jeweiligen Knoten (context node), zwei positiven Ganzzahlen, Variablenbindungen, Funktionen und Namensraumdeklarationen zusammen. Was sich hier so kompliziert anhört, ist sicherlich leichter verständlich, wenn man sich die unten stehenden Beispiele ansieht.
XPath-Ausdrücke bestehen aus drei Bestandteilen: einer Achse, einem Knotentest und optionalen Prädikaten. Achsen in den Beispielausdrücken weiter unten sind unter anderem child, descendant, following-sibling und preceding-sibling. Sie beschreiben die Beziehung, die zwischen dem Ausgangsknoten (der gerade durchlaufen wird) und dem gesuchten Knoten besteht. Zwei Doppelpunkte trennen die Achse vom Knotentest (child::absatz), dem jeweils in eckigen Klammern Prädikate folgen können, die die Suche verfeinern. Die folgende Tabelle fasst die Achsen zusammen. Bis auf attribute und namespace gehört zu allen Achsen das Element als Knotentyp.
Achse | Bedeutung |
---|---|
child | Kindelemente |
parent | Direkter Vorfahr |
descendant | Nachfahren |
ancestor | Vorfahren |
following | Alle nach dem gegenwärtigen im Dokument vorhandenen Knoten |
preceding | Alle vor dem gegenwärtigen im Dokument vorhandenen Knoten |
following-sibling | Geschwister des gegenwärtigen Knotens, die noch folgen |
preceding-sibling | Geschwister, die vor dem gegenwärtigen Knoten angesiedelt sind |
attribute | Die Attribute eines Knotens (nur bei Elementen) |
namespace | Namensraumknoten des gegenwärtigen Knotens (nur bei Elementen) |
self | Der gegenwärtige Knoten |
descendant-or-self | Wie descendant, plus der gegenwärtige Knoten |
ancestor-or-self | Wie ancestor, plus der gegenwärtige Knoten |
Wenn oben von der Reihenfolge der Elemente die Rede ist, dann im Sinne der zu Anfang des Abschnitts 7.1 beschriebenen Struktur. preceding verweist also auf das Elternelement, während preceding-sibling auf das hierarchisch auf derselben Stufe stehende Geschwisterelement verweist, das in der Reihenfolge vor dem gegenwärtigen Knoten steht.
Für die Ausdrücke von Pfaden hat das Konsortium eine Form vorgesehen, die an objektorientierte Progammierung erinnert: Zwei Doppelpunkte trennen die Achsen vom angegebenen Knoten. Wie die weiter unten folgende Tabelle zeigt, existiert aber auch eine verkürzte Form, die der Notation von Pfaden in der Unix-Welt entspricht.
Ausdruck | Zugriff auf |
---|---|
/ | Ursprung des Dokumentbaums, nicht das Top-Level-Element des Dokuments |
child::* | Alle Kindelemente des gegenwärtigen Knotens |
child::absatz | Alle absatz-Kindelemente des gegenwärtigen Knotens |
child::text() | Alle Textknoten des gegenwärtigen Knotens |
child::node() | Alle Kindknoten des gegenwärtigen Knotens |
attribute::name | Das Attribut name |
attribute::* | Alle Attribute des gegenwärtigen Knotens |
descendant::absatz | Alle absatz-Nachfahren des gegenwärtigen Knotens |
/descendant::absatz | Alle absatz-Elemente in diesem Dokument |
/descendant::kapitel/child::absatz | Alle absatz-Kindelemente, deren direkter Vorfahr kapitel ist |
descendant-or-self::absatz | Alle absatz-Nachfahren des gegenwärtigen Knotens oder er selbst (wenn er ein absatz ist) |
ancestor::absatz | Alle absatz-Ahnen des gegenwärtigen Knotens |
ancestor-or-self | Alle absatz-Ahnen des gegenwärtigen Knotens oder er selbst |
self::absatz | Der Knoten selbst, wenn es sich um einen absatz handelt |
child::kapitel/descendant::absatz | Alle absatz-Elemente der kapitel-Kindelemente |
child::*/child::absatz | Alle absatz-Kindelemente der direkten Kindelemente des gegenwärtigen Knotens (Enkel-Absätze) |
child::absatz[position = 1] | Erstes absatz-Kindelement des gegenwärtigen Elements |
child::absatz[position = last()] | Letztes absatz-Kindelement des gegenwärtigen Elements |
child::absatz[position = last() - 1] | Vorletztes absatz-Kindelement des gegenwärtigen Elements |
following-sibling::kapitel[position() = 1] | Das dem gegenwärtigen Knoten nächstliegende Element kapitel (nachfolgend) |
preceding-sibling::kapitel[position() = 1] | Das dem gegenwärtigen Knoten nächstliegende Element kapitel (vorhergehend) |
child::absatz[position() = last()][attribute::typ = "beispiel"] | Das letzte Kindelement absatz, wenn es ein Attribut typ mit dem Wert beispiel besitzt |
Diese Liste ließe sich endlos fortführen, aber
Beispiele werden in diesem und im folgenden Kapitel noch
genügend zu lesen sein. Wichtig ist, und das gilt natürlich
auch für die Kurzformen dieser Ausdrücke, dass es wie in
Dateisystemen sowohl absolute als auch relative Pfade
gibt. Hier wie dortWiederum gilt: zumindest unter
Unix; denn unter Windows muss es ein rückwärts gerichteter
Schrägstrich sein. Vom Macintosh sei hier dezent
geschwiegen. benennt der gemeine Schrägstrich den
Ursprung des Kontextes, in diesem Fall des Dokuments.
Alles, was mit dem Schrägstrich (/) beginnt, ist absolut:
/child::buch/child::kapitel
beinhaltet alle Kindelemente kapitel eines Wurzelelements buch.
child::buch/child::kapitel
könnte hingegen in einem Dokument, in dem mehrere Bücher als Kindelemente versammelt sind (unterhalb eines anderen, hier nicht bezeichneten Wurzelelements), Zugriff auf alle Kapitel als den Kindelementen von buch zugreifen.
Prädikate wie das in den Ausdruckbeispielen erwähnte [position = last()] produzieren aus dem durchsuchten Knotensatz einen neuen, der nur die Knoten enthält, die den Suchbedingungen entsprechen.
Besonders komplizierte Ausdrücke können die Lesbarkeit deutlich herabsetzen. Möglicherweise haben die Autoren von XPath deshalb eine verkürzte Schreibweise für sie vorgesehen. Dabei ist child die automatisch berücksichtigte Achse, solange keine andere explizit verwendet wird. Die größten Erleichterungen: Wie in Dateisystemen kann man mit . den gegenwärtigen Knoten ansprechen und mit .. den Elternknoten. Anstatt child::* reicht ein einfaches *, um die Kindelemente als gesuchten Knotensatz anzugeben. Außerdem kennzeichnet ein @ das Attribut und //absatz bewirkt durch die führenden Schrägstriche, dass alle Elemente absatz im Dokument dem Auswahlkriterium entsprechen — unabhängig von der Strukturtiefe, in der sie vorkommen.
Bei Verwendung von XPath in
XSL-Transformationen ist unbedingt zu beachten,
dass das <-Zeichen auch bei Größenvergleichen
zu maskieren
ist: <. Innerhalb von
Attributwerten gilt das auch für die einfachen und doppelten
Anführungszeichen (" und
'). Die folgenden Beispiele sind deshalb
XPath-Ausdrücke, kein XSLT.
Ausdruck | Zugriff auf |
---|---|
./@thema | Attribut thema des gegenwärtigen Elements |
../@thema | Attribut thema des Elternelements |
absatz[24] | 24. Kindelement absatz |
//absatz[@typ="wichtig"] | Alle absatz-Elemente im Dokument, die ein Attribut typ mit dem Wert wichtig haben |
absatz[@typ="wichtig"][1] | Erstes absatz-Kindelement, das als Attribut typ mit dem Wert wichtig hat |
abschnitt[unterabschnitt] | Alle abschnitt-Elemente, die ihrerseits über unterabschnitt-Elemente verfügen |
abschnitt[ueberschrift and position() < 24] | Die ersten 23 abschnitt-Elemente, die eine ueberschrift haben |