XPath-Funktionen in Predicate-Ausdrücken

(Auszug aus "XSLT 2.0 & XPath 2.0" von Frank Bongers, Kapitel 2.)

Die zur Bildung von Predicates eingesetzten XPath-Ausdrücke erlauben auch den Einsatz von Funktionen zur Formulierung der Bedingung. In erster Linie von Interesse ist hier die Teilmenge von Funktionen, die Auskunft über den aktuellen Kontext geben kann – hier als Kontextfunktionen bezeichnet. Aber auch alle anderen Funktionen aus XPath und XSLT dürfen in diesem Zusam­menhang eingesetzt werden, wobei einige der Stringfunktionen und Sequenzfunktionen von vorrangiger Bedeutung sind.

XPath-Funktionen – Streiflicht auf die Syntax

Hier soll zunächst ein kurzer Überblick über die Syntax eines Funktionsaufrufs gegeben werden. Wie sieht eine solche Funktion aus?

Ganz allgemein verwendet man für XPath-Funktionen innerhalb von XPath-Ausdrücken folgende Syntax:

fn:funktionsname()

Ähnlich wie in den meisten anderen Programmiersprachen auch, steht hinter dem Funktionsnamen eine Argumentklammer. Diese kann dazu dienen, Ein­gaben entgegenzunehmen, die verarbeitet werden:

fn:funktionsname(argument1, argument2)

Jede Funktion hat einen Rückgabewert, den der Prozessor nach der Verarbei­tung durch den Rückgabewert (d. h. das Ergebnis) ersetzt. Der Funktionsaufruf ist also eine Art von Platzhalter für seinen Rückgabewert.

<xsl:value-of select="fn:funktionsname()"/>

entspricht daher

<xsl:value-of select="rückgabewert"/>

wobei dieser Rückgabewert ein atomarer Wert, ein Knoten oder eine Sequenz sein kann. Gelegentlich gibt eine Funktion auch eine leere Sequenz bzw. einen leeren String zurück, was beides im jeweiligen Kontext einen neutralen Wert bedeutet (der also keinesfalls Schaden anrichtet).

Der zum Aufruf verwendete Funktionsname kann qualifiziert sein, d. h. mit einem Namensraumpräfix verwendet werden. Für XPath-Funktionen verwen­det man das Präfix fn, und zwar mit folgender Namensraumdeklaration:

xmlns:fn="http://www.w3.org/2005/xpath-function"

In der Regel werden XSLT-Prozessoren die XPath-Funktionen auch an ihrem unqualifiziertem Bezeichner erkennen. Sofern Sie die Funktionsnamen mit Prä­fix verwenden möchten, ist es jedoch obligatorisch, den entsprechenden Namensraum im Stylesheet zu deklarieren.

Zu beachten, wenn auch im aktuellen Zusammenhang noch nicht von Bedeu­tung, ist die Typbindung von Funktionsargumenten: Funktionen erwarten in XPath 2.0 Eingangswerte eines bestimmten Typs und melden einen Typfehler, wenn dies nicht gewährleistet ist. Eine automatische Typkonvertierung hinter den Kulissen, wie man sie von XPath 1.0 her kennt, gibt es nicht mehr. Im Gegen­zug besitzt auch der Rückgabewert verlässlich einen bestimmten Datentyp.

Kontextfunktionen: fn:position() und fn:last()

Hilfreich bei der Verarbeitung einer Sequenz sind Kenntnisse über die Zahl der in ihr existierenden Items und die Position des aktuell verarbeiteten Items in der Sequenz – mit anderen Worten über den Kontext. Im Fall einer Sequenz aus Elementen <buch> mag für die Verarbeitung von Interesse sein, wie viele Bücher ausgegeben werden sollen, und ob das aktuell ausgegebene Buch mög­licherweise das letzte in der Sequenz ist.

XPath stellt hierfür zwei Funktionen zur Verfügung, die die genannten Informationen liefern können: fn:position() und fn:last().

fn:position()

gibt eine Ganzzahl zurück, die der Position des aktuellen Items in der aktuel­len Sequenz entspricht.

fn:last()

gibt eine Ganzzahl zurück, die der Position des letzten Items der Sequenz ent­spricht. Dies ist gleichbedeutend mit der Zahl der Items.

Beide Funktionen werden häufig innerhalb von Predicates benötigt (auch für andere Zwecke, etwa Nummerierungen, wie im Folgenden gezeigt wird).

Um aus der Initialsequenz alle bis auf die ersten fünf Bücher mittels eines Pre­dicates auszufiltern, können Sie folgenden Ausdruck verwenden:

<xsl:apply-templates select="buch[fn:position() &lt; 6]"/>

Hierbei ist die Sequenz, auf die fn:position() angewendet wird, die zunächst vom Location Step gebildete Sequenz aus allen Büchern. Von denen werden diejenigen gewählt, die das Predicate erfüllen. Dies sind die ersten fünf <buch>-Elemente.

Um nur die letzten fünf Bücher in der Sequenz zu behalten, können Sie Folgen­des schreiben:

<xsl:apply-templates select="buch[fn:position() &gt; last()-6]"/>

Dies funktioniert, weil der Subtraktionsoperator höhere Präzedenz als der Ver­gleichsoperator besitzt. Eine Klammersetzung ist nicht nötig.

Um auf die oben angerissene Problemstellung mehrerer Indexzahlen zurückzu­kommen – mit Hilfe von fn:position() sind diese einfach lösbar. So wählt

buch[fn:position()=1 or fn:position()=3]

das erste und dritte Buch der Sequenz, und

buch[fn:position() &gt;1 and fn:position() &lt; 6]

das zweite bis fünfte Buch-Element der Sequenz.

Boolesche Funktionen: fn:not()

Die Funktion fn:not() negiert ihr Eingabeargument und kann zur Formulierung von Predicates herangezogen werden. Ist das Funktionsargument true, so gibt die Funktion false zurück und umgekehrt:

buch[fn:not(buchautor='Panter, Peter' or @kat='reisen')]

Dieser Pfadausdruck enthält nur jene Bücher, deren Autor weder Peter Panter heißt, noch die in die Kategorie 'reisen' fallen.

Die Verwendung der Funktion ist selten wirklich erforderlich; sie lässt sich oft umgehen, indem ihr Argument umgekehrt wird. Hier wäre dies:

buch[buchautor!='Panter, Peter' and @kat!='reisen']

Stringfunktionen: fn:contains(), fn:starts-with(), fn:ends-with()

Wenn es um Bedingungen für den Stringwert von Knoten geht, kann auf ent­sprechende Funktionen von XPath zurückgegriffen werden. Für Predicates eig­nen sich vordringlich die Funktionen fn:contains() und fn:starts-with(), gege­benenfalls (eher selten) auch fn:ends-with(), die alle zwei Stringargumente entgegennehmen und einen Booleschen Wert zurückgeben. So kann beispiels­weise mittels

buch[fn:contains(buchautor[1], 'Hans')]

eine Sequenz aus Buch-Elementen zusammengestellt werden, die ein <buchau­tor>-Kindelement besitzen, dessen Stringwert die Zeichenkette 'Hans' enthält. Dies wäre für 'Hass, Hans' der Fall oder für 'Hansen, Carl'.

Interessanter ist vielleicht in diesem speziellen Zusammenhang die Funktion fn:starts-with(), falls nach Anfangsbuchstaben gefiltert werden soll.

buch[fn:starts-with(buchautor[1], 'A')]

liefert Bücher aller Autoren, deren Nachname mit A beginnt (was bei der hier verwendeten Inhaltsstruktur des Buchautor-Elements funktioniert).

Hinweis:
Das zusätzliche innere Predicate buchautor[1] ist notwendig, weil die Stringfunktionen fn:contains() und fn:starts-with() genau einen String als erstes Argument erwarten. Ein zweites oder drittes Autor-Element muss vorsichtshalber ausgefiltert werden, damit die Verarbeitung stattfin­den kann.

RegEx-Funktionen: fn:matches()

Komplexere Bedingungen erfordern die Verwendung regulärer Ausdrücke, die von XPath 2.0 im Rahmen mehrerer Funktionen unterstützt werden. Für Predicates bietet sich fn:matches() an, das true zurückgibt, wenn der reguläre Ausdruck auf den untersuchten String passt. So selektiert

buch[fn:matches(buchautor[1], '^[A-H].*ss[a-z]+')]

die Bücher, deren erstes Autor-Element einen Nachnamen (mit denen der untersuchte String beginnt) mit einem Anfangsbuchstaben von A bis H besitzt, dem irgendwo im Namen ein Doppel-S folgt, an das sich mindestens ein weiterer Buchstabe anschließt. Dies gilt für 'Assmann, Peter', 'Esser, Klaus', 'Hesse, Hermann', aber nicht für 'Hass, Hans' (hier folgt dem zweiten S ein Komma, kein Buchstabe).

   

<< zurück vor >>
Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © Galileo Press, Bonn 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT 2.0 & XPath 2.0 ― Das umfassende Handbuch" denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Galileo Press, Rheinwerkallee 4, 53227 Bonn