
Abfragen mit XPATH
Relative und absolute Pfade
XPATH Achsen
Die Achse ancestor
Die Ache ancestor-or-self
Die Aches descendant
Die Achse descendant-or-self
Die Achse following
Die Achse following-sibling
Die Achse preceding
Die Achse preceding-sibling
Präziserer Zugriff mit position und last
Auf bestimmte Elemente innerhalb einer Achse
zugreifen
Arbeitem mit Prädikaten
Gleichnamige Elemente finden, die auf unterschiedlichen
Hierarchiestufen liegen
or in einem XPATH Ausdruck
Zeichenkettenfunktionen
Verbinden von Zeichenketten: concat()
Überprüfen, ob ein Zeichenkette Bestandteil
einer anderen Zeichenkette ist
Die Länge von Zeichenketten ermitteln:string-length()
Testen, ob eine Zeichenkette mit einer bestimmten
Zeichenkette beginnt
Zeichenketten aus einer Zeichenkette rausschneiden:
substring()
Alle Zeichen vor bzw. nach einem bestimmten
Zeichen rausfischen: substring-before() und substring-after()
Funktionen zum Ermitteln von Knoteneigenschaften
Ermitteln des letzten Knotens, last()
Die Funktion count()
XPATH ist, wenn man will, das sql für
XML Dokumente. Mit XPATH kann auf beliebige Knoten eines XML
Dokumentes zugegriffen werden. XPATH ist die Abfragesprache
von XSLT, wird aber von verschiedenen Parsern unterstützt,
die eigentlich auf den DOM Standard aufsetzen. Um die Möglichkeiten
von XPATH aufzuzeigen, gehen wir von dem XML Dokument aus,
dass schon dem ganzen Handbuch zugrunde liegt.
<?xml version="1.0" encoding="ISO-8859-1"?>
<Projekte>
<Gruppe>
<Gruppenname stand="abgeschifft">Berliner
Verwaltungsreform</Gruppenname>
<Kollegen>
<Mitarbeiter Summe="90000" Firma="Preis
Wasserhaus">Werner Lepinski</Mitarbeiter>
<Mitarbeiter Firma="Schitag Ernst und Jung" status="ausgeliehen"
Summe="20000">Erika Saufwech</Mitarbeiter>
<Mitarbeiter Summe="27000">Hans Geldfliech</Mitarbeiter>
</Kollegen>
<Ansprechpartner Telefon="030-435555" Ident="A_1">Otto
Moltoimportante</Ansprechpartner>
<Adresse>
<Strasse Gegend="teures Pflaster">Kurfürstendamm
5</Strasse>
<Ort>13453 Berlin</Ort>
</Adresse>
<Budget>40 000000</Budget>
<Kommentar>Alles wird gut</Kommentar>
</Gruppe>
<Gruppe>
<Gruppenname>Hamburger Verwaltungschaos </Gruppenname>
<Kollegen>
<Mitarbeiter Firma="Arthur der Kleine" Summe="30000">Werner
Nordflut</Mitarbeiter>
<Mitarbeiter Firma="Wertarbeit" status="ausgeliehen"
Summe="40000">Marina Meimportauncarajo</Mitarbeiter>
<Mitarbeiter Firma="Preis Wasserhaus" Summe="70000"
status="ausgeliehen">Peter Wessnich</Mitarbeiter>
</Kollegen>
<Ansprechpartner Ident="A_2">Ludwig Noresponsable</Ansprechpartner>
<Adresse>
<Strasse>An der Waterkant 15</Strasse>
<Ort>45555 Hamburg</Ort>
</Adresse>
<Kostenvoranschlag>30 000000</Kostenvoranschlag>
</Gruppe>
<Team>
<Name>Controlling</Name>
<Mitarbeiter>Werner Bummerang</Mitarbeiter>
<Ansprechpartner>Werner Kostfix</Ansprechpartner>
<Telefon>030-4544332</Telefon>
</Team>
</Projekte>
Um XPATH in Aktion zu zeigen, brauchen
wir des weiteren einen Ansatz, der XPATH verwendet. Der hinsichtlich
Implementierung einfachste Ansatz ist XSLT mit dem Saxon Prozessor.
Für Details siehe Auslesen eines
XML Dokumentes mit XSLT. Diesen verwenden wir. Wer sehen
will, wie man XPATH auch bei Verwendung des DOM Ansatzes verwendet,
kann zu dem Kapitel Auslesen einer
XML Datei mit dem Perl Modul XML::LIBXML gehen. Eine grundlegende
Ahnung von XSLT, siehe Auslesen eines
XML Dokumentes mit XSLT, ist sinnvoll. Um den Wurzelknoten
abzugreifen geben wir einfach einen Slash ein.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="name(node())"/>
</xsl:template>
</xsl:stylesheet>
Kopieren wir dieses Stylesheet und die
dazugehörige XML Datei in den Ordner wo auch die saxon.exe
liegt und geben dann
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
So erhalten wir als Ergebnis Projekte.
Mit der Funktion name() können wir uns den Namen des
als Parameter übergebenen Knotens anschauen. node() ermittelt
den aktuellen Knoten. Den aktuellen Knoten ermittelt aber
auch der schnöde Punkt, so dass wir auch sowas hätten
schreiben können.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:value-of select="name(.)"/>
</xsl:template>
</xsl:stylesheet>
Da die Funktion name() aber eh im Default
den Kontextknoten zeigt, hätte man auch sowas schreiben
können.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
Alle drei Varianten liefern Projekte,
also den aktuellen Knoten.
Relative
und absolute Pfade |
|
Ein absoluter Pfad beginnt mit einem Slash.
Das hatten wir oben. Ein absoluter Pfad ist ein Pfad, der
an der Wurzel startet. Relative Pfade starten beim aktuellen
Kontextknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe"/>
</xsl:template>
<xsl:template match="Gruppe">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet
Wir erhalten zweimal Gruppe, weil es zwei
Elemente Gruppe gibt und foglich das Template Gruppe zweimal
aufgerufen wird.
Will man alle Mitarbeiter sehen, könnte
man das, wie bereits oben beschrieben, so machen. Allerdings
würden so nur die Mitarbeiter im Element Gruppe erfasst.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe/Kollegen/Mitarbeiter"/>
</xsl:template>
<xsl:template match="Mitarbeiter">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
Alternativ, und manchmal ist das sinnvoll,
könnte man es auch so machen. Bei dieser Methode
werden alle Mitarbeiter erfasst, auch die im Element Team.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe/Kollegen/child::*"/>
</xsl:template>
<xsl:template match="child::*">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
Wir erhalten wieder 6 Mal Mitarbeiter. Mit
Achsen kann man von ausgehend vom aktuellen Knoten nach rechts,
links, oben und unten wandern.
Mit der Achse ancestor holen wir, ausgehend
von dem Kontextknoten, alle Elemente bis zum Wurzelknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team/Ansprechpartner"/>
</xsl:template>
<xsl:template match="Ansprechpartner">
<xsl:for-each select="ancestor::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Projekte Team, weil das der Opa
und der Vater des aktuellen Knotens Ansprechpartner in Team
ist.
Die
Ache ancestor-or-self |
|
Die Achse ancestor-or-self ist mit der
Achse ancestor weitgehend identisch, der einzige Unterschied
besteht darin, dass ancestor-or-self auch den Kontextknoten
selber mit erfasst.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team/Ansprechpartner"/>
</xsl:template>
<xsl:template match="Ansprechpartner">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Projekte Team Ansprechpartner.Der
Stern * steht hier für alle Elemente.
Mit der Achse descendant kann man alle
Knoten unterhalb des Kontextknotens erfassen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team"/>
</xsl:template>
<xsl:template match="Team">
<xsl:for-each select="descendant::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Name Ansprechpartner Telefon, weil
diese Unterhalb von Team liegen.
Die
Achse descendant-or-self |
|
Die Achse descendant-or-self erfasst alle direkten
Kindknoten und den Kontextknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team"/>
</xsl:template>
<xsl:template match="Team">
<xsl:for-each select="descendant-or-self::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Team Name Ansprechpartner
Telefon
Die Achse following erfasst alle Knoten
rechts vom Kontextknoten und die Kindknoten dieser Knoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]"/>
</xsl:template>
<xsl:template match="Gruppe[1]">
<xsl:for-each select="following::*">
Name <xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Name Gruppe
Name Gruppenname
Name Kollegen
Name Mitarbeiter
Name Mitarbeiter
Name Mitarbeiter
Name Ansprechpartner
Name Adresse
Name Strasse
Name Ort
Name Kostenvoranschlag
Name Team
Name Name
Name Ansprechpartner
Name Telefon
C:\saxon2>
Wir sehen dass wir die Gruppe erhalten, das
ist der Knoten rechts des Kontextknotens und alle Kindknoten.
Weiter erhalten wir auch den Schwesternknoten Team und dessen
Kindknoten.
Die
Achse following-sibling |
|
Die Achse following-sibling erfasst ebenfalls
die Schwesterknoten rechts vom Kontextknoten, allerdings ohne
deren Kindknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]"/>
</xsl:template>
<xsl:template match="Gruppe[1]">
<xsl:for-each select="following-sibling::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Gruppe Team.
Die Achse preceding liefert alle Schwesternknoten
links vom Kontextknoten und die Kindknoten dieser Schwesterknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team"/>
</xsl:template>
<xsl:template match="Team">
<xsl:for-each select="preceding::*">
Name <xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0"
encoding="utf-8"?>
Name Gruppe
Name Gruppenname
Name Kollegen
Name Mitarbeiter
Name Mitarbeiter
Name Mitarbeiter
Name Ansprechpartner
Name Adresse
Name Strasse
Name Ort
Name Budget
Name Kommentar
Name Gruppe
Name Gruppenname
Name Kollegen
Name Mitarbeiter
Name Mitarbeiter
Name Mitarbeiter
Name Ansprechpartner
Name Adresse
Name Strasse
Name Ort
Name Kostenvoranschlag
C:\saxon2>
Die Achse preceding-sibling |
|
Die Achse preceding-sibling erfasst alle Schwesternknoten
links vom Kontextknoten allerdings ohne deren Kindknoten.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team"/>
</xsl:template>
<xsl:template match="Team">
<xsl:for-each select="preceding-sibling::*">
<xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Gruppe Gruppe.
Präziserer Zugriff mit position und last |
|
Mit preceding, preceding-sibling, descendant,
descendant-sibling, following, following-sibling und ancestor
bzw. ancestor-self haben wir immer nur eine ganze Gruppe von
Knoten erhalten. Was ist, wenn man nur den ersten Schwesternknoten
rechts, links, oberhalb oder unterhalb des Kontextknotens
haben will ? Dies kann man erreichen mit position.
Schwersternknoten und dessen Kindknoten
unmittelbar rechts vom Kontextknoten erfassen
Wenn die erste Gruppe der Kontextknoten ist, und wir die zweite
Gruppe erfassen wollen, können wir sowas machen.
<?xml version="1.0"
encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]"/>
</xsl:template>
<xsl:template match="Gruppe[1]">
<xsl:for-each select="following-sibling::*[position()=1]">
<xsl:for-each select="descendant::*">
Name <xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten sowas und das ist korrekt.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Name Gruppenname
Name Kollegen
Name Mitarbeiter
Name Mitarbeiter
Name Mitarbeiter
Name Ansprechpartner
Name Adresse
Name Strasse
Name Ort
Name Kostenvoranschlag
C:\saxon2>
Schwierig einzusehen sind hierbei die verschachtelten
for-each Schleifen. Mit following-sibling::*[position()=1]
erfassen wir den unmittelbar rechts folgenden Schwesternknoten,
also die zweite Gruppe. Die zweite for-each Schleife geht
von diesem Kontextknoten aus und erfasst mit descendant::*
alle Kindsknoten dieses Schwesternknoten. Innerhalb dieser
zweiten for-each Schleife lassen wir uns dann alle Kindknoten
zeigen. Hätten wir das Team erfassen wollen, hätten
wir statt following-sibling::*[postion()=1] eben following-sibling::*[postion()=2]
geschrieben etc.
Den letzten Schwesternknoten und dessen
Kindknoten erfassen
Will man den letzten Schwesternknoten erfassen, kann man so
was machen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]"/>
</xsl:template>
<xsl:template match="Gruppe[1]">
<xsl:for-each select="following-sibling::*[last()]">
<xsl:for-each select="descendant::*">
Name <xsl:value-of select="name()"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten sowas, was tatsächlich das
Element Team wiederspiegelt.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Name Name
Name Ansprechpartner
Name Telefon
C:\saxon2>
Auf bestimmte Elemente innerhalb einer Achse zugreifen |
|
Wenn man weiss, wie das Element heisst, auf
dass man zugreifen will, kann man auch über eine Achse
direkt auf das Element zugreifen. Nehmen wir mal an wir suchen
zum Ansprechpartner im Element Team die Telefonnummer. Dann
können wir auch sowas machen.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Team/Ansprechpartner"/>
</xsl:template>
<xsl:template match="Ansprechpartner">
<xsl:for-each select="following-sibling::Telefon">
Telefon <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Telefon 030-4544332
C:\saxon2>
Was dem entpricht, was wir uns wünschen.
Die Auswahl bestimmter Knoten auf einer Achse bezeichnet man
als Knotentest.
Will man noch feiner selektieren, also z.B.
auf einer Achse einen Knoten ermitteln, der weiteren Kriterien
entspricht, kann man das mit Attributen machen. Wir können
z.B. vom Kontextknoten Gruppe[1]/Kollegen starten, dann die
Achse descendant entlangwandern, was uns ja die Mitarbeiter
liefert, aber von diesen nur jene selektieren, die das Attribut
Firma besitzen. Das sieht dann so aus.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]/Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
<xsl:for-each select="descendant::*[attribute::Firma]">
Mitarbeiter <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Mitarbeiter Werner Lepinski
Mitarbeiter Erika Saufwech
C:\saxon2>
Und das ist was wir uns erhofft hatten. In
der ersten Gruppe haben die zwei Mitarbeiter Werner Lepinski
und Erika Saufwech das Attribut Firma. Für attribute::irgendwas
gibt es noch eine Kurzschreibweise, die sieht so aus.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]/Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
<xsl:for-each select="descendant::*[@Firma]">
Mitarbeiter <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Man könnte noch präziser selektieren,
etwa nur die Mitarbeiter rausfischen, die bei Preis Wasserhaus
beschäftigt sind, also nur den Werner Lepinski. Das sieht
dann so aus.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="Gruppe[1]/Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
<xsl:for-each select="descendant::*[@Firma='Preis
Wasserhaus']">
Mitarbeiter <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten Mitarbeiter Werner Lepinski, was
richtig ist, da er in dieser Gruppe der einzige ist, der bei
Preis Wasserhaus beschäftigt ist. Wir können noch
präziser selektieren, wenn wir mehrere Prädikate
über and verknüpfen. Zum Beispiel können wir
uns alle Mitarbeiter anzeigen lassen, die als Attribut Werner
Lepinski haben und als status ausgeliehen, also den Peter
Wessnich.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="child::*/Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
<xsl:for-each select="descendant::*[@Firma='Preis
Wasserhaus' and @status='ausgeliehen']">
Mitarbeiter <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Das liefert uns dann den Peter Wessnich. Selbsverständlich
funktionniert auch or (oder). Wollen wir z.B. alle Mitarbeiter
haben, die als Wert für das Attribut Preis Wasserhaus
oder Wertarbeit haben, können wir sowas machen.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="child::*/Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
<xsl:for-each select="descendant::*[@Firma='Preis
Wasserhaus' or @Firma='Wertarbeit']">
Mitarbeiter <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten alle Mitarbeiter, die entweder
bei Preis Wasserhaus oder Wertarbeit beschäftigt sind.
Nach einem ähnlichen Schema wäre es auch möglich
gewesen, nur die Gruppe rauszufischen, die das Kindelement
Kostenvoranschlag besitzt, was ja nur bei der zweiten Gruppe
der Fall ist.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:value-of select="(Gruppe[Kostenvoranschlag])"/>
</xsl:template>
</xsl:stylesheet>
Als Ergebnis dieses Stylesheets erhalten wir
die Textelemente der zweiten Gruppe, den nur diese hat das
Element Kostenvoranschlag.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Hamburger Verwaltungschaos
Werner Nordflut
Marina Meimportauncarajo
Peter Wessnich
Ludwig Noresponsable
An der Waterkant 15
45555 Hamburg
30 000000
C:\saxon2>
Man kann das, ähnlich wie bei Attribut,
noch weiter präzisieren, indem man auch noch angibt,
welchen Textknoten das Element haben soll.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:value-of select="(Gruppe[Kostenvoranschlag='30
000000'])"/>
</xsl:template>
</xsl:stylesheet>
Das Ergebnis ist dann das gleiche wie oben,
da wir nur einen Kostenvoranschlag haben. Ist das Attribut
eine Zahl, lassen sich auch die üblichen mathematischen
Operatoren anwenden. z.B. könnte man alle Mitarbeiter
ermitteln, die bei Summe mehr als 30000 haben.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:for-each select="Gruppe/Kollegen/descendant::*[@Summe
< '30000']">
Hallo <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Das Ergebnis sieht dann so aus.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Hallo Werner Lepinski
Hallo Marina Meimportauncarajo
Hallo Peter Wessnich
C:\saxon2>
Das mathematische größer Zeichen
kann nicht verwendet werden, anstatt dessen ist >
zu verwenden (die dem > Zeichen entsprechende HTML entity).
Mit derselben Methode kann man sich auch alle Mitarbeiter
anzeigen lassen, die bei Summe weniger als 3000 haben.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:for-each select="Gruppe/Kollegen/descendant::*[@Summe
< '30000']">
Hallo <xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Wir erhalten dann die Erika Saufwech
und den Hans Geldfliech.
Gleichnamige Elemente finden, die auf unterschiedlichen
Hierarchiestufen liegen |
|
Wenn man alle gleichnamigen Elemente finden
will und diese auf unterschiedlichen Hierarchiestufen liegen,
lässt sich schlecht ein XPATH Ausdruck formulieren, da
dieser ja immer den ganzen Pfad beschreibt, genau dieser ist
aber dann unterschiedlich ist. In unserem Beispiel haben wir
z.B. auch einen Mitarbeiter in Team, der ist aber eine Hierarchiestufe
weiter oben als die Mitarbeiter im Element Gruppe, weil er
nicht in einem Element Kollegen gekapselt ist. Will man jetzt
alle Mitarbeiter rausfischen, kann man sowas machen.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='//Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Das gleiche geht natürlich auch mit Attributen.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='//@Firma'/>
</xsl:template>
<xsl:template match="@Firma">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Das liefert uns dann alle Firmen.
or in einem XPATH Ausdruck |
|
Wir hätten das Problem oben auch, wenn
auch umständlicher, dadurch lösen können, dass
wir zwei Pfade definieren. Das hätte dann so ausgesehen.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter
| Team/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Bei dieser Variante definieren wir jeweils den
kompletten Pfad zu jedem Mitarbeiter.
XPATH kennt manche der in anderen Programmiersprachen
üblichen Funktionen zur Bearbeitung und Analyse von Zeichenketten.
Es ist wohl damit zu rechnen, dass irgendwann einmal auch
regular expressions unterstützt werden.
Verbinden von Zeichenketten: concat() |
|
Mit concat lassen sich Zeichenketten verknüpfen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Herr/Frau <xsl:value-of select="concat(node(),' arbeitet
bei ',@Firma,' Status ',@status)"/>
</xsl:template>
</xsl:stylesheet>
In der Regel dürfte
die concat Funktion nicht viel bringen, das gleiche hätte
man auch so erreichen können.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Herr/Frau <xsl:value-of select="node()"/>
arbeitet bei <xsl:value-of select="@Firma"/>
Status <xsl:value-of select="@status"/>
</xsl:template>
</xsl:stylesheet>
Überprüfen, ob ein Zeichenkette Bestandteil
einer anderen Zeichenkette ist |
|
Wenn wir alle Namen rausfischen wollen, die
Werner enthalten, also Werner Lepinski und Werner Nordflut,
können wir sowas machen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Wert <xsl:value-of select="contains(node(),'Werner')"/>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Wert true
Wert false
Wert false
Wert true
Wert false
Wert false
C:\saxon2>
Fazit, die Funktion liefert true zurück,
wenn die Zeichenkette enthalten ist und false, wenn dies nicht
der Fall ist. Das kann man dann in einer if clause ausnützen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
<xsl:if test="contains(node(),'Werner')='true'">
Hallo <xsl:value-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Die Länge von Zeichenketten ermitteln:string-length() |
|
Will man die Länge einer Zeichenkette
ermitteln, kann man das so machen
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Wert <xsl:value-of select="string-length(.)"/>
</xsl:template>
</xsl:stylesheet>
Testen, ob eine Zeichenkette mit einer bestimmten Zeichenkette
beginnt |
|
Will man z.B. testen, ob ein Name mit dem Buchstaben
P beginnt, was bei einem Mitarbeiter, dem Peter Wessnich ja
der Fall ist, dann kann man das so machen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Wert <xsl:value-of select="starts-with(node(),'P')"/>
</xsl:template>
</xsl:stylesheet>
Wir erhalten dann
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Wert false
Wert false
Wert false
Wert false
Wert false
Wert true
C:\saxon2>
Was wir über eine if Bedingung wie oben
beschrieben ausnützen können.
Zeichenketten aus einer Zeichenkette rausschneiden: substring() |
|
Mit der Funktion substring können wir aus
einer bestimmten Zeichenkette einen Teil herausschneiden.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Ergebnis <xsl:value-of select="substring(node(),5,6)"/>
</xsl:template>
</xsl:stylesheet>
Wir fischen also vom aktuellen Knoten ab der
Position 5 die nächsten 6 Zeichen raus. Das Ergebnis
sieht dann so aus.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Ergebnis er Lep
Ergebnis a Sauf
Ergebnis Geldf
Ergebnis er Nor
Ergebnis na Mei
Ergebnis r Wess
C:\saxon2>
Alle Zeichen vor bzw. nach einem bestimmten Zeichen rausfischen:
substring-before() und substring-after() |
|
Wenn wir uns alle Vornamen rausfischen wollen,
können wir bei dem Leerzeichen die Zeichenkette aufspalten
und das was davor kommt rausfischen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select='Gruppe/Kollegen/Mitarbeiter'/>
</xsl:template>
<xsl:template match="Mitarbeiter">
Ergebnis <xsl:value-of select="substring-before(node(),'
')"/>
</xsl:template>
</xsl:stylesheet>
Das Ergebnis sieht dann so aus.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Ergebnis Werner
Ergebnis Erika
Ergebnis Hans
Ergebnis Werner
Ergebnis Marina
Ergebnis Peter
C:\saxon2>
Funktionen zum Ermitteln von Knoteneigenschaften |
|
Ermitteln, wieviele
Knoten eines bestimmten Typs es überhaupt gibt. count()
Interessiert man sich dafür, wieviele Mitarbeiter es
gibt, kann man das so machen.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:value-of select='count(//Mitarbeiter)'/>
</xsl:template>
</xsl:stylesheet>
Das Ergebnis ist dann sieben.
Ermitteln des letzten Knotens, last() |
|
Die Funktion last() ermittelt die Postitionsnummer
des letzten Knotens der aktuellen Knotenmenge. Das heisst,
dass sie wohl sinnvoll nur innerhalb eines Pradikates mit
position, also z.B. descendant::*[position=last()] eingesetzt
werden kann. Man kann ihr keine Parameter übergeben,
also sie kann nur die Positionsnummer des letzten Knotens
der aktuellen Knotenmenge ermitteln.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="//Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
Wert <xsl:value-of select="last()"/>
</xsl:template>
</xsl:stylesheet>
Das Resultat sieht dann so aus.
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
Wert 2
Wert 2
C:\saxon2>
Da es zwei Kollegen gibt, wird das Template
Kollegen zweimal aufgerufen. last() ermittelt dann jeweils
die Position des letzten Knotens der Knotenmenge Kollegen.
Ein sinnvolles Beispiel sieht so aus.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="/Projekte/Gruppe"/>
</xsl:template>
<xsl:template match="Gruppe">
Hallo <xsl:value-of select="Kollegen/Mitarbeiter[last()]"/>
</xsl:template>
</xsl:stylesheet>
Wie das erste, weniger sinnvolle Beispiel gezeigt
hat, ermittelt die Funktion last() das letzte Element einer
Knotenmenge.
Die Funktion count() unterscheidet sich hiervon
in zwei Aspekten. Erstens kann man ihr eine Knotenmenge als
Parameter übergeben und zweitens ermittelt sie die Anzahl
der Elemente dieser Knotenmenge, ermittelt also den letzten
Knoten der Knotenmenge, die sie als Parameter übergeben
bekommt.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Projekte">
<xsl:apply-templates select="//Kollegen"/>
</xsl:template>
<xsl:template match="Kollegen">
Wert <xsl:value-of select="count(descendant::*)"/>
</xsl:template>
</xsl:stylesheet>
Wir erhalten
C:\saxon2>saxon Unternehmensberatung.xml
test.xsl
<?xml version="1.0" encoding="utf-8"?>
wert 3
wert 3
C:\saxon2>
|