Homepage-Webhilfe Event-Banner

Grundlagen

Bei XPath (XML Path Language, zu Deutsch XML Pfadsprache) handelt es sich um eine Abfragesprache, die dazu verwendet wird, Knoten innerhalb eines XML-Dokuments zu adressieren. Verwendung findet XPath dabei vor allem in der Transformationssprache XSLT, kann jedoch auch in anderen Programmiersprachen (z. B. JavaScript oder C#) für die Adressierung von Bestandteilen des XML-Baums verwendet werden.

Die mit XPath definierten Ausdrücke werden nicht in extra Dateien abgespeichert, sondern in anderen Dokumenten bzw. in Skripten eingebettet. Die Sprache XPath wurde vom W3C entworfen und dient zudem als Grundlage für weitere Sprachen.

In diesem Thema werden wir verschiedene Fachbegriffe (wie z. B. Knoten und Achse) sowie die Schlüsselwörter und den Syntax von XPath erläutern.


In Bezug auf XML und XPath werden Sie oft den Begriff Knoten (engl. node) hören. Doch was genau ist ein Knoten? Unter einem Knoten versteht man einen Teil eines XML-Dokuments oder auch das ganze XML-Dokument. Dabei stehen Knoten in enger Verbindung mit der Baumstruktur von XML. Bei Knoten wird zwischen ein paar unterschiedlichen Typen unterschieden:

  • Wurzelknoten (engl. root node, auch Dokumentknoten genannt): Dabei handelt es sich um den abstrakten Ursprung des XML-Dokuments. Der Wurzelknoten repräsentiert das ganze Dokument und darf nicht mit dem Wurzelelement verwechselt werden.
  • Elementknoten (engl. element node): ein beliebiges Element.
  • Textknoten (engl. text node): ein Text, welcher einem Element untergeordnet ist.
  • Attributknoten (engl. attribute node): ein beliebiges Attribut eines Elements.
  • Kommentarknoten (engl. comment node): ein beliebiger Kommentar.
  • Namensraumknoten (engl. namespace node): eine beliebige Namensraumangabe eines Elements oder Attributs.
  • Verarbeitungsanweisungsknoten (engl. processing instruction node): ein XML-Verarbeitungshinweis (die XML-Deklaration zählt dabei nicht dazu).

Für die Pfade, welche nachher genutzt werden, um im Dokument zu navigieren bzw. Knoten zu adressieren, werden sogenannte Achsen (engl. axis) benötigt. Eine Achse spezifiziert dabei die Beziehung des gewünschten Knotens (also dem Knoten, welchen Sie mittels XPath adressieren möchten) zum aktuellen Knoten (auch als Kontextknoten bezeichnet). Einige Achsen adressieren nur einzelne Knoten, wohingegen mit anderen Achsen auch mehrere Knoten adressiert werden können. Die folgende Tabelle zeigt die verschiedenen Achsen (Name und Kurz-Notation) sowie die Knoten, die damit selektiert werden:

Name Kurz-Notation selektierte Knoten
/ / Wurzelknoten
child (nicht notwendig) direkt untergeordnete Knoten (Kindknoten)
self . aktuelle Knoten (Kontextknoten)
parent .. direkt übergeordneter Knoten (Elternknoten)
descendant .// alle untergeordnete Knoten
descendant-or-self alle untergeordnete Knoten sowie der aktuelle Knoten
ancestor alle übergeordnete Knoten
ancestor-or-self alle übergeordneten Knoten sowie der aktuelle Knoten
following alle nachfolgende Knoten (ohne Kindknoten)
following-sibling alle nachfolgende Knoten (ohne Kindknoten), die den gleichen Elternknoten haben
preceding alle vorangehende Knoten (ohne alle Elternknoten)
preceding-sibling alle vorangehende Knoten (ohne alle Elternknoten), die den gleichen Elternknoten haben
attribute @ Attributknoten
namespace Namensraumknoten

Ein Prädikat (engl. predicate) wird in XPath dazu verwendet, mit Hilfe von Ausdrücken (i. d. R. handelt es sich dabei um Bedingungen) die Selektierung von Knoten weiter einzuschränken. Ein typisches Beispiel: Sie möchten alle Elemente mit dem Namen x selektieren, aber nur, sofern diese über das Attribut y verfügen. Die Notation von Prädikaten erfolgt in den eckigen Klammern [ und ].

Innerhalb der Prädikate können Sie verschiedene Operatoren verwenden. Dazu zählen die mathematischen Operatoren + (Addition), - (Subtraktion), * (Multiplikation), div (Division) und mod (Modulo, Divisionsrest), aber auch die logischen Operatoren and (und) und or (oder) sowie die Vergleichsoperatoren = (gleich), != (ungleich), < (kleiner als), <= (kleiner-gleich), > (größer als) und >= (größer-gleich).

Eine weitere beliebte Verwendung von Prädikaten ist die Adressierung eines einzelnen Knotens mit Hilfe des Indexes. Bei einem Index handelt es sich um eine laufende Nummer. Bei der Notation wird der Index direkt als Zahl innerhalb der eckigen Klammern angegeben: 1 = erster Knoten, 2 = zweiter Knoten, etc..

Oft werden Prädikate aber auch in Verbindung mit XPath-Funktionen (dazu mehr im nächsten Thema) verwendet. Dadurch ist z. B. die Adressierung des letzten Knotens, das Modifizieren von Zahlen und Zeichenketten und vieles mehr möglich.


Ein XPath-Ausdruck (also der Pfad, welcher zur Adressierung von Knoten verwendet wird) setzt sich aus einem oder mehreren Lokalisierungsschritt(en) zusammen. Ein Lokalisierungsschritt besteht wiederum aus weiteren 3 Teilen: der Achse, einem Knotentest und bei Bedarf aus einem oder mehreren Prädikat(en). Wird bei der Angabe der Achse der Achsenname verwendet, so muss der Achsenname vom Knotentest mit Hilfe der Zeichen :: (Doppel-Doppelpunkt) getrennt werden. Wird die verkürzte Notation verwendet, so fällt der Doppel-Doppelpunkt weg. Der Knotentest ist letztendlich nichts anderes als der Name des Knotens. Alternativ kann hier auch mit dem sogenannten Wildcard-Zeichen * gearbeitet werden. Das Wildcard-Zeichen dient dabei als Platzhalter für den Namen. Mit * können somit also alle Knoten (ausgehend von dem aktuellen Knoten und abhängig von der Achse) unabhängig vom Namen selektiert werden. Lokalisierungsschritte werden mit Hilfe des Schrägstrichs / voneinander getrennt.


Wie Sie sicherlich bemerkt haben, war dieses Thema sehr theorielastig. Daher wollen wir uns das theoretische Wissen nun noch an ein paar Praxisbeispielen verdeutlichen. In den Beispielen nutzen wir folgendes XML-Dokument:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

<adressbuch>
    <kontakt geschlecht="m" alter="17">
        <name>Max Mustermann</name>
        <strasse>Musterstraße 123</strasse>
        <ort>12345 Musterstadt</ort>
    </kontakt>
    <kontakt geschlecht="w" alter="24">
        <name>Maria Musterfrau</name>
        <strasse>Musterstraße 456</strasse>
        <ort>67890 Musterhafen</ort>
    </kontakt>
    <kontakt geschlecht="m" alter="53">
        <name>Peter Müller</name>
        <strasse>Hauptstraße 29</strasse>
        <ort>27946 Programmierstadt</ort>
    </kontakt>
</adressbuch>

Eine kurze Erklärung dazu: adressbuch ist das Wurzelelement (nicht der Wurzelknoten), welchem 3 Kindelemente (child) mit dem Namen kontakt untergeordnet sind. Das Elternelement (parent) der kontakt-Elemente ist daher das Element adressbuch. Jedes kontakt-Element besitzt das Attribut geschlecht, welches angibt, ob es sich um eine männliche oder weibliche Person handelt, und das Attribut alter, welche das Alter der Person spezifiziert. Genauere Angaben zur Person werden über die Elemente name, strasse (eigentlich straße, jedoch sollten Sonderzeichen in Knotennamen vermieden werden) und ort festgelegt. Zu den übergeordneten Knoten (ancestor) des Elements ort, gehört daher kontakt und adressbuch. Untergeordnete Knoten (descendant) aus Sicht des Elements adressbuch sind die kontakt-Elemente sowie deren ungeordneten Elemente name, strasse und ort.

Nun wollen wir uns jedoch ein paar XPath-Ausdrücken widmen. Folgender Ausdruck selektiert alle kontakt-Elemente:

/child::adressbuch/child::kontakt

Die weiter oben angesprochene verkürzte Notation würde dazu wie folgt aussehen:

/adressbuch/kontakt

Möchten wir z. B. nur das erste kontakt-Element selektieren, so notieren wir den folgenden Ausdruck:

/child::adressbuch/child::kontakt[1]

In der Regel wird die ausführliche Notation nur selten verwendet. In den nächsten Beispielen entspricht der erste Ausdruck immer der ausführlichen Notation und der zweite Ausdruck der verkürzten Notation. Hier die verkürzte Notation zum Ausdruck von oben:

/adressbuch/kontakt[1]

Wollen wir alle kontakt-Elemente selektieren, die über das Attribut geschlecht verfügen (unabhängig vom Wert), dann könnten wir folgenden Ausdruck verwenden:

/child::adressbuch/child::kontakt[attribute::geschlecht]
/adressbuch/kontakt[@geschlecht]

Es ist aber auch möglich, mittels Prädikat mehrere Attribute „auf einmal“ abzufragen. Im folgenden Beispiel werden alle kontakt-Elemente selektiert, die über das Attribut geschlecht und alter verfügen:

/child::adressbuch/child::kontakt[attribute::geschlecht and attribute::alter]
/adressbuch/kontakt[@geschlecht and @alter]

Stellen Sie sich vor, Sie möchten als nächstes alle kontakt-Elemente selektieren, aber nur dann, wenn der Wert des Attributs geschlecht m ist:

/child::adressbuch/child::kontakt[attribute::geschlecht='m']
/adressbuch/kontakt[@geschlecht='m']

Mit dem Ausdruck von oben erhalten Sie nun die kompletten kontakt-Knoten aller männlichen Kontakte Ihres Adressbuchs. Es ist aber auch möglich, nur die Namen dieser Personen herauszufinden, indem wir das name-Element selektieren:

/child::adressbuch/child::kontakt[attribute::geschlecht='m']/child::name
/adressbuch/kontakt[@geschlecht='m']/name

Bei einer Selektierung mit dem Ausdruck von oben werden Sie feststellen (sofern Sie den Ausdruck getestet haben), dass das Ergebnis nicht Max Mustermann und Peter Müller ist, sondern <name>Max Mustermann</name> und <name>Peter Müller</name>. In einigen Fällen kann es jedoch notwendig sein, nicht (wie hier) das name-Element zu selektieren, sondern dessen Textinhalt (also den Textknoten). Für diesen Fall wird als Knotentest text() angegeben. Dadurch kann dann ein Textknoten (der nicht mittels eines Namens selektiert werden kann) adressiert werden. Dies sieht dann bspw. so aus:

/child::adressbuch/child::kontakt[attribute::geschlecht='m']/child::name/child::text()
/adressbuch/kontakt[@geschlecht='m']/name/text()

Attribute, deren Inhalt ein Zahlenwert ist, können auch mit dem Kleiner-Als- und Größer-Als-Operator verglichen werden. Im folgenden Beispiel werden nur Kontakte selektiert die mindestens 18 Jahre alt sind:

/child::adressbuch/child::kontakt[attribute::alter >= 18]
/adressbuch/kontakt[@alter >= 18]

Zum Schluss noch ein Beispiel mit dem Wildcard-Zeichen: Mit dem folgenden Ausdruck selektieren wir alle Kindknoten (unabhängig von deren Namen) der kontakt-Elemente:

/child::adressbuch/child::kontakt/child::*
/adressbuch/kontakt/*

Wichtig: In diesen Beispielen wurde immer mit absoluter Adressierung gearbeitet. In Sprachen wie XSLT wird dies nur selten verwendet, da man sich hier Stück für Stück durch das Dokument durcharbeitet. Für die Beispiele hier hätten wir jedoch dann immer dazu schreiben müssen, welcher Knoten der Kontextknoten, also der „aktuelle“ Knoten ist, um das Beispiel überhaupt nachvollziehen zu können.

Um unsere Webseite für Sie optimal zu gestalten und fortlaufend verbessern zu können, verwenden wir Cookies. Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu. Weitere Informationen OK