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 Zusammenhang 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, Eingaben entgegenzunehmen, die verarbeitet werden:
fn:funktionsname(argument1, argument2)
Jede Funktion hat einen Rückgabewert, den der Prozessor nach der Verarbeitung 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 verwendet 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 Bedeutung, 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 Gegenzug 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öglicherweise 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 aktuellen Sequenz entspricht.
fn:last()
gibt eine Ganzzahl zurück, die der Position des letzten Items der Sequenz entspricht. 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 Predicates auszufiltern, können Sie folgenden Ausdruck verwenden:
<xsl:apply-templates select="buch[fn:position() < 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 Folgendes schreiben:
<xsl:apply-templates select="buch[fn:position() > last()-6]"/>
Dies funktioniert, weil der Subtraktionsoperator höhere Präzedenz als der Vergleichsoperator besitzt. Eine Klammersetzung ist nicht nötig.
Um auf die oben angerissene Problemstellung mehrerer Indexzahlen zurückzukommen – 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() >1 and fn:position() < 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 entsprechende Funktionen von XPath zurückgegriffen werden. Für Predicates eignen sich vordringlich die Funktionen fn:contains() und fn:starts-with(), gegebenenfalls (eher selten) auch fn:ends-with(), die alle zwei Stringargumente entgegennehmen und einen Booleschen Wert zurückgeben. So kann beispielsweise mittels
buch[fn:contains(buchautor[1], 'Hans')]
eine Sequenz aus Buch-Elementen zusammengestellt werden, die ein <buchautor>-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 stattfinden 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