XML Path Language (XPath)
|
Copyright © 1999 W3C (MIT, INRIA, Keio), All Rights Reserved. Es gelten die W3C-Regeln zu Haftung, Warenzeichen und Verwendung des Dokuments sowie die Lizenzregeln für Software.
Die Sprache XPath dient zur Adressierung von Teilen eines XML-Dokuments. Sie wurde für die Verwendung sowohl in XSLT als auch in XPointer entworfen.
Dieses Dokument wurde von Mitgliedern des W3C und anderen Interessierten geprüft und vom Direktor als W3C-Empfehlung gebilligt. Es ist ein abgeschlossenes Dokument und darf als Referenzmaterial verwendet oder als normative Referenz von einem anderen Dokument zitiert werden. Die Rolle des W3C bei der Erstellung dieser Empfehlung ist es, die Spezifikation bekannt zu machen und ihre breite Anwendung zu fördern. Dies erhöht die Funktionsfähigkeit und Interoperabilität des Web.
Die Liste der bekannten Fehler in dieser Spezifikation ist unter http://www.w3.org/1999/11/REC-xpath-19991116-errata verfügbar.
Anmerkungen zu dieser Spezifikation können an www-xpath-comments@w3.org geschickt werden; alle Anmerkungen sind in einem Archiv verfügbar.
Die englische Version dieser Spezifikation ist die einzig normative Version. Allerdings werden Übersetzungen dieses Dokuments unter http://www.w3.org/Style/XSL/translations.html aufgeführt.
Aktuelle W3C-Empfehlungen und weitere technische Dokumente sind unter http://www.w3.org/TR zu finden.
Diese Spezifikation ist das Ergebnis der gemeinsamen Arbeit der XSL- und der XML-Linking-Arbeitsgruppen und damit Teil der W3C Style Activity und der W3C XML Activity.
XPath ist das Ergebnis der Bemühungen, eine gemeinsame Syntax und Semantik für jene Funktionen bereitzustellen, die sowohl von XSL Transformations [XSLT] als auch von XPointer [XPointer] genutzt werden. Die primäre Aufgabe von XPath besteht in der Adressierung von Teilen eines XML-Dokuments [XML]. Zur Unterstützung dieser Aufgabe werden außerdem einfache Hilfsmittel für die Manipulation von Zeichenketten, Zahlen und booleschen Werten bereitgestellt. XPath benutzt eine kompakte Nicht-XML-Syntax, um die Verwendung von XPath-Ausdrücken innerhalb von URIs und XML-Attributen zu erleichtern. XPath operiert auf der abstrakten, logischen Struktur eines XML-Dokuments, nicht auf seiner äußerlichen Syntax. Seinen Namen erhält XPath durch die Verwendung einer auch in URLs genutzten Pfad-Notation (path), mit der sich durch die hierarchische Struktur eines XML-Dokuments navigieren lässt.
Neben der Verwendung für die Adressierung wurde XPath so gestaltet, dass eine natürliche Teilmenge davon zum Matching (Testen, ob ein Knoten auf ein Muster passt) genutzt werden kann. Diese Anwendung von XPath ist in XSLT beschrieben.
Anmerkung des Übersetzers: Diese Teilmenge wird in XSLT Muster (pattern) genannt. Obwohl diese Muster durch eine eigene Grammatik definiert werden, ist jedes Muster auch ein XPath-Ausdruck. Neben XSLT und XPointer existieren weitere Spezifikationen, die XPath nutzen. Als Beispiel sei hier der Arbeitsentwurf des W3C für die XML-Abfragesprache XQuery [XQuery] genannt, deren Syntax erweiterte XPath-Ausdrücke verwendet. |
XPath modelliert ein XML-Dokument als einen Baum, der aus Knoten besteht. Es gibt verschiedene Knotentypen, unter anderem Elementknoten, Attributknoten und Textknoten. XPath definiert, wie der Zeichenkettenwert für jeden Knotentyp berechnet wird. Einige Knoten besitzen zusätzlich einen Namen. XPath unterstützt in vollem Umfang XML-Namensräume [XML Names]. Daher wird der Name eines Knotens als ein Paar aus einem lokalen Bestandteil und einem gegebenenfalls leeren Namensraum-URI modelliert – dieses wird erweiterter Name genannt. Das Datenmodell ist detailliert in [5 Datenmodell] beschrieben.
Anmerkung des Übersetzers: Zur Veranschaulichung der durch XPath modellierten Baumstruktur soll folgendes Beispiel dienen: <?xml version="1.0"?> <!DOCTYPE rezept SYSTEM "rezept.dtd"> <?xml-stylesheet href="style.xsl" type="text/xml"?> <rezept> <zutat id="mehl">200g Mehl</zutat> <!-- weitere Zutaten --> <anleitung> Zuerst nehmen Sie das <zutat xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="mehl">Mehl</zutat> und mischen es mit ... </anleitung> </rezept> Dieses recht kurze XML-Dokument besitzt bereits eine aus 23 Knoten bestehende Baumrepräsentation:
Die XML-Deklaration sowie die Dokumenttyp-Deklaration finden sich in
der Baumdarstellung nicht wieder, auf sie kann über einen
XPath-Ausdruck auch nicht zugegriffen werden. Alle anderen Bestandteile
des Dokuments (Wurzel, Elemente, Textinhalt, Attribute, Namensräume,
Kommentare, Processing Instructions) werden durch entsprechende Knoten
des Baumes repräsentiert. Die leeren Quadrate symbolisieren Textknoten,
die ausschließlich Leerraumzeichen enthalten. Inwieweit sich solcher
Leerraum in eigenen Textknoten wiederfindet, wird von der XPath
nutzenden Anwendung bestimmt. Schließlich sei auf die implizit zu jedem
Element gehörenden Namensraumknoten für den Das Document Object Model [DOM] definiert ebenfalls eine Baumrepräsentation, die allerdings in einigen Punkten von der in XPath verwendeten abweicht. Auf diese Unterschiede wird innerhalb des Kapitels [5 Datenmodell] eingegangen. |
Das primäre syntaktische Konstrukt in XPath ist der Ausdruck. Ein Ausdruck lässt sich aus der Produktion Expr ableiten. Die Auswertung eines Ausdrucks ergibt ein Objekt, das zu einem der folgenden vier Grundtypen gehört:
Anmerkung des Übersetzers: Das sind die vier Grundtypen, die XPath definiert. Tatsächlich können darauf aufbauende Spezifikationen weitere Typen definieren, sodass die Auswertung eines XPath-Ausdrucks ein Objekt dieses neuen Typs ergeben kann. Insbesondere können im Ausdruck enthaltene Variablen Objekte anderer Typen aufnehmen. Wie man sieht, gibt es keinen Datentyp für Knoten. Ein einzelner Knoten kann aber als Knotenmenge (node-set) dargestellt werden, die genau ein Element enthält. Die innerhalb von Zeichenketten erlaubten UCS-Zeichen (Universal Multiple-Octet Coded Character Set) sind in [ISO/IEC 10646] bzw. [ISO/IEC 10646, 2nd Edition] beschrieben. |
Ein Ausdruck wird immer bezüglich eines Kontextes ausgewertet. XSLT und XPointer spezifizieren, wie dieser Kontext bei der Verwendung von XPath-Ausdrücken in XSLT bzw. XPointer bestimmt wird. Der Kontext besteht aus:
Die Kontextposition ist immer kleiner oder gleich der Kontextgröße.
Die Variablenbelegungen bestehen aus einer Abbildung von Variablennamen auf Variablenwerte. Der Wert einer Variablen ist ein Objekt, welches von jedem beliebigen Typ sein kann, der für Ausdrücke möglich ist. Daneben sind auch weitere Typen möglich, die hier nicht spezifiziert werden.
Anmerkung des Übersetzers:
In der XSLT-1.0-Spezifikation [XSLT] wird beispielsweise
als neuer Typ Ergebnisteilbaum (result tree
fragment) eingeführt. Werte
dieses Typs entstehen im Ergebnis des Transformationsprozesses. Durch
die folgende Variablenvereinbarung wird z.B. eine Variable namens
<xsl:variable name="antwort"> <antwort><xsl:value-of select="6 * 7" /></antwort> </xsl:variable> Dieser Typ wird voraussichtlich in zukünftigen XSLT-Versionen nicht mehr existieren, da das Ergebnis einer Transformation dann eine normale Knotenmenge vom Typ node-set sein wird, siehe [XSLT 2.0]. Die folgende Anweisung erzeugt dagegen eine Variable, deren Wert sich aus der Berechnung eines XPath-Ausdrucks expression ergibt: <xsl:variable name="var" select="expression" />
An dieser Stelle sei darauf hingewiesen, dass die Erzeugung der
Variablenbelegungen für
Die XPointer-Spezifikation [XPointer], die ebenfalls XPath
nutzt, sieht keine Möglichkeiten für das Erzeugen von
Variablenbelegungen vor. Die Verwendung von Variablenreferenzen
innerhalb eines XPointer-Ausdrucks führt daher zu einem syntaktischen
Fehler. Die als Arbeitsentwurf des W3C vorgelegte Abfragesprache für
XML-Dokumente XQuery [XQuery] benutzt zur Erzeugung von
Variablenbelegungen so genannte FLWR-Ausdrücke (gesprochen
"flower", eine Abkürzung für Andere auf XPath aufbauende Spezifikationen müssen in analoger Weise definieren, wie Variablenbelegungen für einen Kontext erzeugt werden. |
Die Funktionsbibliothek besteht aus einer Abbildung von Funktionsnamen auf Funktionen. Jede Funktion besitzt null oder mehr Argumente und liefert einen einzelnen Wert. Diese Spezifikation definiert eine Bibliothek von Grundfunktionen, die von allen XPath-Implementationen unterstützt werden muss (siehe [4 Bibliothek der Grundfunktionen]). Bei einer Grundfunktion gehören die Argumente und das Ergebnis einem der vier Grundtypen an. Sowohl XSLT als auch XPointer erweitern XPath um zusätzliche Funktionen, von denen einige auf den vier Grundtypen, andere auf zusätzlichen, durch XSLT und XPointer definierten Typen operieren.
Namensraumdeklarationen bestehen aus einer Abbildung von Präfixen auf Namensraum-URIs.
Anmerkung des Übersetzers:
Angenommen, ein Element enthält in seinem Start-Tag folgende
Namensraumdeklaration:
|
Die Variablenbelegungen, die Funktionsbibliothek und die Namensraumdeklarationen, die benutzt werden, um einen Teilausdruck zu berechnen, sind immer dieselben, die auch für den umgebenden Ausdruck benutzt werden. Der Kontextknoten, die Kontextposition und die Kontextgröße, die zur Berechnung eines Teilausdrucks benutzt werden, sind dagegen zuweilen verschieden von denen des umgebenden Ausdrucks. Mehrere Arten von Ausdrücken ändern den Kontextknoten, aber nur Prädikate ändern die Kontextposition und die Kontextgröße (siehe [2.4 Prädikate]). Bei der Beschreibung, wie bestimmte Ausdrücke zu berechnen sind, wird immer explizit angegeben, ob sich der Kontextknoten, die Kontextposition oder die Kontextgröße bei der Berechnung von Teilausdrücken ändert. Wird nichts über Kontextknoten, Kontextposition und Kontextgröße ausgesagt, bleiben sie bei der Berechnung von Teilausdrücken dieser Ausdrücke gleich.
Anmerkung des Übersetzers: Zur Erklärung hier ein kleiner Vorgriff: Innerhalb eines Lokalisierungspfades ändert jeder Schritt den Kontextknoten, der für die Berechnung der folgenden Schritte relevant ist. Durch ein Prädikat werden Knoten aus einer Knotenmenge herausgefiltert, sodass die Kontextgröße sich in der Regel verkleinert und die Position der gefilterten Knoten sich entsprechend ändert. |
XPath-Ausdrücke erscheinen häufig in XML-Attributen. Die in diesem
Abschnitt spezifizierte Grammatik wird auf Attributwerte nach ihrer
Normalisierung gemäß XML 1.0 angewendet. Wenn beispielsweise die
Grammatik das Zeichen <
verwendet, darf dieses
nicht in der XML-Quelle als <
auftreten, sondern muss
gemäß den XML-1.0-Regeln notiert werden, zum Beispiel durch Eingabe
als <
. Innerhalb von Ausdrücken werden
Zeichenkettenliterale durch einfache oder doppelte Anführungszeichen
begrenzt, die ebenfalls zur Begrenzung von XML-Attributen verwendet
werden. Um zu vermeiden, dass ein Anführungszeichen innerhalb eines
Ausdrucks durch den XML-Prozessor als Abschluss des Attributwertes
interpretiert wird, kann das Anführungszeichen als Zeichenreferenz
eingegeben werden ("
oder
'
). Alternativ können im Ausdruck einfache
Anführungszeichen benutzt werden, falls das XML-Attribut durch
doppelte Anführungszeichen begrenzt wird oder umgekehrt.
Anmerkung des Übersetzers: Statt "Zeichenreferenz" muss es hier "Entity-Referenz" heißen. Abgesehen davon gibt es immer noch Fälle, in denen dieses einfache Kochrezept nicht ausreichend ist – nämlich dann, wenn eine Zeichenkette benötigt wird, die beide Arten von Anführungszeichen enthalten soll.
Angenommen, es soll getestet werden, ob der Inhalt des Elements
para="Sie fragte: "Wie geht's?""
Das ist aber keine Lösung, da ein XML-Parser, der diese Zeichenfolge
analysiert, Entity-Referenzen auflöst. Ein darauf aufsetzender
XPath-Prozessor kann nicht mehr zwischen »"« und
» <xsl:if test='para="Sie fragte: "Wie geht's?""'> (diese Zeile ist im XML-Sinn wohlgeformt), so führt das zu einem Fehler im XPath-Prozessor, da dieser trotzdem die folgende Zeichenkette auswertet: para="Sie fragte: "Wie geht's?"" Eine einfache Lösung für solche Fälle besteht darin, die betreffende Zeichenkette als Wert einer Variablen zu definieren, etwa in XSLT per <xsl:variable name="string">Sie fragte: "Wie geht's?"</xsl:variable> und anschließend diese Variable in XPath-Ausdrücken zu verwenden. <xsl:if test="para=$string"> Alternativ kann man die gewünschte Zeichenkette aus mehreren Teilen zusammensetzen (unter Benutzung der noch zu erläuternden Funktion concat), wobei jede Teilzeichenkette jeweils nur eine Sorte von Anführungszeichen enthält: para=concat('Sie fragte: "Wie geht', "'", 's?"') Das Anführungszeichen, das zur Begrenzung dieses Ausdrucks innerhalb eines Attributwertes genutzt wird, muss dann durch die dazugehörige Entity-Referenz ersetzt werden. Das Ergebnis sieht zwar unübersichtlich aus, ist aber syntaktisch korrekt: <xsl:if test="para=concat('Sie fragte: "Wie geht', "'", 's?"')"> Diese zweite Variante muss verwendet werden, wenn Variablen nicht erlaubt sind, etwa innerhalb eines XSLT-Musters oder als Bestandteil eines XPointers. |
Ein wichtiger spezieller Ausdruck ist der Lokalisierungspfad. Ein Lokalisierungspfad wählt eine Knotenmenge relativ zu einem Kontextknoten aus. Das Ergebnis der Berechnung eines Ausdrucks, der ein Lokalisierungspfad ist, ist genau die Knotenmenge, die die durch den Lokalisierungspfad ausgewählten Knoten enthält. Lokalisierungspfade können Ausdrücke rekursiv enthalten, die zum Filtern von Knotenmengen benutzt werden. Ein Lokalisierungspfad lässt sich aus der Produktion LocationPath ableiten.
Die in der nachfolgenden Grammatik verwendeten Nichtterminale QName und NCName sind in [XML Names] definiert, S ist in [XML] definiert. Die Grammatik verwendet die gleiche EBNF-Notation wie in [XML] (mit der Ausnahme, dass Grammatiksymbole immer mit einem Großbuchstaben beginnen).
Anmerkung des Übersetzers: Die Erweiterte Backus-Naur-Form (EBNF) wird zur Notation von formalen Grammatiken verwendet. Sie wird im Kapitel Notation der XML-Spezifikation [XML, 2nd Edition] näher erläutert. |
Ausdrücke werden geparst, indem die Zeichenfolge in einzelne Tokens zerlegt und anschließend die entstehende Folge der Tokens geparst wird. Leerraumzeichen können beliebig zwischen Tokens verwendet werden. Der Zerlegungsprozess wird in [3.7 Lexikalische Struktur] beschrieben.
Anmerkung des Übersetzers:
Ein Token ist eine syntaktische Einheit von Zeichen, etwa der Name
» |
Obwohl Lokalisierungspfade nicht das allgemeinste grammatische Konstrukt der Sprache darstellen (ein Lokalisierungspfad ist ein Spezialfall eines Ausdrucks), sind sie doch das wichtigste Konstrukt und werden deshalb als Erstes beschrieben.
Jeder Lokalisierungspfad kann durch eine unkomplizierte und eher verbale Syntax ausgedrückt werden. Daneben gibt es eine Reihe von syntaktischen Abkürzungen, mit denen sich häufige Fälle kurz und prägnant ausdrücken lassen. Dieser Abschnitt erläutert die Semantik von Lokalisierungspfaden anhand der ausführlichen Syntax. Die abgekürzte Syntax wird im Anschluss daran erläutert, indem gezeigt wird, wie diese auf die ausführliche Syntax abgebildet wird (siehe [2.5 Abgekürzte Syntax]).
Es folgen einige Beispiele für Lokalisierungspfade unter Benutzung der ausführlichen Syntax:
child::para
wählt die Kindelemente
para
des Kontextknotens aus.
child::*
wählt alle Kindelemente des
Kontextknotens aus.
child::text()
wählt alle Textknoten aus, die
Kinder des Kontextknotens sind.
child::node()
wählt alle Kindknoten des
Kontextknotens aus, unabhängig von ihrem Knotentyp.
Anmerkung des Übersetzers: Obwohl sich sämtliche XPath-Lokalisierungspfade für Kontextknoten jedes Typs anwenden lassen, muss an dieser Stelle darauf hingewiesen werden, dass nur der Wurzelknoten sowie Elementknoten Kinder haben können. Diese Kinder können Element-, Text-, Kommentar- und Processing-Instruction-Knoten sein. Attribut- und Namensraumknoten sind niemals Kinder anderer Knoten. Dieses Konzept wird noch einmal ausführlich in Kapitel [5 Datenmodell] beschrieben. |
attribute::name
wählt das Attribut
name
des Kontextknotens aus.
attribute::*
wählt alle Attribute des
Kontextknotens aus.
Anmerkung des Übersetzers: Diese beiden Ausdrücke sind nur sinnvoll, wenn der Kontextknoten ein Elementknoten ist. Für alle anderen Knotentypen liefern sie die leere Knotenmenge. |
descendant::para
wählt die
para
-Elemente aus, die Nachkommen des Kontextknotens
sind.
ancestor::div
wählt alle
div
-Elemente aus, die Vorfahren des Kontextknotens
sind.
ancestor-or-self::div
wählt alle
div
-Vorfahren des Kontextknotens sowie auch den
Kontextknoten selbst aus, falls dieser ein div
-Element
ist.
descendant-or-self::para
wählt alle
para
-Nachkommen des Kontextknotens aus, sowie auch den
Kontextknoten selbst, falls dieser ein para
-Element
ist.
self::para
wählt den Kontextknoten aus, falls
dieser ein para
-Element ist, und sonst
nichts.
child::chapter/descendant::para
wählt die para
-Elemente aus, die Nachkommen der
chapter
-Kindelemente des Kontextknotens sind.
child::*/child::para
wählt
alle para
-Enkelelemente des Kontextknotens aus.
/
wählt die Wurzel des Dokuments aus (diese
ist immer der Vater des Dokumentelements).
Anmerkung des Übersetzers: Der Begriff Wurzel unterscheidet sich hier von dem in der XML-Spezifikation [XML, 2nd Edition] genutzten. Dort bezeichnen Wurzel und Dokumentelement das Gleiche. In der XPath-Terminologie ist das Dokumentelement ein Kind des Wurzelknotens. Der Wurzelknoten entspricht damit dem Dokument-Entity, siehe [5.1 Wurzelknoten]. Das ist insofern wichtig, als der Wurzelknoten zusätzlich Kommentar- oder Processing-Instruction-Knoten als Kinder haben kann, die damit Geschwister des Dokumentelements sind.
Des Weiteren muss hier hinzugefügt werden, dass durch |
/descendant::para
wählt alle
para
-Elemente aus, die im gleichen Dokument wie der
Kontextknoten enthalten sind.
Anmerkung des Übersetzers:
Genau genommen werden alle |
/descendant::olist/child::item
wählt alle
item
-Elemente aus, die ein olist
-Vaterelement
besitzen und die sich im gleichen Dokument wie der Kontextknoten
befinden.
Anmerkung des Übersetzers: Die folgenden Beispiele zeigen Lokalisierungspfade, bei denen die ursprünglich ausgewählten Knotenmengen durch nachgestellte Filterausdrücke in eckigen Klammern, so genannte Prädikate, weiter eingeschränkt werden. |
child::para[position()=1]
wählt das erste
para
-Kindelement des Kontextknotens aus.
child::para[position()=last()]
wählt das letzte
para
-Kindelement des Kontextknotens aus.
child::para[position()=last()-1]
wählt das
vorletzte para
-Kindelement des Kontextknotens
aus.
child::para[position()>1]
wählt alle
para
-Kindelemente des Kontextknotens aus, mit Ausnahme des
ersten para
-Kindelements des Kontextknotens.
following-sibling::chapter[position()=1]
wählt das nächste chapter
-Geschwisterelement des
Kontextknotens aus.
preceding-sibling::chapter[position()=1]
wählt das vorhergehende chapter
-Geschwisterelement des
Kontextknotens aus.
Anmerkung des Übersetzers: An dieser Stelle sei als kurzer Vorgriff darauf hingewiesen, dass sich die Position eines Knotens in der aktuellen Kontextknotenliste über die Funktion position bestimmen lässt und diese Position offenbar von der Blickrichtung abhängt. Von allen vorhergehenden Geschwisterelementen befindet sich der unmittelbare Vorgänger an der Position 1. |
/descendant::figure[position()=42]
wählt das
zweiundvierzigste figure
-Element im Dokument aus.
Anmerkung des Übersetzers:
Hier werden alle |
/child::doc/child::chapter[position()=5]/child::section[position()=2]
wählt das zweite section
-Element des fünften
chapter
-Elements des doc
-Dokumentelements
aus.
child::para[attribute::type="warning"]
wählt alle para
-Kindelemente des Kontextknotens aus, die
ein type
-Attribut mit dem Wert warning
besitzen.
child::para[attribute::type='warning'][position()=5]
wählt das fünfte para
-Kindelement des Kontextknotens aus,
das ein Attribut type
mit dem Wert warning
besitzt.
child::para[position()=5][attribute::type="warning"]
wählt das fünfte para
-Kindelement des Kontextknotens aus,
wenn dieses Kind ein type
-Attribut mit dem Wert
warning
besitzt.
Anmerkung des Übersetzers:
Die letzten beiden Beispiele zeigen, wie sich durch ein Prädikat
Kontextgröße und -position ändern können. Das Prädikat
|
child::chapter[child::title='Introduction']
wählt die chapter
-Kindelemente des Kontextknotens aus,
die wenigstens ein title
-Kindelement mit einem Zeichenkettenwert gleich
Introduction
besitzen.
child::chapter[child::title]
wählt die
chapter
-Kindelemente des Kontextknotens aus, die ein
oder mehrere title
-Kindelemente besitzen.
child::*[self::chapter or self::appendix]
wählt die chapter
- und appendix
-Kindelemente
des Kontextknotens aus.
Anmerkung des Übersetzers:
Hier werden aus allen Kindern ( |
child::*[self::chapter or
self::appendix][position()=last()]
wählt das letzte
chapter
- oder appendix
-Kindelement des
Kontextknotens aus.
Anmerkung des Übersetzers:
Hier wird zunächst die Menge aller |
Es gibt zwei Arten von Lokalisierungspfaden: relative und absolute Lokalisierungspfade.
Ein relativer Lokalisierungspfad wird durch eine Folge aus einem
oder mehreren Lokalisierungsschritten gebildet, die durch /
voneinander getrennt sind. Die Schritte eines relativen
Lokalisierungspfades werden von links nach rechts zusammengesetzt.
Jeder Schritt wählt der Reihe nach eine Knotenmenge relativ zu einem
Kontextknoten aus. Eine Anfangsfolge von Schritten wird mit einem
folgenden Schritt wie folgt zusammengesetzt: Die Anfangsfolge von
Schritten wählt eine Knotenmenge relativ zu einem Kontextknoten aus.
Jeder Knoten in dieser Menge wird dann als Kontextknoten für den
folgenden Schritt benutzt. Die durch diesen Schritt bestimmten
Knotenmengen werden vereinigt. Die Vereinigung ist dann genau die
Knotenmenge, die durch das Zusammensetzen der Schritte ausgewählt wird.
Zum Beispiel wählt child::div/child::para
die
para
-Kindelemente der div
-Kindelemente des
Kontextknotens aus, oder – mit anderen Worten – die
para
-Enkelelemente, die div
-Elternelemente
haben.
Ein absoluter Lokalisierungspfad besteht aus dem Zeichen
/
und einem optional folgenden relativen
Lokalisierungspfad. Ein /
allein wählt den
Wurzelknoten des Dokuments aus, das den Kontextknoten enthält.
Falls ein relativer Lokalisierungspfad folgt, so wählt der
Lokalisierungspfad die Knotenmenge aus, die ein relativer
Lokalisierungspfad relativ zum Wurzelknoten des den Kontextknoten
enthaltenen Dokuments auswählen würde.
Anmerkung des Übersetzers:
Hier bietet sich der Vergleich zu Pfaden im Dateisystem an: Sowohl in
UNIX-Betriebssystemen als auch innerhalb von URLs wird der Schrägstrich
»
Man sollte sich allerdings einer Feinheit bewusst sein: Während
beispielsweise durch » |
[1] | LocationPath | ::= | RelativeLocationPath | |
| AbsoluteLocationPath | ||||
[2] | AbsoluteLocationPath | ::= | '/' RelativeLocationPath? | |
| AbbreviatedAbsoluteLocationPath | ||||
[3] | RelativeLocationPath | ::= | Step | |
| RelativeLocationPath '/' Step | ||||
| AbbreviatedRelativeLocationPath |
Anmerkung des Übersetzers: Die obige Grammatik gibt das bisher Beschriebene noch einmal formal wieder. Wie man sieht, können Lokalisierungspfade auch abgekürzte Bestandteile enthalten. Diese werden in Kapitel [2.5 Abgekürzte Syntax] beschrieben. |
Ein Lokalisierungsschritt hat drei Bestandteile:
eine Achse, welche die Beziehung zwischen den durch den Lokalisierungsschritt ausgewählten Knoten und dem Kontextknoten innerhalb des Baumes spezifiziert,
einen Knotentest, der den Knotentyp und den erweiterten Namen der durch den Lokalisierungsschritt ausgewählten Knoten spezifiziert, sowie
null oder mehr Prädikate, die mittels beliebiger Ausdrücke die durch den Lokalisierungsschritt ausgewählte Knotenmenge weiter verfeinern können.
Anmerkung des Übersetzers: Prädikate im mathematischen Sinn sind Aussagen über Eigenschaften, die für die betreffenden Objekte wahr oder falsch sein können. In diesem Sinn wählt ein Prädikat aus einer Knotenmenge genau diejenigen Knoten aus, für die die entsprechende Aussage zutrifft. Aber auch ohne Kenntnis der Begriffswelt der Prädikatenlogik kann man sich anhand der Begriffe »Prädikatswein« oder »Prädikatsexamen« verdeutlichen, dass hier jeweils eine bestimmte Eigenschaft bzw. Qualität des beschriebenen Objekts ausgedrückt wird. |
Ein Lokalisierungsschritt besteht syntaktisch aus dem Namen der
Achse, gefolgt von zwei Doppelpunkten und dem Knotentest, gefolgt von
null oder mehr in eckigen Klammern eingeschlossenen Ausdrücken. Zum
Beispiel enthält child::para[position()=1]
die Achse
child
, den Knotentest para
und ein Prädikat
[position()=1]
.
Die durch den Lokalisierungspfad ausgewählte Knotenmenge ergibt sich aus der durch Achse und Knotentest bestimmten Ausgangsknotenmenge, indem dort der Reihe nach die einzelnen Prädikate angewendet werden.
Die Ausgangsknotenmenge enthält alle Knoten, die zum Kontextknoten
in der durch die Achse angegebenen Beziehung stehen und die den im
Knotentest spezifizierten Knotentyp und
erweiterten Namen besitzen.
Zum Beispiel wählt der Lokalisierungsschritt
descendant::para
alle para
-Nachkommen des
Kontextknotens aus: descendant
besagt, dass jeder Knoten
in der Ausgangsknotenmenge ein Nachkomme des Kontextknotens sein muss;
para
besagt, dass jeder Knoten in der Ausgangsknotenmenge
ein Element mit dem Namen para
sein muss. Die verfügbaren
Achsen werden in [2.2 Achsen] beschrieben, die verfügbaren
Knotentests in [2.3 Knotentests]. Die Bedeutung einiger
Knotentests hängt von der jeweiligen Achse ab.
Die Ausgangsknotenmenge wird durch das erste Prädikat gefiltert und ergibt eine neue Knotenmenge. Diese wird anschließend durch das zweite Prädikat gefiltert und so weiter. Die resultierende Knotenmenge ist schließlich die Knotenmenge, die durch den Lokalisierungsschritt ausgewählt wird. Die Achse beeinflusst, wie der Ausdruck in jedem Prädikat berechnet wird. Die Semantik eines Prädikats ist damit bezüglich einer Achse definiert (siehe [2.4 Prädikate]).
Anmerkung des Übersetzers: Dieser letzte Satz bezieht sich auf Prädikate, die die Kontextposition und damit die Näheposition der gefilterten Knoten auswerten. Zur Verdeutlichung der Vorgehensweise bei mehreren Prädikaten sei auf die beiden bereits diskutierten Beispiele child::para[attribute::type="warning"][position()=5] und child::para[position()=5][attribute::type="warning"] in Kapitel [2 Lokalisierungspfade] verwiesen. |
[4] | Step | ::= | AxisSpecifier NodeTest Predicate* | |
| AbbreviatedStep | ||||
[5] | AxisSpecifier | ::= | AxisName '::' | |
| AbbreviatedAxisSpecifier |
Es stehen die folgenden Achsen zur Verfügung:
Die Achse child
enthält die Kinder des
Kontextknotens.
Anmerkung des Übersetzers: Die Kreise, die hier und bei den folgenden Achsen zur Darstellung der einzelnen Knoten genutzt werden, repräsentieren keine speziellen Knotentypen. Es könnte sich also sowohl um Elemente als auch um Textknoten, Kommentare oder Processing Instructions handeln. Sie repräsentieren allerdings niemals Attribut- oder Namensraumknoten, da diese nur über eigens dafür definierte Achsen erreicht werden können. Insbesondere sind es keine Kinder anderer Knoten. Die Nummern geben die Näheposition der Knoten in der durch die Achse ausgewählten Knotenmenge an. |
Die Achse descendant
enthält die Nachkommen des
Kontextknotens; ein Nachkomme ist ein Kind oder ein Kind eines
Kindes usw. Die Nachkommenachse enthält niemals Attribut- oder
Namensraumknoten.
Anmerkung des Übersetzers: |
Die Achse parent
enthält den Elternknoten des Kontextknotens, falls es
einen gibt.
Anmerkung des Übersetzers: Bis auf den Wurzelknoten besitzt jeder Knoten einen Elternknoten. |
Die Achse ancestor
enthält die Vorfahren des
Kontextknotens; die Vorfahren des Kontextknotens bestehen aus dem
Elternknoten des Kontextknotens,
dessen Elternknoten usw. Die Vorfahrenachse enthält somit immer den
Wurzelknoten, es sei denn, der Kontextknoten selbst ist der
Wurzelknoten.
Anmerkung des Übersetzers: |
Die Achse following-sibling
enthält alle
nachfolgenden Geschwister des Kontextknotens; falls der Kontextknoten
ein Attribut- oder Namensraumknoten ist, ist diese Achse leer.
Anmerkung des Übersetzers: Geschwister sind die Knoten, die den gleichen Elternknoten wie der Kontextknoten besitzen. |
Die Achse preceding-sibling
enthält alle
vorhergehenden Geschwister des Kontextknotens; falls der Kontextknoten
ein Attribut- oder Namensraumknoten ist, ist diese Achse leer.
Anmerkung des Übersetzers: |
Die Achse following
enthält alle Knoten im
gleichen Dokument wie der Kontextknoten, die nach dem Kontextknoten
in Dokumentordnung auftreten, und zwar ohne seine Nachkommen und ohne
Attribut- und Namensraumknoten.
Anmerkung des Übersetzers: |
Die Achse preceding
enthält alle Knoten im
gleichen Dokument wie der Kontextknoten, die vor dem Kontextknoten
in Dokumentordnung auftreten, und zwar ohne seine Vorfahren und ohne
Attribut- und Namensraumknoten.
Anmerkung des Übersetzers: |
Die Achse attribute
enthält die Attribute des
Kontextknotens; diese Achse ist leer, es sei denn, der Kontextknoten
ist ein Elementknoten.
Die Achse namespace
enthält alle Namensraumknoten
des Kontextknotens; diese Achse ist leer, es sei denn, der Kontextknoten
ist ein Elementknoten.
Die Achse self
enthält nur den Kontextknoten
selbst.
Anmerkung des Übersetzers: |
Die Achse descendant-or-self
enthält den
Kontextknoten sowie die Nachkommen des Kontextknotens.
Anmerkung des Übersetzers: |
Die Achse ancestor-or-self
enthält den
Kontextknoten sowie die Vorfahren des Kontextknotens; diese Achse
enthält somit immer den Wurzelknoten.
Anmerkung des Übersetzers: |
Anmerkung: Die Achsenancestor
,descendant
,following
,preceding
undself
partitionieren ein Dokument (unter Auslassung der Attribut- und Namensraumknoten): sie überschneiden sich nicht und enthalten zusammen alle Knoten des Dokuments.
Anmerkung des Übersetzers: |
Anmerkung des Übersetzers:
Attribut- und Namensraumachse nehmen hier eine Sonderrolle ein. Die
adressierten Knoten zeichnen sich nämlich durch einen bestimmten festen
Knotentyp aus (den so genannten Hauptknotentyp). Da diese Knoten
per Definition keine Kinder anderer Knoten sind, wurden die speziellen
Achsen |
Jede Achse besitzt einen Hauptknotentyp. Falls eine Achse Elemente enthalten kann, so ist der Hauptknotentyp der Elementtyp, ansonsten ist es genau der Typ der Knoten, die die Achse enthalten kann. Das bedeutet:
Ein Knotentest, der ein QName
ist, ist genau dann erfüllt, wenn der Knotentyp (siehe
[5 Datenmodell]) der Hauptknotentyp ist und einen
erweiterten Namen besitzt,
der gleich dem erweiterten
Namen des
QName ist.
Beispielsweise wählt child::para
die
para
-Kindelemente des Kontextknotens aus. Falls der
Kontextknoten keine para
-Kinder besitzt, ist das
Ergebnis eine leere Knotenmenge. attribute::href
wählt
die href
-Attribute des Kontextknotens aus. Falls der
Kontextknoten keine href
-Attribute besitzt, ist das
Ergebnis eine leere Knotenmenge.
Anmerkung des Übersetzers:
Das Akronym QName steht für
"qualifizierter Name" und bedeutet, dass der entsprechende
Name aus einem optionalen Präfix und einem lokalen Bestandteil bestehen
kann. Beide Teile werden durch einen Doppelpunkt voneinander getrennt.
Durch das Präfix wird der Namensraum bestimmt, zu dem der lokale Name
gehört. Im Beispiel
Möchte man auf das
Wie in den Beispielen am Beginn des Kapitels bereits gezeigt wurde,
eignet sich die Achse |
Ein QName im Knotentest wird
in einen erweiterten Namen
unter Verwendung der Namensraumdeklarationen aus dem Kontext des
Ausdrucks expandiert. Dies geschieht in der gleichen Weise wie bei
Elementnamen in Start- und End-Tags, allerdings mit der Ausnahme, dass
ein mit xmlns
deklarierter voreingestellter Namensraum
nicht genutzt wird: d.h. enthält
QName kein Präfix, so ist der
Namensraum-URI leer (das ist die gleiche Regel, nach der auch
Attributnamen expandiert werden). Es ist ein Fehler, wenn der
QName ein Präfix enthält, für das
es keine Namensraumdeklaration im Kontext des Ausdrucks gibt.
Anmerkung des Übersetzers:
Qualifizierte Namen werden also gemäß der Namensraum-Empfehlung
[XML Names] expandiert. Das bedeutet insbesondere, dass
in einem XPath-Ausdruck nicht das gleiche Präfix wie im betrachteten
XML-Dokument benutzt werden muss. Wichtig ist nur, dass beide
Präfixe den gleichen Namensraum repräsentieren.
Wenn beispielsweise das zugrunde liegende XML-Dokument ein
XHTML-Dokument ist, dessen Elemente zum Namensraum
Gerade in diesen Fällen ist Vorsicht geboten. Sehr leicht übersieht
man eine solche Namensraumdeklaration, die sich selbstverständlich
auch auf alle Kindelemente auswirkt, und ist gewillt, nur den
jeweiligen Elementnamen in einem Ausdruck anzugeben, z.B.
bei folgender XSLT-Anweisung:
Stellt man fest, dass XPath-Ausdrücke nach dem Einfügen einer DTD in
das Originaldokument nicht mehr die richtigen Knoten zurückliefern
(was sich beispielsweise darin äußert, dass ein XSLT-Stylesheet nicht
mehr die erwartete Ausgabe liefert), ist in der Regel ebenfalls die
Deklaration eines voreingestellten Namensraums die Ursache. Eine
Deklaration innerhalb der DTD der Form
Schließlich sei noch einmal darauf hingewiesen, dass sich ein
voreingestellter Namensraum im Kontext eines XPath-Ausdrucks nicht auf
den Ausdruck auswirkt. Ein qualifizierter Name ohne Präfix adressiert
damit immer ein Element oder ein Attribut, das zu keinem Namensraum
gehört. Die folgende Variante ist damit keine Alternative
zum obigen Beispiel:
|
Ein Knotentest *
ist für jeden Knoten des
Hauptknotentyps erfüllt. Beispielsweise wählt child::*
alle Kindelemente und attribute::*
alle Attributknoten des
Kontextknotens aus.
Anmerkung des Übersetzers:
Handelt es sich beim Kontextknoten um einen Elementknoten, so liefert
der Schritt |
Ein Knotentest kann in der Form NCName:*
auftreten. In
diesem Fall wird das Präfix wie bei einem QName unter Verwendung der
Namensraumdeklarationen des Kontextes expandiert. Es ist ein Fehler,
wenn es für das Präfix keine Namensraumdeklaration im Kontext
des Ausdrucks gibt. Der Knotentest ist erfüllt für jeden Knoten des
Hauptknotentyps, dessen erweiterter
Name den Namensraum-URI besitzt, zu dem das Präfix expandiert,
unabhängig vom lokalen Bestandteil des Namens.
Anmerkung des Übersetzers:
Beispielsweise wählt Diese Form von Knotentests kann in einem XSLT-Stylesheet innerhalb eines Musters z.B. dazu genutzt werden, alle Elemente eines bestimmten Namensraums in der gleichen Weise zu behandeln. Eingebettete XHTML-Elemente in einem beliebigen zu transformierenden XML-Dokument können auf diese Weise einfach in die Ausgabe kopiert werden, ohne dass diese Elemente explizit benannt werden müssen. |
Der Knotentest text()
ist erfüllt für jeden Textknoten.
Zum Beispiel wählt child::text()
alle Textknoten aus, die
Kinder des Kontextknotens sind. Analog ist der Knotentest
comment()
für jeden Kommentarknoten erfüllt und der
Knotentest processing-instruction()
für jede
Processing Instruction. Dem Test processing-instruction()
kann ein Literal als Argument übergeben
werden. In diesem Fall ist der Test für jede Processing Instruction
erfüllt, deren Name gleich dem Wert des übergebenen
Literals ist.
Anmerkung des Übersetzers:
Offensichtlich werden Kommentare nicht einfach ignoriert, sondern durch
eigene Knoten innerhalb des XML-Baumes repräsentiert. Auf diese Weise
können XPath-Ausdrücke mittels
Für Processing Instructions gibt es ebenfalls entsprechende Knoten im
XML-Baum. Jede Processing Instruction besitzt einen Namen (ein Ziel),
z.B. |
Der Knotentest node()
ist für alle Knoten jedes
beliebigen Typs erfüllt.
Anmerkung des Übersetzers:
Möchte man alle Knoten eines Dokuments auswählen, kann man z.B.
die folgenden Knotenmengen vereinigen:
Es wurde bereits auf die Sonderrolle von Attribut- und Namensraumknoten
hingewiesen. Diese werden nicht durch einen Knotentest, sondern durch
entsprechende Achsen ausgewählt. Das hat zur Folge, dass sich zwar
einfach prüfen lässt, ob der Kontextknoten z.B. ein Textknoten ist
(per |
[7] | NodeTest | ::= | NameTest | |
| NodeType '(' ')' | ||||
| 'processing-instruction' '(' Literal ')' |
Eine Achse ist entweder vorwärts- oder rückwärtsgerichtet. Eine
vorwärtsgerichtete Achse enthält immer nur den Kontextknoten oder
Knoten, die nach dem Kontextknoten im Dokument auftreten. Eine
rückwärtsgerichtete Achse enthält immer nur den Kontextknoten oder
Knoten, die vor dem Kontextknoten im Dokument auftreten.
Demzufolge sind die Achsen
ancestor
, ancestor-or-self
,
preceding
und preceding-sibling
rückwärtsgerichtete Achsen. Alle anderen Achsen sind vorwärtsgerichtet.
Da die Achse self
immer höchstens einen Knoten enthält,
hat es keine Bedeutung, ob sie als vorwärts- oder rückwärtsgerichtete
Achse betrachtet wird.
Die
Näheposition eines Knotens in einer Knotenmenge bezüglich
einer Achse ist definiert als die Position des Knotens in dieser
Knotenmenge, welche in Dokumentordnung geordnet ist, wenn es sich um
eine vorwärtsgerichtete Achse handelt, und welche in umgekehrter
Dokumentordnung geordnet ist, wenn es sich um eine rückwärtsgerichtete
Achse handelt. Die erste Position ist 1.
Anmerkung des Übersetzers: Diese recht komplizierte Definition bedarf einer Erläuterung. Die Knoten in einer Knotenmenge sind ungeordnet – es handelt sich schließlich um eine Menge. Allerdings kann über die Funktion position die Position eines Knotens in der aktuellen Knotenliste bestimmt werden. Die Reihenfolge der Knoten orientiert sich an der Reihenfolge, in der die Knoten im XML-Dokument auftreten. Bei vorwärtsgerichteten Achsen wird diese Ursprungsreihenfolge beibehalten und man spricht von Dokumentordnung. Für rückwärtsgerichtete Achsen wird die Reihenfolge umgekehrt und man spricht von umgekehrter Dokumentordnung.
Die obige Definition hat zur Folge, dass innerhalb eines
Lokalisierungsschrittes immer der nächstgelegene Knoten die
Position 1 hat. Abhängig von der Blickrichtung kann es sich um einen
unmittelbaren Vorgänger ( Die Näheposition ist nur innerhalb von Prädikaten in Lokalisierungsschritten von Bedeutung, da hier die ausschlaggebende Achse bekannt ist. Die in [4.2 Zeichenkettenfunktionen] vorgestellte Funktion string (ebenso wie die Funktionen number und boolean) konvertiert dagegen bei einer Knotenmenge immer den ersten Knoten bezüglich der Dokumentordnung, unabhängig davon, auf welchem Weg diese Knotenmenge gebildet wurde.
Für vorwärtsgerichtete Achsen gilt daher folgende Gleichheit
(am Beispiel string(following::p) = string(following::p[position()=1])
Dies ist bei rückwärtsgerichteten Achsen nicht der Fall. Stattdessen
gilt hier (am Beispiel string(preceding::p) = string(preceding::p[position()=last()])
Die XSLT-Anweisung Für Attribute und Namensraumknoten ist die Diskussion um Position und Richtung bedeutungslos. Das liegt daran, dass die Reihenfolge, in der Attribute und Namensraumdeklarationen im Start-Tag eines Elements angegeben wurden, als irrelevant angesehen wird. Informationen darüber sind daher nicht mehr im XML-Baum enthalten. |
Ein Prädikat filtert eine Knotenmenge bezüglich einer Achse und produziert damit eine neue Knotenmenge. Für jeden zu filternden Knoten der Knotenmenge wird der dazugehörige Ausdruck PredicateExpr berechnet, und zwar mit diesem Knoten als Kontextknoten, der Anzahl der Knoten der Knotenmenge als Kontextgröße und mit der Näheposition des Knotens in der Knotenmenge bezüglich der Achse als Kontextposition. Falls die Berechnung von PredicateExpr für diesen Knoten wahr ergibt, wird der Knoten in die Ergebnisknotenmenge aufgenommen, andernfalls nicht.
Anmerkung des Übersetzers: Diese Definition soll anhand eines Beispiels veranschaulicht werden: ancestor::person[position() >= 2]
Achse und Knotentest
Falls der Ausdruck eines nachfolgenden Prädikats nicht auf Kontextgröße
oder -position zugreift, kann dieser Ausdruck bereits im ersten
Prädikat berechnet und über den logischen Operator child::chapter[child::title][attribute::type="warning"] liefert damit die gleiche Knotenmenge wie child::chapter[child::title and attribute::type="warning"] |
Ein PredicateExpr wird durch
Berechnung des Expr und anschließender
Konvertierung des Ergebnisses in einen booleschen Wert bestimmt. Falls
das Ergebnis eine Zahl war, wird es für den Fall, dass diese Zahl
gleich der Kontextposition ist, in den Wert wahr
konvertiert, ansonsten in den Wert falsch. Wenn das
Ergebnis keine Zahl war, dann wird es so
konvertiert wie bei einem Aufruf der Funktion
boolean. Damit ist ein Lokalisierungspfad
para[3]
äquivalent zu para[position()=3]
.
Anmerkung des Übersetzers:
Da die abgekürzte Syntax erst im folgenden Kapitel beschrieben wird,
sollte als Beispiel hier besser
Für Zahlen als Wert eines PredicateExpr
gilt hier eine Sonderregel. Diese ermöglicht eine Schreibweise, die
dem Zugriff auf Feldelemente in anderen Programmiersprachen gleicht.
Allerdings muss beachtet werden, dass ein Ausdruck
|
[8] | Predicate | ::= | '[' PredicateExpr ']' | |
[9] | PredicateExpr | ::= | Expr |
Zunächst einige Beispiele für Lokalisierungspfade, die die abgekürzte Syntax benutzen:
para
wählt die para
-Kindelemente des
Kontextknotens aus.
*
wählt alle Kindelemente des Kontextknotens
aus.
text()
wählt alle Textknoten aus, die Kinder des
Kontextknotens sind.
@name
wählt das Attribut name
des
Kontextknotens aus.
@*
wählt alle Attribute des Kontextknotens
aus.
para[1]
wählt das erste
para
-Kindelement des Kontextknotens aus.
para[last()]
wählt das letzte
para
-Kindelement des Kontextknotens aus.
*/para
wählt alle para
-Enkelelemente
des Kontextknotens aus.
/doc/chapter[5]/section[2]
wählt das zweite
section
-Element des fünften chapter
-Elements
von doc
aus.
chapter//para
wählt die
para
-Elemente aus, die Nachkommen der
chapter
-Kindelemente des Kontextknotens sind.
//para
wählt alle para
-Nachkommen
der Dokumentwurzel aus und somit alle para
-Elemente im
gleichen Dokument wie der Kontextknoten.
//olist/item
wählt all die
item
-Elemente aus dem gleichen Dokument wie der
Kontextknoten aus, die ein olist
-Elternelement
besitzen.
.
wählt den Kontextknoten aus.
.//para
wählt die para
-Elemente aus,
die Nachkommen des Kontextknotens sind.
..
wählt den Elternknoten des Kontextknotens
aus.
../@lang
wählt das Attribut lang
des Elternknotens des Kontextknotens aus.
para[@type="warning"]
wählt alle
para
-Kindelemente des Kontextknotens aus, die ein
Attribut type
mit dem Wert warning
besitzen.
para[@type="warning"][5]
wählt das fünfte
para
-Kindelement des Kontextknotens aus, das ein Attribut
type
mit dem Wert warning
besitzt.
para[5][@type="warning"]
wählt das fünfte
para
-Kindelement des Kontextknotens aus, falls dieses
Kind ein Attribut type
mit dem Wert warning
besitzt.
chapter[title="Introduction"]
wählt die
chapter
-Kindelemente des Kontextknotens aus, die ein
oder mehrere title
-Kindelemente mit einem Zeichenkettenwert gleich
Introduction
besitzen.
chapter[title]
wählt die
chapter
-Kindelemente des Kontextknotens aus, die ein
oder mehrere title
-Kindelemente besitzen.
employee[@secretary and @assistant]
wählt alle
employee
-Kindelemente des Kontextknotens aus, die sowohl
ein Attribut secretary
als auch ein Attribut
assistant
besitzen.
Die wichtigste Abkürzung besteht darin, dass child::
in einem Lokalisierungsschritt weggelassen werden kann.
Die Standardachse ist also child
. So steht beispielsweise
ein Lokalisierungspfad div/para
abkürzend für
child::div/child::para
.
Für Attribute gibt es ebenfalls eine Abkürzung:
attribute::
kann zu @
abgekürzt werden.
Ein Lokalisierungspfad para[@type="warning"]
steht
beispielsweise abkürzend für
child::para[attribute::type="warning"]
und wählt damit
para
-Kindelemente mit einem Attribut type
aus, dessen Wert gleich warning
ist.
//
ist die Abkürzung für
/descendant-or-self::node()/
. Zum Beispiel steht
//para
abkürzend für
/descendant-or-self::node()/child::para
und wählt damit
alle para
-Elemente im Dokument aus (selbst ein
para
-Element, das ein Dokumentelement ist, wird durch
//para
ausgewählt, da der Dokumentelementknoten ein
Kind des Wurzelknotens ist). div//para
steht
abkürzend für
div/descendant-or-self::node()/child::para
und wählt
daher alle para
-Nachfolger von div
-Kindern
aus.
Anmerkung des Übersetzers:
Hier enthält das Originaldokument einen kleinen Fehler.
Der vollständige Lokalisierungspfad für das letzte Beispiel muss
|
Anmerkung: Der Lokalisierungspfad//para[1]
bedeutet nicht das Gleiche wie/descendant::para[1]
. Der zweite wählt das erste Nachkommenelementpara
aus, der erste wählt allepara
-Nachkommen aus, die das erste Kind ihrer Eltern sind.
Anmerkung des Übersetzers: Davon kann man sich durch Bestimmung des vollständigen Ausdrucks leicht überzeugen: //para[1] = /descendant-or-self::node()/para[1] = /descendant-or-self::node()/child::para[1]
Das Prädikat |
Ein Lokalisierungsschritt .
steht abkürzend für
self::node()
. Das ist insbesondere in Verbindung mit
//
nützlich. Der Lokalisierungspfad .//para
steht zum Beispiel abkürzend für
self::node()/descendant-or-self::node()/child::para
und wählt daher alle para
-Elemente aus, die Nachkommen
des Kontextknotens sind.
Analog steht der Lokalisierungsschritt ..
abkürzend
für parent::node()
. Zum Beispiel steht
../title
abkürzend für
parent::node()/child::title
und wählt damit die
title
-Kindelemente des Elternknotens des Kontextknotens
aus.
Anmerkung des Übersetzers:
Die Kombination aus
Ein Blick in die unten stehende Grammatik zeigt, dass es sich bei
|
[10] | AbbreviatedAbsoluteLocationPath | ::= | '//' RelativeLocationPath | |
[11] | AbbreviatedRelativeLocationPath | ::= | RelativeLocationPath '//' Step | |
[12] | AbbreviatedStep | ::= | '.' | |
| '..' | ||||
[13] | AbbreviatedAxisSpecifier | ::= | '@'? |
Eine Variablenreferenz (VariableReference) ergibt den Wert, der an den Variablennamen innerhalb der Menge der Variablenbelegungen des Kontexts gebunden ist. Es ist ein Fehler, falls dem Variablennamen in der Menge der Variablenbelegungen aus dem Kontext des Ausdrucks kein Wert zugewiesen wurde.
Anmerkung des Übersetzers:
Der Name einer Variablen ist ein qualifizierter Name, kann also ein
Präfix enthalten, das auf einen Namensraum verweist. Mittels des
Zeichens
Der letzte Satz des obigen Abschnitts bedeutet, dass Variablen vor
ihrer Benutzung definiert worden sein müssen.
Wie bereits erwähnt, sieht XPath dafür keinerlei Sprachelemente vor.
In [XSLT] verwendete Variablen haben immer einen
definierten Wert. So wird durch das leere Element
|
Zum Gruppieren können runde Klammern verwendet werden.
[14] | Expr | ::= | OrExpr | |
[15] | PrimaryExpr | ::= | VariableReference | |
| '(' Expr ')' | ||||
| Literal | ||||
| Number | ||||
| FunctionCall |
Ein Ausdruck, der ein Funktionsaufruf (FunctionCall) ist, wird ausgewertet, indem anhand des Funktionsnamens (FunctionName) die Funktion in der Funktionsbibliothek des Ausdruckskontexts bestimmt, jedes der Argumente (Argument) berechnet und in den von der Funktion erwarteten Typ konvertiert und schließlich die Funktion mit den konvertierten Argumenten aufgerufen wird. Es ist ein Fehler, wenn eine falsche Anzahl von Argumenten übergeben wird oder eines der Argumente nicht in den geforderten Typ konvertiert werden kann. Das Ergebnis des Funktionsaufrufes (FunctionCall) ist der von der Funktion zurückgelieferte Wert.
Die Konvertierung eines Arguments in den Typ string geschieht so wie beim Aufruf der Funktion string. Die Konvertierung eines Arguments in den Typ number geschieht so wie beim Aufruf der Funktion number. Die Konvertierung eines Arguments in den Typ boolean geschieht so wie beim Aufruf der Funktion boolean. Ein Argument, das nicht vom Typ node-set ist, kann nicht in eine Knotenmenge konvertiert werden.
Anmerkung des Übersetzers:
Dieser letzte Satz stimmt insofern, als es keine automatische
Konvertierung in eine Knotenmenge gibt. Zusätzliche Funktionen können
durchaus Werte anderer Typen als Parameter entgegennehmen und eine
Knotenmenge zurückliefern. In vielen XSLT-1.0-konformen Prozessoren
existiert beispielsweise eine Erweiterungsfunktion
|
[16] | FunctionCall | ::= | FunctionName '(' ( Argument ( ',' Argument )* )? ')' | |
[17] | Argument | ::= | Expr |
Ein Lokalisierungspfad kann als Ausdruck benutzt werden. Ein solcher Ausdruck liefert die durch den Pfad ausgewählte Knotenmenge.
Der Operator |
berechnet die Vereinigung seiner
Operanden, welche jeweils Knotenmengen sein müssen.
Anmerkung des Übersetzers: Da es sich um eine Vereinigung von Mengen handelt, ist ein identischer Knoten in beiden Operanden in der Ergebnisknotenmenge auch nur einmal vorhanden. Zusammen mit der Funktion count (siehe [4.1 Funktionen auf Knotenmengen]) lässt sich so die Identität zweier Knoten feststellen.
Die Knotenmenge XPath definiert keine Operatoren für die Bestimmung von Durchschnitt und Differenz zweier Knotenmengen. Basierend auf dem Teilmengentest lassen sich diese Operationen allerdings berechnen:
Durchschnitt von $a[count(.|$b) = count($b)]
Differenz von $a[count(.|$b) != count($b)] Damit lässt sich nun auch testen, ob der Kontextknoten ein Attributknoten ist (analog für Namensraumknoten): count(.|../@*) = count(../@*) Die bedingte Auswahl einer Knotenmenge aus zwei Alternativen abhängig von einem logischen Ausdruck kann durch folgende Konstruktion erreicht werden: node-set1[boolean-test] | node-set2[not(boolean-test)]
In den Programmiersprachen C, C++ und Java stellt der
Fragezeichenoperator
In XSLT-Mustern, die eine Teilmenge der XPath-Ausdrücke bilden, wird
der Operator |
Prädikate werden zum Filtern von Ausdrücken in der gleichen Weise wie in Lokalisierungspfaden benutzt. Es ist ein Fehler, falls das Ergebnis des zu filternden Ausdrucks keine Knotenmenge ist. Das Prädikat filtert die Knotenmenge bezüglich der Kindachse.
Anmerkung: Die Bedeutung eines Prädikats hängt entscheidend davon ab, welche Achse angewendet wird. Zum Beispiel liefertpreceding::foo[1]
das erstefoo
-Element in umgekehrter Dokumentordnung, weil die für das Prädikat[1]
anzuwendende Achse die Vorgängerachse (preceding) ist. Demgegenüber liefert(preceding::foo)[1]
das erstefoo
-Element in Dokumentordnung, weil die Achse, die in diesem Fall für das Prädikat[1]
gilt, die Kindachse ist.
Anmerkung des Übersetzers: Auf diesen Unterschied soll noch einmal deutlich hingewiesen werden: Prädikate, die Bestandteil eines Lokalisierungsschrittes sind, filtern eine Knotenmenge bezüglich der im Lokalisierungsschritt verwendeten Achse. Für jeden Knoten der Knotenmenge ist daher dessen Näheposition relevant. Prädikate, die auf einen XPath-Ausdruck angewendet werden, interpretieren die betreffenden Knoten immer in Dokumentordnung, da laut Definition in solch einem Fall die Kindachse anzuwenden ist.
Im obigen Beispiel
Das folgende Beispiel stellt den Sachverhalt aus einer praxisnäheren
Sicht dar. Es gibt zwar die Achse
Bei der Betrachtung des Beispiels
An dieser Stelle sei darauf hingewiesen, dass über die in [XSLT] definierte Funktion document auch Knotenmengen aus verschiedenen Dokumenten miteinander vereinigt werden können. In diesem Fall gibt es keine definierte Dokumentordnung für die Vereinigungsmenge mehr. Die Anwendung eines entsprechenden Prädikats ist damit implementationsabhängig. Entsprechendes gilt bei einer Knotenmenge, die die Attribute eines Elements enthält. |
Die Operatoren /
und //
verbinden einen
Ausdruck und einen relativen Lokalisierungspfad. Es ist ein Fehler,
wenn die Berechnung des Ausdrucks keine Knotenmenge ergibt. Der
Operator /
arbeitet dabei in der gleichen Weise wie in
einem Lokalisierungspfad. Ebenso wie in Lokalisierungspfaden steht
//
abkürzend für
/descendant-or-self::node()/
.
Es gibt keine Objekte, die in eine Knotenmenge konvertiert werden können.
Anmerkung des Übersetzers:
Angenommen, eine Variable namens
Dabei ist zu beachten, dass sich einem Ausdruck anschließende
Lokalisierungsschritte immer auf die Position der Knoten im
XML-Dokument beziehen und nicht auf die durch den Ausdruck
berechnete Knotenmenge. Beispielsweise bestimmt
Ausdrücke, speziell Variablen, dürfen nur vor
Wie schon gesagt wurde, muss ein Ausdruck, dem ein Prädikat oder einer
der Operatoren |
[18] | UnionExpr | ::= | PathExpr | |
| UnionExpr '|' PathExpr | ||||
[19] | PathExpr | ::= | LocationPath | |
| FilterExpr | ||||
| FilterExpr '/' RelativeLocationPath | ||||
| FilterExpr '//' RelativeLocationPath | ||||
[20] | FilterExpr | ::= | PrimaryExpr | |
| FilterExpr Predicate |
Ein Objekt vom Typ boolean kann zwei Werte annehmen, wahr und falsch.
Die Berechnung eines or
-Ausdrucks erfolgt, indem jeder
der Operanden berechnet und in einen booleschen Wert wie beim Aufruf
der Funktion boolean konvertiert wird. Das
Ergebnis ist der Wert wahr, wenn einer der beiden Werte
wahr ist, und andernfalls falsch. Der rechte
Operand wird nicht mehr ausgewertet, wenn der linke Operand
wahr ergibt.
Die Berechnung eines and
-Ausdrucks erfolgt, indem jeder
der Operanden berechnet und in einen booleschen Wert wie beim Aufruf
der Funktion boolean konvertiert wird. Das
Ergebnis ist der Wert wahr, wenn beide Werte
wahr sind, und andernfalls falsch. Der rechte
Operand wird nicht mehr ausgewertet, wenn der linke Operand
falsch ergibt.
Anmerkung des Übersetzers: Mit dieser Regelung lässt sich die Berechnung von Teilausdrücken und der Aufruf enthaltener Funktionen verhindern. Abgesehen von Performance-Aspekten hat sie im Zusammenhang mit XSLT allerdings nicht die gleiche Bedeutung wie in anderen Programmiersprachen. So arbeiten alle XSLT-Funktionen ohne Seiteneffekte (sie produzieren weder Ausgaben noch ändern sie Variableninhalte); Funktionsparameter werden automatisch in den geforderten Typ konvertiert und mathematische Operationen liefern immer einen definierten Wert. Lediglich Typfehler können auftreten, falls ein Ausdruck als Operand oder Funktionsparameter eine Knotenmenge verlangt. Allerdings gibt es in XPath keine Möglichkeit festzustellen, ob ein Teilausdruck vom Typ Knotenmenge ist.
Da sich über Erweiterungsmechanismen jedoch Funktionen definieren
lassen, die die genannten Eigenschaften nicht mehr besitzen,
kann über eine Verknüpfung mit |
Die Berechnung eines EqualityExpr-Ausdrucks (der nicht
allein ein RelationalExpr-Ausdruck ist)
oder eines RelationalExpr-Ausdrucks
(der nicht allein ein AdditiveExpr-Ausdruck ist) geschieht, indem
die Objekte miteinander verglichen werden, die im Ergebnis der
Auswertung der beiden Operanden entstehen.
Die folgenden drei Absätze definieren den Vergleich zwischen den
daraus resultierenden Objekten.
Erst werden Vergleiche, die Knotenmengen betreffen, über Vergleiche
definiert, die keine Knotenmengen betreffen; dies geschieht einheitlich
für =
, !=
, <=
,
<
, >=
und >
.
Dann werden Vergleiche, die keine Knotenmengen betreffen, für
=
und !=
definiert.
Schließlich werden Vergleiche, die keine Knotenmengen betreffen, für
<=
, <
, >=
und
>
definiert.
Wenn beide zu vergleichenden Objekte Knotenmengen sind, so liefert ein Vergleich genau dann den Wert wahr, wenn es einen Knoten aus der ersten Knotenmenge und einen Knoten aus der zweiten Knotenmenge gibt, sodass das Ergebnis des Vergleichs der Zeichenkettenwerte dieser beiden Knoten wahr ergibt. Wenn eines der zu vergleichenden Objekte eine Knotenmenge und das andere eine Zahl ist, dann liefert ein Vergleich genau dann den Wert wahr, wenn es einen Knoten in der Knotenmenge gibt, sodass der Vergleich zwischen der Zahl und dem Ergebnis der Konvertierung des Zeichenkettenwerts dieses Knotens zu einer Zahl über die Funktion number wahr ergibt. Wenn eines der zu vergleichenden Objekte eine Knotenmenge und das andere eine Zeichenkette ist, dann liefert ein Vergleich genau dann den Wert wahr, wenn es einen Knoten in der Knotenmenge gibt, sodass der Vergleich zwischen der Zeichenkette und dem Zeichenkettenwert dieses Knotens wahr ergibt. Wenn eines der zu vergleichenden Objekte eine Knotenmenge und das andere ein boolescher Wert ist, dann liefert ein Vergleich genau dann den Wert wahr, wenn es einen Knoten in der Knotenmenge gibt, sodass der Vergleich zwischen dem booleschen Wert und dem Ergebnis der Konvertierung des Zeichenkettenwerts dieses Knotens zu einem boolschen Wert über die Funktion boolean wahr ergibt.
Wenn keines der zu vergleichenden Objekte eine Knotenmenge ist und
als Operator =
oder !=
vorkommt, so werden
die Objekte wie nachfolgend beschrieben in einen gemeinsamen Typ
konvertiert und anschließend verglichen.
Wenn wenigstens eines der zu vergleichenden Objekte ein boolescher
Wert ist, wird jedes Objekt wie bei der Anwendung der Funktion
boolean in einen booleschen Wert konvertiert.
Wenn wenigstens eines der zu vergleichenden Objekte eine
Zahl ist, wird jedes Objekt wie bei der Anwendung der Funktion
number in eine Zahl konvertiert.
Andernfalls werden beide Objekte wie bei der Anwendung der Funktion
string in Zeichenketten konvertiert.
Der Vergleich =
liefert als Ergebnis genau dann den Wert
wahr, wenn beide Objekte gleich sind;
der Vergleich !=
liefert als Ergebnis genau dann den Wert
wahr, wenn beide Objekte ungleich sind.
Zahlen werden gemäß IEEE 754 [IEEE 754] verglichen.
Zwei boolesche Werte sind gleich, wenn sie entweder beide
wahr oder beide falsch sind. Zwei
Zeichenketten sind genau dann gleich, wenn sie aus derselben Folge von
UCS-Zeichen bestehen.
Anmerkung: Wenn$x
mit einer Knotenmenge belegt ist, dann bedeutet$x="foo"
nicht dasselbe wienot($x!="foo")
: Der erste Vergleich ergibt genau dann wahr, wenn ein Knoten in$x
den Zeichenkettenwertfoo
hat; der zweite ergibt genau dann wahr, wenn alle Knoten in$x
den Zeichenkettenwertfoo
haben.
Anmerkung des Übersetzers:
Der Vergleich
Ein häufigerer Fall dürfte der Test auf Ungleichheit sein. Man möchte
z.B. feststellen, ob der Wert eines Ausdrucks verschieden von
allen Kindelementen
Bemerkenswert ist noch der Fall, dass die beteiligte Knotenmenge leer
ist. Ein Vergleich
Es sei noch einmal darauf hingewiesen, dass für Knotenmengen mit den
Operatoren |
Wenn keines der zu vergleichenden Objekte eine Knotenmenge ist und
als Operator <=
, <
, >=
oder >
vorkommt, so werden beide Objekte in Zahlen
konvertiert und anschließend gemäß IEEE 754 verglichen.
Der Vergleich <
ergibt genau dann den Wert
wahr, wenn die erste Zahl kleiner als die zweite Zahl ist.
Der Vergleich <=
ergibt genau dann den Wert
wahr, wenn die erste Zahl kleiner oder gleich der zweiten
Zahl ist.
Der Vergleich >
ergibt genau dann den Wert
wahr, wenn die erste Zahl größer als die zweite Zahl ist.
Der Vergleich >=
ergibt genau dann den Wert
wahr, wenn die erste Zahl größer oder gleich der zweiten
Zahl ist.
Anmerkung des Übersetzers: Somit sind Vergleiche, an denen Knotenmengen beteiligt sind, dann erfüllt, wenn sich wenigstens ein Knoten aus der jeweiligen Menge finden lässt, dessen Zeichenkettenwert den Vergleich erfüllt. Insbesondere liefert der Vergleich mit wenigstens einer leeren Menge in jedem Fall den Wert falsch. Sind nur Werte verschiedener skalarer Typen beteiligt, so wird in der Rangfolge "boolescher Wert – Zahl – Zeichenkette" ein gemeinsamer Typ gesucht und der jeweils andere Wert konvertiert. Größenvergleiche sind nur für Zahlen definiert.
Unter Ausnutzung dieser Regeln kann z.B. die kleinste Zahl in
einer Knotenmenge $set[not(. > $set)]
Ein Vergleich mit dem speziellen Zahlenwert NaN (Not a Number) liefert
immer den Wert falsch, selbst bei
$set[number()=number() and not(. > $set)] Vorsicht ist geboten, wenn die Werte einer Knotenmenge vor dem Vergleich durch eine Funktion mit skalarem Argumenttyp bearbeitet werden sollen. Übergibt man der Funktion die gesamte Knotenmenge als Argument, wird nur mit dem Funktionswert des ersten Knotens verglichen. Die spezielle Semantik des Vergleichs mit Knotenmengen geht verloren. In der Anmerkung zur Funktion normalize-space wird dies an einem Beispiel ausführlicher erläutert.
XPath stellt keine Möglichkeit zur Verfügung, mit der man Zeichenketten
lexikographisch der Größe nach vergleichen könnte. Abhängig vom
Anwendungsfall lassen sich in XSLT solche Vergleiche durch die
Programmierung rekursiver Templates oder die Benutzung des
|
Anmerkung: Wenn ein XPath-Ausdruck in einem XML-Dokument vorkommt, müssen alle Operatoren<
und<=
gemäß den XML-1.0-Regeln geschützt werden, zum Beispiel als<
und<=
. Im folgenden Beispiel ist der Wert des Attributestest
ein XPath-Ausdruck:<xsl:if test="@value < 10">...</xsl:if>
[21] | OrExpr | ::= | AndExpr | |
| OrExpr 'or' AndExpr | ||||
[22] | AndExpr | ::= | EqualityExpr | |
| AndExpr 'and' EqualityExpr | ||||
[23] | EqualityExpr | ::= | RelationalExpr | |
| EqualityExpr '=' RelationalExpr | ||||
| EqualityExpr '!=' RelationalExpr | ||||
[24] | RelationalExpr | ::= | AdditiveExpr | |
| RelationalExpr '<' AdditiveExpr | ||||
| RelationalExpr '>' AdditiveExpr | ||||
| RelationalExpr '<=' AdditiveExpr | ||||
| RelationalExpr '>=' AdditiveExpr |
Anmerkung: Mit der obigen Grammatik ergibt sich folgende Vorrangfolge (kleinster Vorrang zuerst):Alle Operatoren sind links-assoziativ. Beispielsweise ist
or
and
=
,!=
<=
,<
,>=
,>
3 > 2 > 1
äquivalent zu(3 > 2) > 1
, was den Wert falsch ergibt.
Anmerkung des Übersetzers:
Der Vergleich
3 > 2
ergibt zunächst den Wert wahr. Dieses Ergebnis wird aufgrund des folgenden Vergleichsoperators>
in die Zahl 1 konvertiert, sodass nun1 > 1
berechnet wird, was den Wert falsch liefert. Auf analoge Weise kann man sich überlegen, dass der Ausdruck2 = 1 = 0
wahr, der Ausdruck0 = 0 = 0
hingegen falsch ergibt.Hier ist Vorsicht geboten, da solche Ausdrücke gemäß der XPath-Grammatik erlaubt sind, aber nicht die Semantik besitzen, die man auf den ersten Blick erwarten würde. Sie verhalten sich allerdings genauso wie beispielsweise in den Programmiersprachen C und C++.
Ein Wert vom Typ number repräsentiert eine Gleitkommazahl. Eine Zahl kann jeden beliebigen, doppelt-genauen 64-Bit-Wert des Formats IEEE 754 [IEEE 754] annehmen. Dies beinhaltet den speziellen Wert "Not-a-Number" (NaN), positiv und negativ unendlich, sowie positiv und negativ Null. Für eine Zusammenfassung der wichtigsten Regeln des IEEE-754-Standards siehe Abschnitt 4.2.3 in [JLS].
Anmerkung des Übersetzers: Die genannten speziellen Werte entstehen dann, wenn eine Rechenoperation einen Überlauf produzieren würde bzw. das Ergebnis nicht definiert ist. Beim Rechnen mit Zahlen in XPath können keine Fehler oder Ausnahmen auftreten.
An dieser Stelle sei bereits kurz auf die Produktion für
Number in [3.7 Lexikalische Struktur]
hingewiesen. Zahlen in XPath sind Gleitkommazahlen ohne
Exponentendarstellung. Eine Schreibweise 2.99792E+08 ist nicht
zulässig. Sie können ein negatives, aber kein explizites positives
Vorzeichen besitzen. Soll einer der speziellen Werte wie z.B. positiv
unendlich verwendet werden, muss dieser ermittelt werden, etwa durch
Es gibt in XPath weder einen speziellen Typ für ganzzahlige Werte noch gesonderte Zahlendarstellungen, die eine Zahl als Oktal- oder Hexadezimalzahl interpretieren, wie dies in vielen Programmiersprachen möglich ist. |
Die numerischen Operatoren konvertieren ihre Operanden in Zahlen, so wie bei einem Aufruf der Funktion number.
Der Operator +
addiert.
Der Operator -
subtrahiert.
Anmerkung des Übersetzers:
Gemäß Errata-Dokument [XPath Errata] ist die Semantik des
einstelligen Operators Der zweistellige Operator |
Anmerkung: Da XML innerhalb von Namen das Zeichen-
erlaubt, muss der Operator-
typischerweise von einem Leerraumzeichen angeführt werden. Zum Beispiel ergibtfoo-bar
eine Knotenmenge, die die Kindelemente namensfoo-bar
enthält;foo - bar
ergibt die Differenz aus den Werten, die durch Konvertierung des Zeichenkettenwertes des erstenfoo
-Kindelements in eine Zahl und durch Konvertierung des Zeichenkettenwertes des erstenbar
-Kindelements in eine Zahl entstehen.
Anmerkung des Übersetzers:
Gemäß Errata-Dokument [XPath Errata] ist die Semantik des
Operators
Der Operator
Das Zeichen |
Der Operator div
berechnet eine Gleitkomma-Division
gemäß IEEE 754.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz eingefügt werden: Beachten Sie: Falls das Ergebnis nicht NaN ist, ist das Ergebnis genau dann positiv, wenn beide Operanden das gleiche Vorzeichen besitzen.
Der Schrägstrich |
Der Operator mod
liefert den Rest einer ganzzahligen
Division. Beispiele:
5 mod 2
ergibt 1
5 mod -2
ergibt 1
-5 mod 2
ergibt -1
-5 mod -2
ergibt -1
Anmerkung:mod
berechnet dasselbe wie der Operator%
in Java und ECMAScript.
Anmerkung: Er berechnet nicht dasselbe wie die IEEE-754-Rest-Operation, welche den Rest einer gerundeten Division liefert.
Anmerkung des Übersetzers:
Der |
[25] | AdditiveExpr | ::= | MultiplicativeExpr | |
| AdditiveExpr '+' MultiplicativeExpr | ||||
| AdditiveExpr '-' MultiplicativeExpr | ||||
[26] | MultiplicativeExpr | ::= | UnaryExpr | |
| MultiplicativeExpr MultiplyOperator UnaryExpr | ||||
| MultiplicativeExpr 'div' UnaryExpr | ||||
| MultiplicativeExpr 'mod' UnaryExpr | ||||
[27] | UnaryExpr | ::= | UnionExpr | |
| '-' UnaryExpr |
Zeichenketten bestehen aus einer Folge von null oder mehr Zeichen, wobei Zeichen wie in der XML-Empfehlung [XML] definiert sind. Ein einzelnes XPath-Zeichen entspricht damit einem einzelnen abstrakten Unicode-Zeichen mit einem einzelnen korrespondierenden skalaren Wert (siehe [Unicode]); dies unterscheidet sich allerdings von einem 16-Bit-kodierten Unicode-Zeichen: Die durch Unicode definierte kodierte Zeichenrepräsentation eines abstrakten Zeichens mit einem skalaren Wert größer als U+FFFF ist ein Paar von 16-Bit Unicode-Codes (ein Surrogat-Paar). In vielen Programmiersprachen wird eine Zeichenkette als Folge von 16-Bit-kodierten Unicode-Zeichen repräsentiert; XPath-Implementationen in solchen Sprachen müssen sicherstellen, dass ein Surrogat-Paar korrekt als einzelnes XPath-Zeichen behandelt wird.
Anmerkung: In Unicode ist es möglich, dass zwei Zeichenketten als identisch anzusehen sind, obwohl sie aus unterschiedlichen Folgen abstrakter Unicode-Zeichen bestehen. Zum Beispiel können einige Akzentzeichen entweder in einer vordefinierten (precomposed) oder einer zerlegten (decomposed) Form repräsentiert werden. Damit können XPath-Ausdrücke unerwartete Resultate liefern, es sei denn, sowohl die Zeichen im XPath-Ausdruck als auch die im XML-Dokument wurden zu einer kanonischen Form normalisiert (siehe [Character Model]).
Anmerkung des Übersetzers: Ein zusammengesetztes Zeichen, das sich auch als vordefiniertes Zeichen kodieren lässt, wird durch einen einzigen Unicode-Code repräsentiert. Beispielsweise lässt sich der Umlaut »ü« als U+00FC darstellen. Zugleich kann dieser Buchstabe auch wie jedes zusammengesetzte Zeichen in der zerlegten Form durch die Folge der beiden Codes U+0075 (»u«) und U+0308 (combining diaeresis) kodiert werden. |
Beim Zerlegen in einzelne Tokens wird immer das längstmögliche Token zurückgeliefert.
Zur besseren Lesbarkeit können Leerraumzeichen innerhalb von Ausdrücken verwendet werden, auch wenn es nicht explizit durch die Grammatik erlaubt wurde: ExprWhitespace kann innerhalb von Ausdrücken frei vor oder nach beliebigen ExprTokens eingefügt werden.
Anmerkung des Übersetzers:
An dieser Stelle sei auf die Anmerkung zum Operator für die
Subtraktion, das zweistellige Minus, in [3.5 Zahlen]
hingewiesen. Der erste Absatz legt fest, dass »
Üblicherweise unterscheidet man bei der Definition einer Sprache
zwischen lexikalischen Produktionen, die den Aufbau der lexikalischen
Einheiten, so genannter Tokens festlegen, und syntaktischen Produktionen,
die die mögliche Kombination dieser Tokens zu komplexeren Konstrukten
beschreiben. In der XPath-Spezifikation sind diese beiden Arten von
Produktionen allerdings nicht streng voneinander abgegrenzt. Der
Hauptunterschied zwischen lexikalischen und syntaktischen Produktionen
besteht darin, dass zwischen einzelnen Tokens Leerraumzeichen auftreten
dürfen, nicht jedoch innerhalb eines Tokens. Die Produktion für das
Nichtterminal ExprToken stellt damit die
oberste lexikalische Produktion dar. Daraus ergibt sich, dass ein
Leerzeichen zwischen |
Die folgenden speziellen Regeln für die Zerlegung in Tokens müssen in der angegebenen Reihenfolge angewendet werden, um die Grammatik ExprToken eindeutig zu machen:
Wenn es ein vorhergehendes Token gibt und dieses Token
kein @
, ::
, (
,
[
, ,
oder ein Operator ist, dann muss ein *
als
MultiplyOperator und ein
NCName als OperatorName erkannt werden.
Falls das einem NCName
folgende Zeichen (möglicherweise nach dazwischenliegendem
ExprWhitespace) das Zeichen
(
ist, dann muss das Token als NodeType oder als FunctionName erkannt werden.
Falls die einem NCName folgenden beiden Zeichen
(möglicherweise nach dazwischenliegendem
ExprWhitespace) die Zeichen
::
sind, dann muss das Token als AxisName erkannt werden.
Andernfalls darf das Token nicht als MultiplyOperator, als OperatorName, als NodeType, als FunctionName oder als AxisName erkannt werden.
Anmerkung des Übersetzers: Im zweiten Aufzählungspunkt des Originaldokuments hat sich ein Fehler eingeschlichen. Da Funktionsnamen mit einem Präfix ausgestattet sein können, muss laut Errata-Dokument [XPath Errata] auf QName statt auf NCName verwiesen werden. Alle Standardfunktionen aus XPath, XSLT und XPointer besitzen zwar nur Namen ohne Präfix, der Erweiterungsmechanismus in XSLT erlaubt jedoch XSLT-Implementationen, zusätzliche Funktionen aus einem proprietären Namensraum zur Verfügung zu stellen. Das hier diskutierte Problem der Mehrdeutigkeit umgeht man in vielen anderen Programmiersprachen durch die Definition von Schlüsselwörtern, die dann für frei wählbare Bezeichner nicht mehr zur Verfügung stehen. Ein XML-Autor ist jedoch frei in seiner Wahl der Element- und Attributnamen, also muss auch die Sprache XPath damit umgehen können. Die gefundene Regelung ermöglicht eine kompakte Schreibweise für XPath-Ausdrücke und bürdet die Last der eindeutigen Interpretation der jeweiligen XPath-Implementation auf.
Die folgenden Beispiele zeigen, wie Bezeichner (und der
|
[28] | ExprToken | ::= | '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' | |
| NameTest | ||||
| NodeType | ||||
| Operator | ||||
| FunctionName | ||||
| AxisName | ||||
| Literal | ||||
| Number | ||||
| VariableReference | ||||
[29] | Literal | ::= | '"' [^"]* '"' | |
| "'" [^']* "'" | ||||
[30] | Number | ::= | Digits ('.' Digits?)? | |
| '.' Digits | ||||
[31] | Digits | ::= | [0-9]+ | |
[32] | Operator | ::= | OperatorName | |
| MultiplyOperator | ||||
| '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' | ||||
[33] | OperatorName | ::= | 'and' | 'or' | 'mod' | 'div' | |
[34] | MultiplyOperator | ::= | '*' | |
[35] | FunctionName | ::= | QName - NodeType | |
[36] | VariableReference | ::= | '$' QName | |
[37] | NameTest | ::= | '*' | |
| NCName ':' '*' | ||||
| QName | ||||
[38] | NodeType | ::= | 'comment' | |
| 'text' | ||||
| 'processing-instruction' | ||||
| 'node' | ||||
[39] | ExprWhitespace | ::= | S |
Dieser Abschnitt beschreibt die Funktionen, die bei einer XPath-Implementation immer in der bei der Auswertung von Ausdrücken benutzten Funktionsbibliothek enthalten sein müssen.
Jede Funktion in der Funktionsbibliothek wird über einen Funktionsprototypen spezifiziert, der den Rückgabetyp, den Namen der Funktion und die Typen der Argumente angibt. Falls ein Argument von einem Fragezeichen gefolgt wird, so ist es optional; andernfalls ist es obligatorisch.
Anmerkung des Übersetzers:
Ein Funktionsargument, dem ein Stern |
Die Funktion last liefert eine Zahl, die gleich der Kontextgröße des Kontexts des ausgewerteten Ausdrucks ist.
Die Funktion position liefert eine Zahl, die gleich der Kontextposition im Kontext des ausgewerteten Ausdrucks ist.
Funktion: number count(node-set)
Die Funktion count liefert die Anzahl der Knoten der übergebenen Knotenmenge.
Anmerkung des Übersetzers:
Für den letzten Knoten einer Knotenmenge gilt damit die Gleichheit
Während last also die Kontextgröße zurückgibt, d.h. die Anzahl der Knoten der Knotenmenge, in der sich der Kontextknoten befindet, berechnet count die Anzahl der Knoten einer beliebigen als Argument zu übergebenden Knotenmenge. Es gibt keinen XPath-Ausdruck, der für einen beliebigen Knoten dessen Position in einer vorgegebenen Knotenmenge berechnet.
In bestimmten Situationen lässt sich jedoch das Wissen über die Art der
Beziehungen der Knoten in der Knotenmenge ausnutzen. Möchte man
beispielsweise herausfinden, welche Position das erste
count(para[@type="warning"]/preceding-sibling::para)+1
Diese Methode funktioniert hier deshalb, weil klar ist, dass alle
In Kapitel [3.3 Knotenmengen] wird im Zusammenhang mit dem
Mengenvereinigungsoperator |
Die Funktion id wählt Elemente anhand ihrer eindeutigen ID aus (siehe [5.2.1 Eindeutige IDs]). Wenn als Argument eine Knotenmenge übergeben wird, so ergibt sich das Ergebnis aus der Vereinigung der Knotenmengen, die durch den Aufruf von id mit dem Zeichenkettenwert jedes Knotens aus der übergebenen Knotenmenge berechnet werden. Ist das Argument der Funktion id von einem beliebigen anderen Typ, so wird es wie bei einem Aufruf der Funktion string in eine Zeichenkette konvertiert; die Zeichenkette wird in eine durch Leerraumzeichen getrennte Liste von Tokens aufgeteilt (Leerraumzeichen sind beliebige Folgen von Zeichen, die sich aus der Produktion S ableiten lassen). Das Ergebnis ist eine Knotenmenge, die die Elemente aus dem Dokument des Kontextknotens enthält, die eine eindeutige ID mit dem gleichen Wert wie eines der Tokens der Liste besitzen.
id("foo")
wählt die Elemente mit der eindeutigen
ID foo
aus.
id("foo")/child::para[position()=5]
wählt das
fünfte para
-Kindelement des Elements mit der eindeutigen
ID foo
aus.
Anmerkung des Übersetzers:
Diese Funktion ermöglicht die Auswertung von Attributen des
Typs Entsprechend der obigen Definition gilt also: id("foo bar baz") = id("foo") | id("bar") | id("baz") Die Knoten in der Ergebnisknotenmenge werden durch ein folgendes Prädikat in Dokumentordnung gefiltert und nicht in der Reihenfolge der angegebenen IDs.
Dagegen wird bei der Übergabe einer Knotenmenge, wie im Beispiel
Die Funktion id kann aber nur korrekt arbeiten,
wenn Es gibt keine komplementäre Funktion, die für ein Element dessen ID zurückliefert. Unter Zuhilfenahme von id lässt sich diese Information allerdings herausfinden. Gesucht ist nämlich genau das Attribut, für das die Funktion id den Elternknoten dieses Attributs liefert: @*[id(.) and count(id(.)|..)=1] |
Funktion: string local-name(node-set?)
Die Funktion local-name liefert den lokalen Teil des erweiterten Namens des ersten Knotens in der Argumentknotenmenge bezüglich der Dokumentordnung. Falls die übergebene Knotenmenge leer ist oder der erste Knoten keinen erweiterten Namen besitzt, wird eine leere Zeichenkette zurückgegeben. Wird kein Argument übergeben, wird stattdessen eine Knotenmenge mit dem Kontextknoten als einzigem Element benutzt.
Anmerkung des Übersetzers: Für Element- und Attributknoten gilt damit, dass die Funktion local-name den dem Doppelpunkt folgenden Teil des QName zurückgibt bzw. den vollständigen Namen, wenn dieser kein Präfix enthält. Die folgenden Beispiele demonstrieren dies unter der Voraussetzung, dass der als jeweiliges Argument übergebene Lokalisierungspfad nicht die leere Knotenmenge ergibt: local-name(xhtml:body) = "body" local-name(@xlink:href) = "href" local-name(para) = "para"
Für Namensraumknoten liefert local-name das
zugewiesene Präfix, also beispielsweise für die Deklaration
Für Processing Instructions liefert local-name
das jeweilige Ziel, also beispielsweise für
Für Textknoten, Kommentare und den Wurzelknoten liefert local-name die leere Zeichenkette. |
Funktion: string namespace-uri(node-set?)
Die Funktion namespace-uri liefert den Namensraum-URI des erweiterten Namens des ersten Knotens in der Argumentknotenmenge bezüglich der Dokumentordnung. Falls die übergebene Knotenmenge leer ist, der erste Knoten keinen erweiterten Namen besitzt oder der Namensraum-URI des erweiterten Namens leer ist, wird eine leere Zeichenkette zurückgegeben. Wird kein Argument übergeben, wird stattdessen eine Knotenmenge mit dem Kontextknoten als einzigem Element benutzt.
Anmerkung: Die von der Funktion namespace-uri zurückgegebene Zeichenkette ist außer für Element- oder Attributknoten immer leer.
Anmerkung des Übersetzers:
Beispiele:
|
Funktion: string name(node-set?)
Die Funktion name liefert eine Zeichenkette mit einem QName, die den erweiterten Namen des ersten Knotens in der Argumentknotenmenge bezüglich der Dokumentordnung repräsentiert. Der QName muss den erweiterten Namen unter Berücksichtigung der Namensraumdeklarationen repräsentieren, die für den Knoten gültig sind, dessen erweiterter Name repräsentiert wird. Typischerweise ist das der QName, der in der XML-Quelle vorkommt. Das muss nicht der Fall sein, wenn es für den Knoten Namensraumdeklarationen gibt, die dem gleichen Namensraum mehrere Präfixe zuordnen. Allerdings kann eine Implementation Informationen über das Originalpräfix speichern; in diesem Fall kann die Implementation sicherstellen, dass der zurückgegebene String immer der in der XML-Quelle benutzte QName ist. Falls die übergebene Knotenmenge leer ist oder der erste Knoten keinen erweiterten Namen besitzt, wird eine leere Zeichenkette zurückgegeben. Wird kein Argument übergeben, wird stattdessen eine Knotenmenge mit dem Kontextknoten als einzigem Element benutzt.
Anmerkung: Die von der Funktion name gelieferte Zeichenkette ist die gleiche wie die von der Funktion local-name gelieferte, außer für Element- und Attributknoten.
Anmerkung des Übersetzers: Für einen folgendermaßen definierten Elementknoten <x:foo xmlns:x="urn:bar" xmlns:y="urn:bar" />
darf die Funktion name damit
die Zeichenkette »
Die drei Funktionen local-name,
namespace-uri und name
werden in der folgenden Tabelle kurz zusammengefasst.
Das Zeichen »
Diese Funktionen erwarten als Argument zwar eine Knotenmenge, werten jedoch immer nur den ersten Knoten bezüglich der Dokumentordnung aus. Der zugrunde liegende Begriff erweiterter Name wird in Kapitel [5 Datenmodell] erläutert.
Über den Umweg, den Namen eines Knotens auszuwerten, lassen sich
Knotentests variabel beschreiben. Möchte man beispielsweise den Typ
eines Nachkommenelements parametrisieren, kann man nicht
descendant::*[local-name()=$lname and namespace-uri()=$uri] Für XML-Dokumente, die keinen Gebrauch von Namensräumen machen, reicht bereits ein Vergleich mit der von der Funktion name gelieferten Zeichenkette. |
Funktion: string string(object?)
Die Funktion string konvertiert ein Objekt wie folgt in eine Zeichenkette:
Eine Knotenmenge wird in eine Zeichenkette konvertiert, indem der Zeichenkettenwert des ersten Knotens in Dokumentordnung zurückgegeben wird. Falls die Knotenmenge leer ist, wird eine leere Zeichenkette zurückgegeben.
Anmerkung des Übersetzers: Der Zeichenkettenwert für jeden Knotentyp wird in Kapitel [5 Datenmodell] definiert. An dieser Stelle wird bereits zusammengefasst, welchen Wert die Funktion string abhängig vom jeweiligen Knotentyp zurückgibt.
|
Eine Zahl wird wie folgt in eine Zeichenkette konvertiert:
NaN (Not a Number – keine gültige Zahl) wird in die
Zeichenkette NaN
konvertiert.
Positiv Null wird in die Zeichenkette 0
konvertiert.
Negativ Null wird in die Zeichenkette 0
konvertiert.
Positiv unendlich wird in die Zeichenkette
Infinity
konvertiert.
Negativ unendlich wird in die Zeichenkette
-Infinity
konvertiert.
Falls die Zahl ein Integer ist, wird sie in dezimaler Form
als Number dargestellt, ohne Dezimalpunkt
und führende Nullen, mit negativem Vorzeichen (-
), falls
die Zahl negativ ist.
Ansonsten wird die Zahl in Dezimalform als Number dargestellt, einschließlich Dezimalpunkt,
wenigstens einer Ziffer vor und nach dem Dezimalpunkt sowie einem
negativen Vorzeichen (-
), falls die Zahl negativ ist.
Es dürfen keine führenden Nullen vor dem Dezimalpunkt auftreten mit
Ausnahme der eventuell erforderlichen Ziffer direkt vor dem
Dezimalpunkt. Abgesehen von der einen erforderlichen Ziffer nach dem
Dezimalpunkt müssen dort so viele, aber nicht mehr, Ziffern auftreten,
wie zur eindeutigen Unterscheidung von allen anderen IEEE 754
numerischen Werten notwendig sind.
Der boolesche Wert falsch wird in die Zeichenkette
false
konvertiert. Der boolesche Wert wahr wird in die
Zeichenkette true
konvertiert.
Die Konvertierung eines Objekts von einem anderen Typ als den vier Grundtypen hängt von diesem Typ ab.
Wird kein Argument übergeben, wird stattdessen eine Knotenmenge mit dem Kontextknoten als einzigem Element benutzt.
Anmerkung: Die Funktionstring
ist nicht dafür gedacht, Zahlen in Zeichenketten zu konvertieren, die an Nutzer ausgegeben werden. Die in [XSLT] definierte Funktionformat-number
und das ebenfalls dort definierte Elementxsl:number
stellen diese Funktionalität bereit.
Funktion: string concat(string, string, string*)
Die Funktion concat liefert die Verkettung ihrer Argumente.
Funktion: boolean starts-with(string, string)
Die Funktion starts-with liefert den logischen Wert wahr, falls die im ersten Argument übergebene Zeichenkette mit der im zweiten Argument übergebenen Zeichenkette beginnt, und andernfalls falsch.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz ergänzt werden: Wenn das zweite Argument die leere Zeichenkette ist, wird der Wert wahr zurückgegeben. |
Funktion: boolean contains(string, string)
Die Funktion contains liefert den logischen Wert wahr, falls die im ersten Argument übergebene Zeichenkette die im zweiten Argument übergebene Zeichenkette enthält, und andernfalls falsch.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz ergänzt werden: Wenn das zweite Argument die leere Zeichenkette ist, wird der Wert wahr zurückgegeben. |
Funktion: string substring-before(string, string)
Die Funktion substring-before liefert aus der
im ersten Argument übergebenen Zeichenkette die Teilzeichenkette,
die vor dem ersten Auftreten der im zweiten Argument übergebenen
Zeichenkette steht, bzw. die leere Zeichenkette, falls die erste
Zeichenkette nicht die zweite enthält. Zum Beispiel liefert
substring-before("1999/04/01","/")
das Ergebnis
1999
.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz ergänzt werden: Wenn das zweite Argument die leere Zeichenkette ist, wird die leere Zeichenkette zurückgegeben. |
Funktion: string substring-after(string, string)
Die Funktion substring-after liefert aus der
im ersten Argument übergebenen Zeichenkette die Teilzeichenkette,
die nach dem ersten Auftreten der im zweiten Argument übergebenen
Zeichenkette steht, bzw. die leere Zeichenkette, falls die erste
Zeichenkette nicht die zweite enthält. Zum Beispiel liefert
substring-after("1999/04/01","/")
das Ergebnis
04/01
und
substring-after("1999/04/01","19")
liefert
99/04/01
.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz ergänzt werden: Wenn das zweite Argument die leere Zeichenkette ist, wird die im ersten Argument übergebene Zeichenkette zurückgegeben. |
Funktion: string substring(string, number, number?)
Die Funktion substring liefert aus der im
ersten Argument übergebenen Zeichenkette die Teilzeichenkette,
die an der im zweiten Argument angegebenen Position beginnt und die
im dritten Argument angegebene Länge besitzt. Zum Beispiel liefert
substring("12345",2,3)
das Ergebnis "234"
.
Falls kein drittes Argument angegeben wird, liefert die Funktion die
Teilzeichenkette, die an der im zweiten Argument angegebenen Position
beginnt und bis zum Ende der Zeichenkette reicht. Zum Beispiel liefert
substring("12345",2)
das Ergebnis "2345"
.
Genauer gesagt wird für jedes Zeichen der Zeichenkette (siehe [3.6 Zeichenketten]) eine numerische Position angenommen: die Position des ersten Zeichens ist 1, die Position des zweiten Zeichens ist 2 usw.
Anmerkung: Dies unterscheidet sich von Java und ECMAScript, in denen die
Methode String.substring
die Position des ersten Zeichens
mit 0 definiert.
Die zurückgegebene Teilzeichenkette enthält die Zeichen, deren Position größer oder gleich dem gerundeten Wert des zweiten Arguments ist und, falls ein drittes Argument übergeben wurde, kleiner als die Summe des gerundeten Wertes des zweiten und des gerundeten Wertes des dritten Arguments. Vergleich und Addition folgen den Standardregeln von IEEE 754; die Rundung erfolgt wie durch die Funktion round. Die folgenden Beispiele illustrieren einige unübliche Fälle:
substring("12345", 1.5, 2.6)
liefert
"234"
substring("12345", 0, 3)
liefert
"12"
substring("12345", 0 div 0, 3)
liefert
""
substring("12345", 1, 0 div 0)
liefert
""
substring("12345", -42, 1 div 0)
liefert
"12345"
substring("12345", -1 div 0, 1 div 0)
liefert
""
Anmerkung des Übersetzers: Die letzten vier Beispiele werden plausibel, wenn man die Definition für substring wortgetreu anwendet und beachtet, dass ein Vergleich mit dem Wert NaN immer falsch sowie jede Gleitkommazahl kleiner als positiv unendlich ist.
Mit Hilfe eines ähnlich gearteten Aufrufs dieser Funktion können
bedingte Ausdrücke für Zeichenketten und damit auch Zahlen simuliert
werden. Ein bedingter Ausdruck liefert abhängig von der Auswertung
eines logischen Ausdrucks einen von zwei möglichen vorgegebenen Werten.
Für Knotenmengen wurde die analoge Funktionalität im Zusammenhang mit
dem Vereinigungsoperator Unter Ausnutzung der Tatsache, dass ein logischer Wert wahr nach 1 und ein logischer Wert falsch nach 0 konvertiert wird (siehe Regeln bei der Funktion number), ergibt der Ausdruck substring(string, 1 div boolean-test)
den Wert concat(substring(true-string, 1 div boolean-test), substring(false-string, 1 div not(boolean-test))) Solche Ausdrücke können beim Sortieren in XSLT eingesetzt werden, wenn der zu benutzende Sortierschlüssel von einer aktuell auszuwertenden Bedingung abhängt. Allerdings werden sie bei komplexeren Bedingungen schnell unübersichtlich. |
Funktion: number string-length(string?)
Die Funktion string-length liefert die Anzahl der Zeichen der Zeichenkette (siehe [3.6 Zeichenketten]). Falls kein Argument übergeben wurde, wird der in eine Zeichenkette konvertierte Kontextknoten angenommen, mit anderen Worten der Zeichenkettenwert des Kontextknotens.
Anmerkung des Übersetzers:
Es gibt in XPath keine Funktion $str2 = substring($str1, string-length($str1) - string-length($str2) + 1) Für das Auffüllen einer Zeichenkette von links mit Leerzeichen (z.B. für eine rechtsbündige Textausgabe) erweisen sich die Funktionen concat, substring und string-length sowie eine ausreichend lange, ausschließlich aus Leerzeichen bestehende Zeichenkette als gute Helfer: concat(substring(" ", 1, $width - string-length($eingabe)), $eingabe) |
Funktion: string normalize-space(string?)
Die Funktion normalize-space liefert als Ergebnis die übergebene Zeichenkette mit normalisiertem Leerraum zurück, d.h. führender und abschließender Leerraum werden entfernt, Folgen von mehreren Leerraumzeichen werden durch ein einzelnes Leerzeichen ersetzt. Leerraumzeichen sind jene, die durch die Produktion S in XML definiert sind. Falls kein Argument übergeben wurde, wird der in eine Zeichenkette konvertierte Kontextknoten angenommen, mit anderen Worten der Zeichenkettenwert des Kontextknotens.
Anmerkung des Übersetzers: Diese Funktion verarbeitet eine übergebene Zeichenkette in der gleichen Weise, wie ein XML-Prozessor nach Ersetzung aller Referenzen Nicht-CDATA-Attribute behandelt, siehe Kapitel 3.3.3 in [XML, 2nd Edition]. Zur Erläuterung sei das folgende Beispiel angegeben. Häufig finden sich in XML-Dokumenten Textdaten, die folgendermaßen ausgezeichnet sind: <name> Otto Normal </name>
Der Zeichenkettenwert des Elements .="Otto Normal" liefert also nicht das erhoffte Ergebnis, sondern schlägt fehl. Korrekt ist in diesem Fall stattdessen ein Vergleich mit dem normalisierten Wert des Knotens: normalize-space()="Otto Normal"
Am Beispiel normalize-space soll an dieser Stelle
vor einer Falle gewarnt werden, in die man bei der Übergabe von
Knotenmengen an Funktionen mit skalaren Parametertypen leicht geraten
kann. Angenommen, der Name .="Otto Normal" and not(preceding-sibling::name="Otto Normal") Muss man aber normalisieren, erweist sich der folgende Test als ungeeignet: normalize-space()="Otto Normal" and not(normalize-space(preceding-sibling::name)="Otto Normal")
Da die Funktion normalize-space als Argument eine
Zeichenkette erwartet, wird die übergebene Knotenmenge mit der Funktion
string konvertiert. Es wird also letztlich nur der
erste Knoten (bezüglich der
Dokumentordnung) der
übergebenen Knotenmenge durch normalize-space
ausgewertet und damit nur getestet, ob der erste
normalize-space()="Otto Normal" and not(preceding-sibling::name[normalize-space()="Otto Normal"]) |
Funktion: string translate(string, string, string)
Die Funktion translate liefert als Ergebnis
die im ersten Argument übergebene Zeichenkette, wobei jedes Vorkommen
eines Zeichens aus der im zweiten Argument übergebenen Zeichenkette
ersetzt wird durch das Zeichen an der korrespondierenden Position aus
der im dritten Argument übergebenen Zeichenkette. Zum Beispiel liefert
translate("bar","abc","ABC")
die Zeichenkette
BAr
. Wenn es im zweiten Argument ein Zeichen gibt, für das
kein korrespondierendes Zeichen im dritten Argument existiert (weil
das zweite Argument länger ist als das dritte), so werden alle
Vorkommen dieses Zeichens im ersten Argument entfernt. Zum Beispiel
liefert translate("--aaa--","abc-","ABC")
das Ergebnis
"AAA"
. Falls ein Zeichen mehrmals im zweiten Argument
vorkommt, bestimmt das erste Auftreten das Ersetzungszeichen. Falls
die im dritten Argument übergebene Zeichenkette länger ist als die
zweite, werden überzählige Zeichen ignoriert.
Anmerkung: Die Funktion translate ist keine ausreichende Lösung für die Umwandlung zwischen Groß- und Kleinschreibung in allen Sprachen. Eine zukünftige Version von XPath kann zusätzliche Funktionen für diese Umwandlung zur Verfügung stellen.
Anmerkung des Übersetzers: Für deutsche Umlaute reicht sie im Allgemeinen aus. Möchte man in einem Stylesheet an mehreren Stellen Klein- in Großschreibung umwandeln, bietet es sich an, geeignete Variablen zu definieren und fortan diese zu benutzen. In XSLT sähe das folgendermaßen aus: <xsl:variable name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ'" /> <xsl:variable name="lower-case" select="'abcdefghijklmnopqrstuvwxyzäöü'" /> ... <xsl:if test="translate(firma, $lower-case, $upper-case) = 'XYZ GMBH'"> ... </xsl:if> Allerdings stößt man schon beim Buchstaben »ß« an die Grenzen der Funktion translate. Die Ersetzung von »ß« durch die beiden Buchstaben »SS« ist auf diese Weise nicht möglich, weil der Ersetzungstext länger als ein Zeichen ist.
Allgemein gilt, dass die Funktion
translate kein Mittel zum Ersetzen von beliebigen
Teilzeichenketten ist. Ein einmaliges Ersetzen im Sinne von
concat(substring-before($string, $from), $to, substring-after($string, $from))
ausgedrückt werden. XPath 1.0 stellt keine Mittel bereit, alle Vorkommen
von
Mit der Funktion translate lassen sich
darüber hinaus sehr einfach ausgewählte Zeichen aus einer Zeichenkette
entfernen, indem als drittes Argument eine leere Zeichenkette übergeben
wird. Dies kann beispielsweise für den Test genutzt werden, ob eine
Zeichenkette translate($string, $allowed-char, "") = "" |
Funktion: boolean boolean(object)
Die Funktion boolean konvertiert ihr Argument wie folgt in einen Boolean-Wert:
Eine Zahl ergibt den Wert wahr genau dann, wenn sie weder positiv oder negativ Null noch NaN ist.
Eine Knotenmenge ergibt den Wert wahr genau dann, wenn sie nicht leer ist.
Anmerkung des Übersetzers:
Aus diesem Grund lässt sich ein Test auf das Vorhandensein von
Knoten sehr kompakt aufschreiben: |
Eine Zeichenkette ergibt genau dann den Wert wahr, wenn ihre Länge ungleich Null ist.
Anmerkung des Übersetzers:
Zum Vergleich mit dem letzten Beispiel:
|
Die Konvertierung eines Objekts von einem anderen Typ als den vier Grundtypen hängt von diesem Typ ab.
Anmerkung des Übersetzers: Während das Argument der Funktionen string und number optional ist, beim Fehlen damit der Kontextknoten angenommen wird, ist das Argument für die Funktion boolean obligatorisch. Eine analoge Definition, die gegebenenfalls auf den Kontextknoten zurückgreift, hätte auch nicht viel Sinn, da in diesem Fall die Funktion boolean den Wert wahr liefern müsste – der Kontextknoten ist schließlich immer vorhanden. |
Funktion: boolean not(boolean)
Die Funktion not liefert den Wert wahr, wenn ihr Argument falsch ist, und ansonsten falsch.
Anmerkung des Übersetzers:
Im Unterschied zu den Operatoren |
Die Funktion true liefert den Wert wahr.
Die Funktion false liefert den Wert falsch.
Anmerkung des Übersetzers: XPath definiert keine Literale für wahr und falsch. Soll ein boolescher Wert als Parameter an eine Funktion oder ein benanntes XSLT-Template übergeben werden, muss dafür eine der Funktionen true oder false benutzt werden. |
Funktion: boolean lang(string)
Die Funktion lang liefert einen Wert
wahr oder falsch in Abhängigkeit davon, ob
die durch xml:lang
-Attribute angegebene Sprache des
Kontextknotens die gleiche oder eine Untersprache der im Argument
übergebenen Zeichenkette ist. Die Sprache des Kontextknotens wird durch
den Wert des Attributes xml:lang
des Kontextknotens
bestimmt oder, wenn der Kontextknoten kein Attribut
xml:lang
besitzt, durch den Wert des Attributes
xml:lang
beim nächsten Vorfahren des Kontextknotens, der
ein Attribut xml:lang
besitzt. Wenn es kein solches
Attribut gibt, liefert lang den Wert
falsch. Wenn es ein solches Attribut gibt, liefert
lang den Wert wahr, wenn
der Attributwert gleich dem Argument ist, unabhängig von der
Groß- oder Kleinschreibung, oder wenn es ein mit -
beginnendes Suffix derart gibt, dass der Attributwert gleich dem
Argument ohne dieses Suffix ist, unabhängig von der Groß- oder
Kleinschreibung. Beispielsweise würde lang("en")
den
Wert wahr liefern, wenn es sich beim Kontextknoten um
eines dieser fünf Elemente handelt:
<para xml:lang="en"/> <div xml:lang="en"><para/></div> <para xml:lang="EN"/> <para xml:lang="en-us"/>
Anmerkung des Übersetzers:
Handelt es sich beim Kontextknoten dagegen um das
<div xml:lang="en"><sect xml:lang="de"><para/></sect></div>
liefert
Das Verhalten der Funktion lang darf nicht mit
einem impliziten Vorhandensein des Attributs |
Funktion: number number(object?)
Die Funktion number konvertiert ihr Argument wie folgt in eine Zahl:
Eine Zeichenkette, die aus optionalem Leerraum besteht, gefolgt von einem optionalen Minuszeichen, gefolgt von einer Number, gefolgt von Leerraum, wird in eine IEEE-754-Zahl konvertiert, die (entsprechend den Rundungsregeln in IEEE 754) dem mathematischen Wert am nächsten ist, der durch die Zeichenkette repräsentiert wird. Jede andere Zeichenkette wird in NaN konvertiert.
Der boolesche Wert wahr wird in 1 konvertiert; der boolesche Wert falsch wird in 0 konvertiert.
Eine Knotenmenge wird zunächst wie beim Aufruf der Funktion string in eine Zeichenkette konvertiert und anschließend in der gleichen Weise wie eine Zeichenkette konvertiert.
Die Konvertierung eines Objekts von einem anderen Typ als den vier Grundtypen hängt von diesem Typ ab.
Wird kein Argument übergeben, wird stattdessen eine Knotenmenge mit dem Kontextknoten als einzigem Element benutzt.
Anmerkung: Die Funktion number sollte nicht für die Konvertierung numerischer Daten in einem Element eines XML-Dokuments benutzt werden, es sei denn, das Element ist von einem Typ, der numerische Daten in einem sprachunabhängigen Format repräsentiert (das typischerweise für die Präsentation für einen Anwender in ein sprachspezifisches Format umgewandelt würde). Darüber hinaus kann die Funktion number nur genutzt werden, wenn das von dem Element genutzte sprachunabhängige Format mit der XPath-Syntax für Number konsistent ist.
Anmerkung des Übersetzers:
Insbesondere eignet sich eine Zahl im hiesigen Format (der Punkt zur
Kennzeichnung der Tausenderstellen, das Komma zur Abgrenzung von den
Dezimalstellen) nicht als Argument für die Funktion
number. Der Aufruf von
|
Funktion: number sum(node-set)
Die Funktion sum liefert die Summe aller in eine Zahl konvertierten Zeichenkettenwerte der Knoten aus der Argumentknotenmenge.
Anmerkung des Übersetzers: Sie eignet sich damit nur für Fälle, in denen die zu summierenden Werte direkt in der XML-Quelle vorliegen. Sollen die Summanden komplexer sein, d.h. jeweils durch einen eigenen Ausdruck berechnet werden, kann die Funktion sum nicht mehr benutzt werden. XPath nutzende Implementationen können aber eigene Sprachmittel bereitstellen, mit denen solche Berechnungen durchgeführt werden können.
Die Funktion sum hilft noch in einem anderen
Anwendungsfall: Aus der Definition des Verhaltens von
number geht hervor, dass letztere eine leere
Knotenmenge in den Wert NaN konvertiert. Ein Ausdruck
|
Funktion: number floor(number)
Die Funktion floor liefert die größte Zahl (die am nächsten an positiv unendlich liegt), die nicht größer als das Argument und ganzzahlig ist.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Absatz ergänzt werden: Wenn das Argument NaN ist, wird NaN zurückgegeben. Wenn das Argument positiv unendlich ist, wird positiv unendlich zurückgegeben. Wenn das Argument negativ unendlich ist, wird negativ unendlich zurückgegeben. Wenn das Argument positiv Null ist, wird positiv Null zurückgegeben. Wenn das Argument negativ Null ist, wird negativ Null zurückgegeben. Wenn das Argument größer als Null, aber kleiner als 1 ist, wird positiv Null zurückgegeben. |
Funktion: number ceiling(number)
Die Funktion ceiling liefert die kleinste Zahl (die am nächsten an negativ unendlich liegt), die nicht kleiner als das Argument und ganzzahlig ist.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Absatz ergänzt werden: Wenn das Argument NaN ist, wird NaN zurückgegeben. Wenn das Argument positiv unendlich ist, wird positiv unendlich zurückgegeben. Wenn das Argument negativ unendlich ist, wird negativ unendlich zurückgegeben. Wenn das Argument positiv Null ist, wird positiv Null zurückgegeben. Wenn das Argument negativ Null ist, wird negativ Null zurückgegeben. Wenn das Argument kleiner als Null, aber größer als -1 ist, wird positiv Null zurückgegeben. |
Funktion: number round(number)
Die Funktion round liefert die Zahl, die am nächsten am Argument liegt und die ganzzahlig ist. Wenn es zwei solche Zahlen gibt, wird die Zahl geliefert, die näher an positiv unendlich liegt. Ist das Argument NaN, wird NaN zurückgegeben. Ist das Argument positiv unendlich, wird positiv unendlich zurückgegeben. Ist das Argument negativ unendlich, wird negativ unendlich zurückgegeben. Ist das Argument positiv Null, wird positiv Null zurückgegeben. Ist das Argument negativ Null, wird negativ Null zurückgegeben. Ist das Argument kleiner als Null, aber größer oder gleich -0.5, wird negativ Null zurückgegeben.
Anmerkung: In den letzten beiden Fällen ist das Ergebnis des Aufrufs der Funktion round verschieden von der Addition von 0.5 und dem Aufruf der Funktion floor.
Anmerkung des Übersetzers: Davon kann man sich leicht selbst überzeugen:
Für -0 ergibt sich:
Für -0.5 ergibt sich: |
XPath operiert auf der Baumrepräsentation eines XML-Dokuments. Das folgende Kapitel beschreibt, wie XPath ein XML-Dokument als Baum modelliert. Dieses Modell ist rein konzeptionell und schreibt keinerlei spezielle Implementation vor. Die Beziehung zwischen diesem Modell und der XML-Informationsmenge [XML Infoset] wird in [B Abbildung auf die XML-Informationsmenge] beschrieben.
Die durch XPath verarbeiteten XML-Dokumente müssen sich nach der XML-Namensraum-Empfehlung [XML Names] richten.
Anmerkung des Übersetzers:
Insbesondere dürfen Namen von Elementen und Attributen das Zeichen
» |
Der Baum enthält Knoten. Es gibt sieben Typen von Knoten:
Wurzelknoten
Elementknoten
Textknoten
Attributknoten
Namensraumknoten
Processing-Instruction-Knoten
Kommentarknoten
Für jeden Knotentyp gibt es einen Weg, den Zeichenkettenwert eines Knotens dieses Typs zu bestimmen. Bei einigen Knotentypen ist der Zeichenkettenwert Teil des Knotens, bei anderen Knotentypen wird der Zeichenkettenwert aus den Zeichenkettenwerten der Nachkommen berechnet.
Anmerkung: Für Element- und Wurzelknoten ist der Zeichenkettenwert eines
Knotens verschieden von der Zeichenkette, die von der DOM-Methode
nodeValue
zurückgegeben wird (siehe [DOM]).
Einige Knotentypen besitzen außerdem einen erweiterten Namen – ein Paar bestehend aus einem lokalen Teil und einem Namensraum-URI. Der lokale Teil ist eine Zeichenkette. Der Namensraum-URI ist entweder leer oder eine Zeichenkette. Der im XML-Dokument spezifizierte Namensraum-URI kann eine URI-Referenz sein, wie sie in [RFC2396] definiert ist; das bedeutet, sie kann einen Fragment-Bezeichner besitzen und sie kann relativ sein. Ein relativer URI sollte als absoluter URI während der Namensraum-Verarbeitung aufgelöst werden: Die Namensraum-URIs der erweiterten Namen von Knoten im Datenmodell sollten absolut sein. Zwei erweiterte Namen sind gleich, wenn sie den gleichen lokalen Teil haben und wenn beide einen leeren Namensraum-URI oder beide die gleichen, nichtleeren Namensraum-URIs besitzen.
Anmerkung des Übersetzers: Nach einer Entscheidung des W3C-XML-Plenums ist die Behandlung relativer Namensraum-URIs implementationsabhängig. Gemäß Errata-Dokument [XPath Errata] müssen deshalb aus dem obigen Abschnitt die Sätze "Der im XML-Dokument spezifizierte Namensraum-URI kann eine URI-Referenz sein, wie sie in [RFC2396] definiert ist; das bedeutet, sie kann einen Fragment-Bezeichner besitzen und sie kann relativ sein. Ein relativer URI sollte als absoluter URI während der Namensraum-Verarbeitung aufgelöst werden: Die Namensraum-URIs der erweiterten Namen von Knoten im Datenmodell sollten absolut sein." ersetzt werden durch: Ein in einer Namensraumdeklaration spezifizierter Namensraum-Name in einem XML-Dokument ist eine URI-Referenz, wie sie in [RFC2396] definiert ist; das bedeutet, sie kann einen Fragment-Bezeichner besitzen und sie kann relativ sein. Die Namensraum-URI-Komponente eines erweiterten Namens ist implementationsabhängig, wenn der erweiterte Name aus einem QName expandiert wird, dessen Präfix durch eine Namensraumdeklaration mit einem relativen URI (mit oder ohne Fragment-Bezeichner) als Namensraum-Namen deklariert wurde. Ein XPath-Ausdruck, der vom Wert der Namensraum-URI-Komponente eines solchen erweiterten Namens abhängt, ist nicht interoperabel.
Relative URIs der Form » |
Es existiert eine Ordnung, die Dokumentordnung, die für alle Knoten im Dokument definiert ist und die zu der Ordnung korrespondiert, in der die ersten Zeichen der XML-Repräsentation aller Knoten in der XML-Repräsentation des Dokuments nach der Expandierung allgemeiner Entities stehen. Der Wurzelknoten ist demzufolge der erste Knoten. Elementknoten stehen vor ihren Kindern. Das bedeutet, die Dokumentordnung ordnet Elementknoten in der Reihenfolge ihrer Start-Tags im XML-Dokument (nach der Expandierung von Entities). Attribut- und Namensraumknoten eines Elements kommen vor den Kindern des Elements. Namensraumknoten erscheinen per Definition vor den Attributknoten. Die relative Ordnung innerhalb der Namensraumknoten ist implementationsabhängig. Die relative Ordnung innerhalb der Attributknoten ist implementationsabhängig. Die umgekehrte Dokumentordnung ist die Umkehrung der Dokumentordnung.
Anmerkung des Übersetzers: Damit ist für Attribut- und Namensraumknoten die Reihenfolge der Repräsentation im XML-Dokument unerheblich. Man darf an dieser Stelle nicht vergessen, dass die Elemente einer Knotenmenge trotzdem immer ungeordnet sind. Die Eigenschaft, die Knoten einer Menge in einer bestimmten Reihenfolge zu betrachten, gehört immer zu einer Operation oder Funktion, die auf dieser Menge ausgeführt wird. So konvertieren die Funktionen string, boolean und number bei einer gegebenen Knotenmenge immer den ersten Knoten bezüglich der Dokumentordnung. Entsprechend legen auf Ausdrücke angewandte Prädikate immer die Dokumentordnung zugrunde. Demgegenüber legt innerhalb eines Lokalisierungsschrittes immer die jeweilige Achse die für die dazugehörenden Prädikate relevante Ordnung fest. Nachdem eine Knotenmenge konstruiert wurde, ist sie (wieder) ungeordnet. Siehe dazu auch die entsprechende Anmerkung in Kapitel [3.3 Knotenmengen]. |
Wurzel- und Elementknoten besitzen eine geordnete Liste von Kindknoten. Mehrere Knoten haben niemals gemeinsame Kinder: Wenn ein Knoten von einem anderen Knoten verschieden ist, dann ist kein Kindknoten des einen Knotens mit einem der Kindknoten des anderen Knotens identisch. Jeder Knoten mit Ausnahme des Wurzelknotens besitzt genau einen Elternknoten, wobei dieser entweder ein Elementknoten oder der Wurzelknoten ist. Ein Wurzel- oder ein Elementknoten ist der Elternknoten jedes seiner Kindknoten. Die Nachkommen eines Knotens sind die Kinder des Knotens sowie die Nachkommen der Kinder des Knotens.
Anmerkung des Übersetzers: Die Bezeichnungen Eltern- und Kindknoten sind vielleicht nicht ganz glücklich. Jeder Knoten besitzt nämlich maximal einen Elternknoten. Daneben sind Attribut- und Namensraumknoten vergleichbar mit rebellierenden Teenagern, die im XPath-Datenmodell nicht als Kinder ihrer Element-Elternknoten betrachtet werden. |
Der Wurzelknoten ist die Wurzel des Baumes. Ein Wurzelknoten kommt nur als Wurzel des Baumes vor. Der Elementknoten für das Dokumentelement ist ein Kind des Wurzelknotens. Der Wurzelknoten hat als Kinder ebenfalls Processing-Instruction-Knoten und Kommentarknoten für Processing Instructions und Kommentare, die im Prolog oder hinter dem Ende des Dokumentelements auftreten.
Anmerkung des Übersetzers: Die Dokumenttyp-Deklaration ist kein Kind des Wurzelknotens. Sie kommt als solche an keiner Stelle im XPath-Datenmodell vor. So kann ein XSLT-Stylesheet keine Kopie der Dokumenttyp-Deklaration erzeugen. Ebenso werden innerhalb der Dokumenttyp-Deklaration auftretende Kommentare oder Processing Instructions nicht durch XPath-Knoten repräsentiert. |
Der Zeichenkettenwert des Wurzelknotens ergibt sich aus der Verkettung der Zeichenkettenwerte aller Textknoten in Dokumentordnung, die Nachkommen des Wurzelknotens sind.
Anmerkung des Übersetzers: Da außerhalb des Dokumentelements keine Textknoten auftreten dürfen, gilt also string(/) = string(/*) oder mit anderen Worten: Der Wurzelknoten und sein (einziger) Element-Kindknoten besitzen den gleichen Zeichenkettenwert. Diesen erhält man auch, wenn aus dem Eingabedokument jegliches Markup entfernt und nur die Zeichendaten behalten werden.
Zum Vergleich: Im Document Object Model [DOM] ist
der Wert des vergleichbaren Attributs |
Der Wurzelknoten hat keinen erweiterten Namen.
Anmerkung des Übersetzers:
Das bedeutet, dass die Funktionen name,
local-name und namespace-uri
als Ergebnis die leere Zeichenkette liefern. Das in DOM definierte
Attribut |
Für jedes Element im Dokument gibt es einen Elementknoten. Ein Elementknoten besitzt einen erweiterten Namen, der sich durch Expandierung des im Tag des Elements spezifizierten QName in Übereinstimmung mit der XML-Namensraum-Empfehlung [XML Names] ergibt. Der Namensraum-URI des erweiterten Namens des Elements ist leer, wenn der QName kein Präfix enthält und es keinen anwendbaren voreingestellten Namensraum gibt.
Anmerkung: In der im Anhang A.3 von [XML Names] verwendeten Notation entspricht der lokale Teil des erweiterten Namens dem Attributtype
des ElementsExpEType
; der Namensraum-URI des erweiterten Namens entspricht dem Attributns
des ElementsExpEType
und ist leer, wenn das Attributns
des ElementsExpEType
weggelassen wurde.
Die Kinder eines Elementknotens sind die enthaltenen Elementknoten, Kommentarknoten, Processing-Instruction-Knoten und Textknoten. Entity-Referenzen zu internen und externen Entities werden expandiert. Zeichenreferenzen werden aufgelöst.
Der Zeichenkettenwert eines Elementknotens ergibt sich aus der Verkettung der Zeichenkettenwerte aller Textknoten, die Nachkommen des Elementknotens in Dokumentordnung sind.
Anmerkung des Übersetzers: Damit gilt, dass der Zeichenkettenwert eines Elementknotens genauso als Verkettung der Zeichenkettenwerte seiner Element- und Textkinder in Dokumentordnung aufgefasst werden kann.
Zum Vergleich: Im Document Object Model [DOM] ist
dagegen der Wert des vergleichbaren Attributs |
Ein Elementknoten kann einen eindeutigen Bezeichner (ID) besitzen.
Dies ist der Wert des Attributes, das in der DTD mit dem Typ
ID
deklariert wurde. Keine zwei Elemente in einem
Dokument dürfen den gleichen eindeutigen Bezeichner besitzen. Falls
ein XML-Prozessor zwei Elemente in einem Dokument mit dem gleichen
eindeutigen Bezeichner meldet (was nur möglich ist, wenn das
Dokument ungültig ist), dann muss das zweite Element in Dokumentordnung
so behandelt werden, als habe es keinen eindeutigen Bezeichner.
Anmerkung: Wenn ein Dokument keine DTD besitzt, dann hat kein Element des Dokuments einen eindeutigen Bezeichner.
Anmerkung des Übersetzers: Für zwei oder mehr Elemente mit dem gleichen eindeutigen Bezeichner liefert die Funktion id nur den ersten Elementknoten in Dokumentordnung zurück. Da die Eigenschaft eines Attributes, eindeutiger Bezeichner zu sein, in der DTD deklariert wird, kann ohne DTD dieses Attribut nicht mehr erkannt werden. Das bedeutet, dass die Funktion id nach dem Entfernen der DTD aus dem Eingabedokument für jedes Argument nur noch die leere Knotenmenge liefert. Dies ist einer der wenigen Fälle, in denen die Existenz einer DTD sich auf die Auswertung eines XPath-Ausdrucks auswirkt. |
Jedes Element besitzt eine mit ihm verbundene Menge von Attributknoten; das Element ist der Elternknoten jedes dieser Attributknoten. Allerdings ist ein Attributknoten kein Kind seines Elternknotens.
Anmerkung: Dies unterscheidet sich vom DOM, welches ein Element nicht als Elternknoten seiner Attribute behandelt (siehe [DOM]).
Mehrere Elemente haben niemals gemeinsame Attributknoten: Wenn ein Elementknoten verschieden von einem anderen Elementknoten ist, dann ist kein Attributknoten des einen Elementknotens mit einem der Attributknoten eines anderen Elementknotens identisch.
Anmerkung: Der Operator=
testet, ob zwei Knoten den gleichen Wert haben, nicht ob es dieselben Knoten sind. Vergleicht man die Attribute von zwei verschiedenen Elementen mittels=
, so kann sich Gleichheit ergeben, obwohl diese nicht dieselben Knoten sind.
Anmerkung des Übersetzers:
Wert bedeutet hier wieder
Zeichenkettenwert.
Tatsächlich gilt die obige Anmerkung für alle Knoten, nicht nur für
Attribute. Um die Identität zweier Knoten zu überprüfen, kann man
sich beispielsweise der in Kapitel [3.3 Knotenmengen] im
Zusammenhang mit dem Operator |
Ein vorgegebenes Attribut wird genauso behandelt wie ein
spezifiziertes Attribut. Falls für einen Elementtyp ein Attribut in der
DTD deklariert wurde, der Vorgabewert jedoch als #IMPLIED
deklariert und das Attribut für das Element nicht angegeben
wurde, so enthält die Attributmenge des Elements keinen Knoten für
dieses Attribut.
Anmerkung des Übersetzers: Beispiel: <!DOCTYPE see [ <!ELEMENT see EMPTY> <!ATTLIST see access (public|restricted) "public" ref CDATA #IMPLIED > ]> <see />
In diesem Fall besitzt der einzige Elementknoten Das XPath-Datenmodell liefert keinerlei Informationen darüber, ob ein solches Attribut im Start-Tag eines Elements spezifiziert wurde oder nicht. Im zweiten Fall ändert sich im Falle des Entfernens der DTD die Baumrepräsentation des XML-Dokuments, da alle vorgegebenen, aber nicht spezifizierten Attribute wegfallen. |
Einige Attribute, wie xml:lang
und
xml:space
, besitzen die Semantik, dass sie für alle
Elemente gelten, die Nachkommen des Elements sind, das das Attribut
trägt, es sei denn, sie wurden in einer Instanz eines
Nachkommenelements durch das gleiche Attribut überschrieben. Das
wirkt sich allerdings nicht darauf aus, wo Attributknoten im Baum
vorkommen: Ein Element besitzt nur Attributknoten für die Attribute,
die explizit im Start-Tag oder Leeres-Element-Tag dieses Elements
angegeben wurden oder die in der DTD explizit mit einem Vorgabewert
deklariert wurden.
Anmerkung des Übersetzers:
Im Zusammenhang mit der Funktion lang wurde auf
diese Eigenschaft bereits hingewiesen. Ein Attribut
Damit liefert z.B. |
Ein Attributknoten hat einen erweiterten Namen und einen Zeichenkettenwert. Der erweiterte Name wird durch Expandierung des im Tag im XML-Dokument angegebenen QName in Übereinstimmung mit der XML-Namensraum-Empfehlung [XML Names] berechnet. Der Namensraum-URI des Attributnamens ist leer, falls der QName des Attributs kein Präfix enthält.
Anmerkung des Übersetzers: Entsprechend der XML-Namensraum-Empfehlung [XML Names] wirkt sich somit ein voreingestellter Namensraum im Gegensatz zu Elementknoten nicht auf Attribute ohne Präfix aus. |
Anmerkung: In der im Anhang A.3 von [XML Names] verwendeten Notation entspricht der lokale Teil des erweiterten Namens dem Attributname
des ElementsExpAName
; der Namensraum-URI des erweiterten Namens entspricht dem Attributns
des ElementsExpAName
und ist leer, wenn das Attributns
des ElementsExpAName
weggelassen wurde.
Ein Attributknoten besitzt einen Zeichenkettenwert. Dieser Zeichenkettenwert ist der durch die XML-Empfehlung [XML] spezifizierte normalisierte Wert. Ein Attribut, dessen normalisierter Wert eine Zeichenkette der Länge null ist, wird nicht gesondert behandelt: Es resultiert in einem Attributknoten, dessen Zeichenkettenwert eine Zeichenkette der Länge null ist.
Anmerkung des Übersetzers:
Normalisierung bedeutet, dass alle Entity- und Zeichenreferenzen
aufgelöst sowie alle Leerraumzeichen durch die gleiche Anzahl
Leerzeichen ersetzt werden. Ist der Attributtyp nicht
|
Anmerkung: Es ist möglich, dass Attribute mit Vorgabewerten in einer externen DTD oder einem externen Parameter-Entity deklariert werden. Die XML-Empfehlung verlangt nicht, dass ein XML-Prozessor eine externe DTD oder ein externes Parameter-Entity einliest, es sei denn, dieser ist validierend. Ein Stylesheet oder ein anderes Werkzeug, das annimmt, der XPath-Baum enthalte in einer externen DTD oder einem externen Parameter-Entity deklarierte Vorgabewerte, kann möglicherweise mit nicht-validierenden XML-Prozessoren nicht funktionieren.
Es gibt keine Attributknoten zu Attributen, die Namensräume deklarieren (siehe [XML Names]).
Anmerkung des Übersetzers:
Attribute mit dem Namen » |
Jedem Element ist eine Menge von Namensraumknoten zugeordnet, einer
für jedes einzelne Namensraum-Präfix, das für das Element gültig ist
(einschließlich des Präfixes xml
, das implizit durch die
XML-Namensraum-Empfehlung deklariert wird) und einer für den
voreingestellten Namensraum, falls einer für das Element gültig ist.
Das Element ist der Elternknoten
jedes dieser Namensraumknoten; ein Namensraumknoten ist allerdings
kein Kind seines Elternelements. Mehrere Elemente haben niemals
gemeinsame Namensraumknoten: Wenn ein Elementknoten verschieden von
einem anderen Elementknoten ist, dann ist kein Namensraumknoten des
einen Elementknotens mit einem der Namensraumknoten eines anderen
Elementknotens identisch. Das bedeutet, ein Element besitzt einen
Namensraumknoten:
für jedes Attribut des Elements, dessen Name mit
xmlns:
beginnt;
für jedes Attribut eines Vorfahrenelements, dessen Name
mit xmlns:
beginnt, es sei denn, das Element selbst oder
ein näherer Vorfahre deklariert das Präfix um;
für ein xmlns
-Attribut, falls das Element oder ein
Vorfahre ein xmlns
-Attribut besitzt und der Wert des
xmlns
-Attributs beim nächsten dieser Elemente nicht leer
ist.
Anmerkung: Ein Attribut xmlns=""
"undeklariert"
den voreingestellten Namensraum (siehe
[XML Names]).
Anmerkung des Übersetzers:
Namensraumdeklarationen wirken sich damit in der Regel auf die
Nachkommen des Elements aus, in dem diese Deklaration erscheint.
Im Gegensatz zu den Attributen
Wie bereits in Kapitel [1 Einleitung] an einem Beispiel
verdeutlicht wurde, folgt aus der Namensraum-Empfehlung, dass jedes
Element wenigstens einen Namensraumknoten mit dem Präfix
Da das XPath-Datenmodell keine Informationen darüber enthält, an welchen Stellen Namensraumdeklarationen im Dokument auftreten, besitzen die Beispiele <foo:e1 xmlns:foo="bar"><foo:e2 /></foo:e1> und <foo:e1 xmlns:foo="bar"><foo:e2 xmlns:foo="bar" /></foo:e1> die gleiche Baumrepräsentation. |
Ein Namensraumknoten besitzt einen erweiterten Namen: Der lokale Teil ist das Namensraum-Präfix (dieses ist leer, falls der Namensraumknoten den voreingestellten Namensraum repräsentiert); der Namensraum-URI ist immer leer.
Der Zeichenkettenwert eines Namensraumknotens ist der Namensraum-URI, der an das Namensraum-Präfix gebunden ist. Wenn dieser relativ ist, muss er wie ein Namensraum-URI in einem erweiterten Namen aufgelöst werden.
Anmerkung des Übersetzers: Nach einer Entscheidung des W3C-XML-Plenums ist die Behandlung relativer Namensraum-URIs implementationsabhängig. Gemäß Errata-Dokument [XPath Errata] muss dieser letzte Absatz durch den folgenden ersetzt werden: Der Zeichenkettenwert eines Namensraumknotens ist der Namensraum-URI, der an das Namensraum-Präfix gebunden ist; wenn der in der Namensraumdeklaration auftretende Namensraum-Name ein relativer URI (mit oder ohne Fragment-Bezeichner) ist, so ist der Zeichenkettenwert implementationsabhängig. Ein XPath-Ausdruck, der vom Zeichenkettenwert eines solchen Namensraumknotens abhängt, ist nicht interoperabel. Die Definition des erweiterten Namens für Namensraumknoten mag auf den ersten Blick etwas ungewöhnlich erscheinen. Tatsächlich wurde hier das Namensraum-Präfix als eigentlich relevanter Namensbestandteil dem Schema für erweiterte Namen angepasst, den jeder Knoten besitzt. Der Namensraum-URI des Namens ist leer, da der Name eines Namensraumknotens nicht von anderen gültigen Namensraumdeklarationen abhängt.
Zur Illustration zwei Beispiele: Die Deklaration
Namensraumknoten werden benötigt, wenn in den Daten enthaltene
qualifizierte Namen ausgewertet werden sollen. Die Typangabe in einem
XML-Schema ist so ein Beispiel: string(namespace::*[name()=substring-before(../@type,':')]) Da der Namensraumknoten für den voreingestellten Namensraum einen leeren Namen besitzt und daher nicht direkt als Knotentest angegeben werden kann, lässt sich ein solcher Knoten nur mit Hilfe eines geeigneten Prädikats auswählen: namespace::*[name()=''] |
Für jede Processing Instruction gibt es einen Processing-Instruction-Knoten, mit Ausnahme der Processing Instructions, die innerhalb der Dokumenttyp-Deklaration erscheinen.
Eine Processing Instruction besitzt einen erweiterten Namen: Der lokale Teil
ist das Ziel der Processing Instruction; der Namensraum-URI ist leer.
Der Zeichenkettenwert eines
Processing-Instruction-Knotens ist der Teil der Processing Instruction,
der dem Ziel und allem Leerraum folgt. Dieser beinhaltet nicht das
abschließende ?>
.
Anmerkung des Übersetzers: Die folgende Processing Instruction <?xml-stylesheet href='style.xsl' title='Hauptstylesheet'?>
wird z.B. durch einen Knoten repräsentiert, dessen
erweiterter Name
[»
Die Abschnitte, die hier wie Attribute einer Processing Instruction
aussehen ( Namensraumdeklarationen wirken sich nicht auf Processing Instructions aus. |
Anmerkung: Die XML-Deklaration ist keine Processing Instruction. Daher gibt es auch keinen Processing-Instruction-Knoten für die XML-Deklaration.
Anmerkung des Übersetzers: Es ist nicht möglich, auf die Angaben innerhalb der XML-Deklaration zuzugreifen. Die Versionsnummer und die Kodierungsangabe gehören nicht zum XPath-Datenmodell. |
Für jeden Kommentar gibt es einen Kommentarknoten, mit Ausnahme der Kommentare, die innerhalb der Dokumenttyp-Deklaration erscheinen.
Der Zeichenkettenwert eines
Kommentarknotens ist der Inhalt des Kommentars ohne die öffnenden
Zeichen <!--
und die schließenden Zeichen
-->
.
Ein Kommentarknoten besitzt keinen erweiterten Namen.
Anmerkung des Übersetzers:
Das bedeutet, dass die Funktionen name,
local-name und namespace-uri
als Ergebnis die leere Zeichenkette liefern. Das in DOM definierte
Attribut |
Zeichendaten werden in Textknoten zusammengefasst. Dabei werden so viele Zeichen wie möglich in jedem Textknoten zusammengefasst: Ein Textknoten hat niemals als direkten Vorgänger oder Nachfolger einen anderen Textknoten. Der Zeichenkettenwert eines Textknotens besteht aus den Zeichendaten. Ein Textknoten enthält immer wenigstens ein Zeichen.
Jedes Zeichen innerhalb eines CDATA-Abschnittes wird wie
Zeichendaten behandelt. So wird
<![CDATA[<]]>
im Quelldokument genauso behandelt
wie <
. Beides ergibt das einzelne Zeichen
<
in einem Textknoten innerhalb des Baumes. Ein
CDATA-Abschnitt wird damit so behandelt, als würden
<![CDATA[
und ]]>
entfernt und jedes
Vorkommen von <
und &
durch
<
bzw. &
ersetzt
werden.
Anmerkung des Übersetzers:
Das XPath-Datenmodell enthält also keinerlei Informationen darüber, in
welcher Form ein Zeichen innerhalb des XML-Dokuments repräsentiert
war. Die folgenden Textinhalte des Elements <x>A</x> <x><![CDATA[A]]></x> <x>A</x> <x>A</x>
Entsprechend würde beispielsweise der Inhalt des folgenden Elements
<para> Hier folgen Beispiel & Erklärung: <![CDATA[a > 10 and a < 20]]> bedeutet ... </para> Einzelne Zeichendaten werden innerhalb des Datenmodells nicht separat repräsentiert. Zur Verarbeitung muss deshalb auf die bereitgestellten Zeichenkettenfunktionen zurückgegriffen werden. |
Anmerkung: Wird ein Textknoten, der das Zeichen<
enthält, als XML ausgegeben, so muss das Zeichen<
geschützt werden, beispielsweise durch<
oder durch Einschluss in einen CDATA-Abschnitt.
Zeichen innerhalb von Kommentaren, Processing Instructions und
Attributwerten erzeugen keine Textknoten. Zeilenenden in externen
Entities werden zu #xA
normalisiert, so wie in der
XML-Empfehlung [XML] spezifiziert.
Anmerkung des Übersetzers: Gemäß Errata-Dokument [XPath Errata] muss an dieser Stelle folgender Satz eingefügt werden: Leerraum außerhalb des Dokumentelements erzeugt keine Textknoten.
Genau genommen lässt sich durch XPath nicht beeinflussen, ob Leerraum
generell Textknoten erzeugen soll. Abhängig von der Applikation, die
XPath verwendet, werden für ausschließlich aus Leerraum bestehende
Bereiche Textknoten angelegt oder nicht. Die Illustration zum Beispiel
in Kapitel [1 Einleitung] beruht auf der Annahme, dass
solche Leerraum-Textknoten vorhanden sind. Das ist auch das
Standardverhalten in XSLT [XSLT] für zu verarbeitende
XML-Dokumente. Durch Verwendung der XSLT-Elemente
Die Existenz solcher Leerraum-Textknoten kann sich auf Kontextgröße
und -position und damit auf das Ergebnis der Funktionen
last, position und
count auswirken. Die Berechnung des Ausdrucks
<name> <anrede>Herr</anrede> Müller-Lüdenscheidt </name> |
Ein Textknoten besitzt keinen erweiterten Namen.
Anmerkung des Übersetzers:
Das bedeutet, dass die Funktionen name,
local-name und namespace-uri
als Ergebnis die leere Zeichenkette liefern. Das in DOM definierte
Attribut |
XPath ist in erster Linie als Komponente gedacht, die von anderen Spezifikationen genutzt werden kann. Demzufolge überlässt es XPath den Spezifikationen, die XPath nutzen (etwa [XPointer] und [XSLT]), Kriterien für die Konformität von XPath zu spezifizieren und definiert selbst keinerlei Konformitätskriterien für unabhängige XPath-Implementationen.
Anmerkung des Übersetzers: Die Organisation Oasis hat eine Kommission für die Konformität von XSLT- und XPath-Implementationen [XSLT-Konformität] gebildet, die geeignete Szenarien für eine Test-Suite zusammenstellt. |
Die Knoten im XPath-Datenmodell lassen sich aus den durch die XML-Informationsmenge [XML Infoset] bereitgestellten Informationseinheiten wie folgt ableiten.
Anmerkung: Eine neue Version des Arbeitsentwurfs der XML-Informationsmenge, die die Version vom 17. Mai (1999, der Übersetzer) ersetzen wird, war zu der Zeit, als die Vorbereitung dieser Version der XPath-Spezifikation vollendet wurde, kurz vor der Fertigstellung. Ihre Veröffentlichung wurde zur gleichen Zeit oder kurz nach Veröffentlichung dieser Version von XPath erwartet. Die Abbildung wird für diese neue Version des Arbeitsentwurfs der XML-Informationsmenge angegeben. Falls die neue Version des Arbeitsentwurfs der XML-Informationsmenge noch nicht veröffentlicht worden sein sollte, können W3C-Mitglieder die interne Arbeitsgruppenversion http://www.w3.org/XML/Group/1999/09/WD-xml-infoset-19990915.html (nur für Mitglieder) einsehen.
Anmerkung des Übersetzers: Die XML-Informationsmenge beschreibt die aus einem XML-Dokument ableitbaren Informationen auf einer abstrakten Ebene. Zu diesem Zweck wurden elf Typen, so genannte Informationseinheiten (information items) definiert. Jede dieser Informationseinheiten besitzt eine Reihe von Eigenschaften (properties). Es wurde in der XML-Informationsmenge bewusst nicht der Term "Knoten" verwendet, um Verwechslungen mit DOM- und XPath-Knoten zu vermeiden. Die im XPath-Datenmodell definierten Knotentypen beschreiben eine Teilmenge der in der XML-Informationsmenge verfügbaren Informationen und lassen sich daher aus diesen Informationseinheiten ableiten. Die XML-Informationsmenge ist am 24. Oktober 2001 als W3C-Empfehlung verabschiedet worden. Im Vergleich zu der hier angesprochenen Version vom Dezember 1999 haben sich einige Details geändert. Die sich daraus ergebenden Änderungen bei der Abbildung des XPath-Datenmodells werden im Folgenden in den jeweiligen Anmerkungen angegeben. |
Der Wurzelknoten folgt aus der Dokument-Informationseinheit. Die Kinder des Wurzelknotens folgen aus den Eigenschaften children und children - comments.
Anmerkung des Übersetzers: Die Eigenschaft children - comments gibt es nicht mehr. Stattdessen folgen mögliche Kommentar-Kindknoten des Wurzelknotens ebenfalls unmittelbar aus der Eigenschaft children. |
Ein Elementknoten folgt aus einer Element-Informationseinheit.
Die Kinder eines Elementknotens folgen aus den Eigenschaften children und children - comments. Die Attribute eines
Elementknotens folgen aus der Eigenschaft attributes. Die Namensräume eines
Elementknotens folgen aus der Eigenschaft in-scope namespaces. Der lokale Teil
des erweiterten Namens
eines Elementknotens folgt aus der Eigenschaft local name. Der Namensraum-URI des
erweiterten Namens eines
Elementknotens folgt aus der Eigenschaft namespace URI. Der eindeutige Bezeichner
(ID) eines Elementknotens folgt aus der Eigenschaft children der
Attribut-Informationseinheit in der Eigenschaft attributes, deren Eigenschaft attribute type gleich ID
ist.
Anmerkung des Übersetzers:
Die Eigenschaft children - comments
gibt es nicht mehr. Stattdessen folgen mögliche Kommentar-Kindknoten
eines Elementknotens ebenfalls unmittelbar aus der Eigenschaft
children.
Der Namensraum-URI des erweiterten
Namens eines Elementknotens folgt aus der Eigenschaft namespace name.
Der eindeutige Bezeichner (ID) eines Elementknotens folgt aus der
Eigenschaft normalized value der
Attribut-Informationseinheit in der Eigenschaft attributes, deren Eigenschaft attribute type gleich |
Ein Attributknoten folgt aus einer Attribut-Informationseinheit. Der lokale Teil des erweiterten Namens des Attributknotens folgt aus der Eigenschaft local name. Der Namensraum-URI des erweiterten Namens des Attributknotens folgt aus der Eigenschaft namespace URI. Der Zeichenkettenwert des Knotens folgt aus der Verkettung aller Eigenschaften character code jedes Bestandteils der Eigenschaft children.
Anmerkung des Übersetzers: Der Namensraum-URI des erweiterten Namens eines Attributknotens folgt aus der Eigenschaft namespace name. Der Zeichenkettenwert des Knotens folgt aus der Eigenschaft normalized value. Attributwerte werden gemäß der aktuellen Version der XML-Informationsmenge nicht weiter in einzelne Zeichen-Informationseinheiten zerlegt. |
Ein Textknoten folgt aus einer Folge einer oder mehrerer aufeinander folgender Zeichen-Informationseinheiten. Der Zeichenkettenwert des Knotens folgt aus der Verkettung der Eigenschaften character code aller Zeichen-Informationseinheiten.
Ein Processing-Instruction-Knoten folgt aus einer Processing-Instruction-Informationseinheit. Der lokale Teil des erweiterten Namens des Knotens folgt aus der Eigenschaft target. (Der Teil Namensraum-URI des erweiterten Namens des Knotens ist leer.) Der Zeichenkettenwert des Knotens folgt aus der Eigenschaft content. Es gibt keine Processing-Instruction-Knoten für Processing-Instruction-Informationseinheiten, die Kinder der Dokumenttyp-Deklarations-Informationseinheit sind.
Ein Kommentarknoten folgt aus einer Kommentar-Informationseinheit. Der Zeichenkettenwert des Knotens folgt aus der Eigenschaft content. Es gibt keine Kommentarknoten für Kommentar-Informationseinheiten, die Kinder der Dokumenttyp-Deklarations-Informationseinheit sind.
Ein Namensraumknoten folgt aus einer Namensraumdeklarations-Informationseinheit. Der lokale Teil des erweiterten Namens des Knotens folgt aus der Eigenschaft prefix. (Der Teil Namensraum-URI des erweiterten Namens des Knotens ist leer.) Der Zeichenkettenwert des Knotens folgt aus der Eigenschaft namespace URI.
Anmerkung des Übersetzers: Ein Namensraumknoten folgt aus einer Namensraum-Informationseinheit. Der Zeichenkettenwert des Knotens folgt aus der Eigenschaft namespace name. |
Zusätzliche Referenzen der deutschen Übersetzung
|