XSL
eXtensible Stylesheet Language
Die Stylesheet Sprache für XML
XSL ist ein World Wide Web Standard
• XSL ist ein vom World Wide Web Consortium empfohlener Standard
• W3C Recommendation von XSLT2.0 und XPath2.0Januar 2007
• W3C Proposed Recommendation der gesamten XSL, inklusive XSL Formatting Objects
August 2001
CSS �� XSL
W3C hat mit der Festlegung des XSL Standards begonnen, bevor derjenige von CSS festgelegt war.
Wozu gibt es zwei Style Sheet Sprachen?
CSS XSL
Verwendung mit HTML? ja neinVerwendung mit XML? ja jaTransformations-Sprache? nein jaSyntax CSS XML
CSS - Style Sheet für HTML-Files
• HTML benutzt vordefinierte (und darum allgemein bekannte) Tags:
<h1> Titel-Element<p> neuer Abschnitt,
...
• Im CSS wird definiert, wie die verschiedenen Elemente darzustellen sind (Fonts, Farben, ...)
h1 { font-family: sans-serif;
font-size: 48pt }
p { font-size: 8pt;
color: blue }
XSL – Style Sheet für XML
• XML benutzt keine vordefinierten Tags: <table> kann eine HTML Tabelle oder auch ein Möbelstück sein.
• Im XML-Dokument steht nicht, wie die Daten dargestellt werden sollen.
• Es braucht einen Mechanismus, welcher beschreibt, wie die Daten eines XML-Dokumentes dargestellt werden sollen.
XSL bietet diesen Mechanismus
XSL erzeugt beliebige Formate
XML(Daten)
C++
WordXML
XML
PostScript(XSL-FO)
Java
TeXPDF
(XSL-FO)
(X)HTML
XSL: Drei Teile / Drei Sprachen
Drei Teile
• eine Methode, um XML Dokumente zu transformieren,
• eine Methode, um XML Teile und Patterns zu adressieren
• eine Methode, um XML Dokumente zu formatieren
Drei Sprachen
• XSLT, die Sprache um XML umzuwandeln• XPath, die Sprache zum Adressieren und
Selektieren von XML-Knoten• XSL Formatting Objects (XSL FO), die Sprache
um formatierte Ausgabe zu beschreiben.
XSLT
XSL Transformations
XSL Transformations
• XSLT ist der wichtigste Teil des XSL Standard. XSLT wird benutzt, um XML Dokumente in andere (XML, HTML, ...) Dokumente umzuformen.
• XSLT kann auch neue (nicht im XML-Dokument enthaltene) Daten-Elemente in das Ausgabe-Dokument einfügen (zum Beispiel Formatier-Befehle), Elemente umsortieren oder weglassen.
• XSLT kann die XML-Knoten (zum Beispiel auch abhängig vom Wert des Elementes) verschieden behandeln (formatieren).
Wie funktioniert XSLT?
XSL
(Templates)
XML
(Daten)
AusgabeDokument
Wie funktioniert XSLT?
• XSLT benutzt im Transformations-Prozess die Sprache XPath, um die zu einem Template passenden Knoten herauszufiltern.
• Sobald im XML-Dokument ein passender Knoten (match) gefunden wird, formt XSLT diesen Knoten mit Hilfe der angegebenen Regeln (Template) um, und schreibt das Resultat ins Ausgabe-Dokument.
• Alle Text-Knoten des XML-Dokumentes, welche nicht zu einer Regel (einem Template) passen, werden unmodifiziert in das Ausgabe-Dokument kopiert.
Das Beispiel Dokument: People.xml
<?xml version="1.0"?><people>
<person><name>
<firstName>Alan</firstName><lastName>Turing</lastName>
</name><born date="1912" addressRef="gbl"/><died date="1954" addressRef="gbc"/><profession>computer scientist</profession><profession>mathematician</profession><profession>cryptographer</profession><hobby>philosophy</hobby><hobby>biology</hobby>
</person>...
XML Dokument mit Stylesheet Verbinden
<?xml version="1.0"?><?xml-stylesheet type="text/xsl"
href="http://www.abc.ch/mystyle.xsl"?><people>
<person><name>
<firstName >Alan</firstName><lastName>Turing</lastName>
</name>...
xsl:template
XSL benutzt Templates (Regeln), um zu bestimmen, wie die XML-Knoten umgeformt werden sollen.
Ein "match"-Attribut wird benutzt, um ein Knoten einem Template zuzuordnen.
<xsl:template match= Knoten >
Action
</xsl:template>
XSL: "hello world"
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="people">hello world
</xsl:template>
</xsl:stylesheet>
hello world
XSL: "hello world"
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="people">
hello world
</xsl:template>
<xsl:template match="person">
I am here
</xsl:template>
</xsl:stylesheet>
hello world
XSL: "hello world"
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="person">
I am here
</xsl:template>
</xsl:stylesheet>
I am here
I am here
I am here
I am here
Great Britain London Germany UlmUSA Queens, NY Switzerland BaselGreat Britain Cambridge USA Princeton
Die wichtigsten xsl Befehle
<xsl: ... >
xsl:apply-templates
Der Befehl xsl:apply-templates sucht im XML den angegebene Pfad, eine Regel dazu und führt diese aus.
Welches Kind als nächstes behandelt werden soll, kann explizit ausgewählt werden durch ein select-Attribut <xsl:apply-templates select="person"/>
Der Befehl<xsl:apply-templates/>
sucht alle Kind (-Elemente) des aktuellen Knotens und führt deren Templates aus.
xsl:apply-templates
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="people">
<xsl:apply-templates select="person"/>
</xsl:template>
<xsl:template match="person">
I am here
</xsl:template>
</xsl:stylesheet>
I am hereI am hereI am hereI am here
xsl:call-template
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0“ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="people">
<xsl:call-template name="templ1"/>
</xsl:template>
<xsl:template name=" templ1"><xsl:apply-templates select="person"/>
</xsl:template>
<xsl:template match="person">I am here</xsl:template>
</xsl:stylesheet> I am hereI am hereI am hereI am here
xsl:for-each
Das gleiche Resultat erhalten wir durch
I am hereI am hereI am hereI am here
<xsl:template match="people">
<xsl:for-each select="person">
I am here
</xsl:for-each>
</xsl:template>
xsl:value-of
Das XSL <xsl:value-of> Element kann benutzt werden, um den Wert bestimmter Knoten auszugeben.
Beispiele:
<xsl:value-of select="lastName"/><xsl:value-of select="firstName"/><xsl:value-of select="hobby" separator=", " />
<xsl:template match="people"><html>
<head><title> Famous Scientists</title></head><body><h4> Famous Scientists</h4>
<xsl:apply-templates select="person"/></body>
</html></xsl:template>
<xsl:template match="person"><p/> <xsl:apply-templates select="name"/>
</xsl:template>
<xsl:template match="name"><xsl:value-of select="lastName"/><xsl:text> </xsl:text><xsl:value-of select="firstName"/>
</xsl:template>
Adressieren von Attributen
<xsl:template match="person"><b><xsl:apply-templates select="name"/></b><xsl:text> </xsl:text><small>
( <xsl:value-of select="born/@date"/> -<xsl: value-of select="died/@date"/>)
</small><p/>
</xsl:template>
Es ist möglich, für dieselben Knoten mehrere, verschiedene Templates zu definieren, die dann kontextabhängig angewandt werden.
Der Aufruf des Templates sowie das Template selber erhalten ein mode Attribute.
Damit können zum Beispiel Inhaltsverzeichnisse, Querverweise oder verschiedene Darstellungen der gleichen Datenelemente erzeugt werden.
Templates mit Modes
<xsl:template match="people"><html> <body>
<h4>Table of Contents</h4><ul><xsl:apply-templates select="person" mode="toc"/></ul><xsl:apply-templates select="person"/>
</body></html></xsl:template>
<xsl:template match="person" mode="toc"><li/><xsl:value-of select="name/lastName"/>
</xsl:template>
<xsl:template match="person"><p>
<b><xsl:apply-templates select="name"/></b><small> (<xsl:value-of select="born/@date"/> -<xsl:value-of select="died/@date"/>)</small>
</p></xsl:template>
Templates mit Modes
Der erste Durchgang wird durch<xsl:template match="person" mode="toc">
gebildet, der zweite durch<xsl:template match="person">
xsl:if
Mit Hilfe einer if-Anweisung können Knoten unterschiedlich behandelt werden
<xsl:if test="name/lastName = 'Euler' ">
<xsl:if test="born/@date > 1900 ">
<xsl:template match="person">
<xsl:if test="born/@date > 1900 ">
<xsl:apply-templates select="name"/>
</xsl:if>
</xsl:template>
XSL Test Operation
Die Bedingungen können mit and oder or verbunden werden.
<xsl:template match="person">
<xsl:if test="born/@date > 1850 andname/firstName != 'Alan' ">
<xsl:apply-templates select="name"/>
</xsl:if>
</xsl:template>
Richard Feynman
Albert Einstein
xsl:choose
Es gibt in XSL kein if-else Konstrukt. Anstatt eines if-else gibt es ein xsl:choose. Verzweigungen werden aus xsl:when und xsl:otherwise zusammengesetzt.
<xsl:choose><xsl:when test="...">
...</xsl:when><xsl:otherwise>
...</xsl:otherwise>
</xsl:choose>
<xsl:template match="person"><xsl:choose>
<xsl:when test="profession='mathematician' "><font color="blue">
<xsl:apply-templates select="hobby"/></font>
</xsl:when><xsl:otherwise>
<xsl:apply-templates select="hobby"/></xsl:otherwise>
</xsl:choose></xsl:template>
XSL Auswahl Operation
xsl:sort
Um eine Sequenz von Knoten während der Transformation (nach einem gewählten Schlüssel) zu sortieren, gibt es das sort Element:
<xsl:sort select="name/lastName"/>
xsl:sort kann entweder innerhalb eines <xsl:apply-templates> oder eines <xsl:for-each> Elements vorkommen.
Das select-Attribut gibt an, nach welchem Schlüssel sortiert werden soll.
<xsl:apply-templates select="person"><xsl:sort select="name/lastName" order="ascending"/>
</xsl:apply-templates>
XSL Sortier Operation
<xsl:sort> als Kind von <xsl:apply-templates>:
xsl:variable
In XSL können auch Konstanten definiert werden:
<xsl:variable name="ntext">value_of_variable
</xsl:variable>
Der Wert der Konstanten ntext kann mit $ntext gelesen werden:
<xsl:value-of select="$ntext"/>
Der Wert von ntext kann nicht verändert werden!
xsl:variable
Berechnen einer gewichteten Summe
<xsl:variable name="tmp"><tmpPrice>
<xsl:for-each select="book"><item>
<xsl:value-of select="price * quantity"/></item>
</xsl:for-each></tmpPrice>
</xsl:variable><xsl:value-of select="sum($tmp/tmpPrice/item)"/>
xsl:param
Beim Aufruf von Templates können Parameter übergeben werden
<xsl:apply-templates select="title"><xsl:with-param name="p1">
<xsl:value-of select="irgendein Wert"/></xsl:with-param>
</xsl:apply-templates>
Verwendung im Template:<xsl:template match="title">
<xsl:param name="p1"/>... verwenden von $p1 ...
</xsl:template>
xsl:for-each-group
<xsl:template match="people"><xsl:for-each-group select="address"
group-by="country"><xsl:value-of select="country"/>:<xsl:value-of select="current-group()/city"
separator=", "/><br/></xsl:for-each-group>
</xsl:template>
xsl:include / xsl:import
<xsl:import href= "URI" >und
<xsl:include href= "URI" > fügen das unter der angegebenen Adresse gefundene
Stylesheet ein.
<xsl:include href="ss.xsl"/>
<xsl:include href="http://www.sowieso.ch/ss.xsl"/>
Default Template Regeln
Was geschieht mit den Knoten, wenn es im Stylesheet dafür kein Template
gibt?
Text- und Attribut-Knoten
Von Text- und Attribut-Knoten wird der Wert des Textes (des Attributes) in das Ausgabe-Dokument kopiert.
Als XSL-Template sieht dies wie folgt aus:
<xsl:template match= " text() | @* "><xsl:value-of select="."/>
</xsl:template>
Root- und Element-Knoten
Vom Root- und von allen Element-Knoten werden per Default die Template-Regeln aller Kindknoten aufgerufen.
Als XSL-Template sieht dies wie folgt aus:
<xsl:template match= " / | * "><xsl:apply-templates/>
</xsl:template>
Kommentare / Verarbeitungsanweisung
Kommentare und Processing Instructions werden per Default ignoriert.
Als XSL-Template sieht dies wie folgt aus:
<xsl:template
match= "processing-instructions() | comment()" />
Es gibt keine Adressierung (keinen XPath Ausdruck) für Namespace-Knoten.
Template Drivenvs.
Data Driven
Schwach strukturierte XML Dokumente
Reports, Briefe, Webseiten, ....
<?xml version='1.0'?>
<book-review>
<title>This Book</title> by <author>This
Author</author>, by <publisher>The
Publisher</publisher> on <date>date</date>,
indeed a good book. However, the book titled
<title>Book</title> by the same publisher is
very bad. The reviewer ...
</book-review>
Data-Driven Template
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body>
<xsl:apply-templates/>
</body></html>
</xsl:template>
<xsl:template match="book-review">
<p> <xsl:apply-templates/> </p>
</xsl:template>
. . .
XPath
www.w3.org/TR/xpath
Adressierung
Die Templates im Stylesheet können nur dann richtig (an der richtigen Stelle) angewandt werden, wenn die Adressierung (match) korrekt ist.
XSL muss beliebige Knoten des XML-Dokumentes adressieren (identifizieren) können.
Dafür benutzt XSL die Sprache XPath.
XPath Beispiele
name alle <name> Kinder des aktuellen Knotens
name/firstName alle <firstName> Kinder aller <name> Kinder des aktuellen Knotens
/ der Root Knoten des Dokumentes
. der aktuelle Knoten
.. der Vorgänger (Parent) des aktuellen Knotens
//name alle <name> Elemente des Dokumentes
.//name alle <name> Nachfolger (direkt und indirekt) des aktuellen Knotens
XPath Syntax
• Die XPath-Syntax sieht ähnlich aus wie die übliche Filesystem-Adressierung.
• Das Pattern matching ist abhängig vom Kontext: Ein XPath Ausdruck kann verschiedene Knoten bezeichnen, abhängig von der Stelle im Dokument, in welchem er steht.
• XPath findet alle passenden Knoten. Sollen nur gewisse Knoten aus dem Pfad selektiert werden, kann der Pfad (durch Prädikate) eingeschränkt werden.
XPath Syntax
• Ein XPath ist absolut, falls er mit einem Slash (" / ") anfängt: /person
• Ein Pfad ist zusammengesetzt auf einer Reihe von Schritten, welche durch "/" getrennt sind:
people/person/born
• Attribute werden durch "@" markiert.born/@addressRef
• Pfade können kombiniert werden durch "|" (Auswahl)
name/firstName | profession | hobby
XPath: Wildcards
Pfade können Wildcards enthalten: *, @* und node().
* selektiert alle Elemente@* selektiert alle Attributenode() selektiert alle Knoten
Beispiele//* alle Elemente im Dokument/* alle Kinder von Rootstr/*/title alle <title> Enkel von str//*/@id alle Attribute mit Namen id
XPath Prädikate
XPath kann auch filtern. Dazu wird im select-Attribut zum Pfad ein Prädikat mit angegeben
<xsl:apply-templatesselect="person [name/firstName != 'Alan' ]"/>
Mögliche Filter-Operatoren sind:= gleich
!= ungleich< kleiner als> grösser als
XPath Beispiele: Prädikate
born[ @addressRef = 'gbc' ]alle <born> Kinder, welche ein addressRef Attribut
mit Wert "gbc" haben
died[ @addressRef ] alle <died> Kinder, welche ein addressRef Attribut
haben
person [born/@date > 1900 ]/namealle Namen von Personen, welche später als 1900
geboren sind
name[last()]das letzte <name> Kind des aktuellen Knotens
XPath Schritte
Jeder Schritt im Pfad ist ein Bezeichner, ein Wildcard oder ein Prädikat.
<xsl:template match="person"><xsl:apply-templates select="*[@date]"/>
</xsl:template>
<xsl:template match="born | died"><xsl:value-of select="../* /lastName"/>, <xsl:value-of select="name(.) "/>: <xsl:value-of select="@date"/><xsl:variable name="var" select="@addressRef"/><xsl:apply-templates select="//*[@id=$var]/city"/><br/>
</xsl:template>
Weitere Beispiele
//name/*alle Kinder von name
//name/*[@*]alle Kinder von name, die ein Attribut haben
//name/*[*]alle Kinder von name, welche keine Blätter sind
//*[@*]alle Elemente, die ein Attribut haben
//person[*/@id]/name
alle name Kinder von person Elementen, die ein Kind mit einem id Attribut haben
//*[@*]/*alle Kinder von Elementen, die ein Attribut haben
XPath Adressierung-Achsen
Es gibt für viele XPath-Adressen zwei Schreibweisen: die ausführliche und die abgekürzte. Bisher haben wir immer die abgekürzte Schreibweise benutzt.
Abkürzung für:attribute @child (default)parent ..self .descendant-or-self //
self
parent
ancestor
preceding
descendant
following
child
descendant-or-self
Adressierungs-Achsen
following-sibling
preceding-sibling
ancestor-or-self
XPath: child, self, parent
Child ist die Default-Richtung im Pfad. child:: kann immer weggelassen werden:
Statt self::* wird üblicherweise die abgekürzte Schreibweise ( . ) benutzt:
parent::* findet den (direkten) Vorgänger eines Knotens und kann abgekürzt werden durch ..
/child::people/child::person/child::profession
= /people/person/profession
XPath Funktionen
Die wichtigsten XPath Funktionen
Konvertierungsfunktionen
boolean( obj )number( obj )string( obj )
Negierungboolean not (value)
String Funktionen
concat(), substring(), contains(), Konkatenation, Substring bilden, Substring-Test
number string-length(string)
boolean matches (string, pattern)true, falls der gegebene String das Pattern erfüllt.
string replace (s1, pattern, s2)im String s1 werden alle Teile, welche das Pattern erfüllen, durch s2 ersetzt
Numerische Funktionen
abs(), avg(), max(), min() Absolutwert, Durchschnitt, Maximum, Minimum
round(), floor(), ceiling()Runden, Abrunden, Aufrunden
Grundoperationen+, -, *, mod, div
Numerische Funktionen (2)
<xsl:value-of select="sum(//number)"/>die Summe der Werte, welche in allen <number>-Knoten vorkommen.
<xsl:value-of select="sum(//book/quantity)"/>
berechnet die Anzahl vorhandene Bücher
format-number( -50.883, '#.0')ergibt den Wert -50.9
Funktionen auf Sequenzen
person[3], person[last()]filtert die dritte (letzte) Person heraus
position() gibt die Position des Knotens im Kontext zurück.
count()zählt die Anzahl Knoten der Knoten-Menge set.
count(//person) ergibt 4, count(//address) ergibt 6
Funktionen auf Sequenzen (2)
boolean empty(items)
ergibt true, falls items eine leere sequenz
remove(), insert-before(), reverse(),
subsequence(), …
Funktionen auf Sequenzen zum Löschen, Einfügen, Umdrehen und Zerteilen der Sequenzen.
Datum und Zeit
current-date(), current-time()aktuelle Zeit, aktuelles Datum
format-date(date, pictureString) …
Beispiel:format-date(current-date(), ' [D]-[M]-[Y] ')
For-Ausdrücke
for $x in E1 return result
evaluiert result für jedes Element der Sequenz E1
sum(for $x in book return $x/price * $x/quantity)
summiert die price * quantity Werte aller order Elemente
Einlesen von XML-Dokumenten
Die Funktion
document($srcval )lädt das an der Adresse (URI) srcval gefundene Dokument.
Durch Definition einer Variable „input“ kann so auf die Elemente des Files „Daten.xml“ zugegriffen werden.
<xsl:variable name="input"select="document('Daten.xml')/person"/>
xsl:key, key()
Durch xsl:key kann eine Indexierung (Schlüssel) von Elementen angelegt werden.
Alle ../born/@date-Attribute von name-Elementen:
<xsl:key name="myKey1" match="name"use="../born/@date"/>
Alle Anfangsbuchstaben von hobby-Elementen:
<xsl:key name="myKey2" match="hobby"use="substring(.,1,1)"/>
xsl:key, key()
Die XPath Funktion key() gibt dann die entsprechenden Elemente zurück.
<xsl:apply-templates select="key('myKey1','1912')"/>
gibt alle name-Knoten mit Geburtstjahr 1912 zurück.
<xsl:apply-templates select="key('myKey2','p')"/>
gibt alle hobby-Knoten mit Anfangsbuchstabe "p" zurück.
People Beispiel: address ID auflösen
Schlüssel definieren<xsl:key name="addrKey" match="address"
use="@id"/>
Schlüssel benutzen<xsl:template match="person">
<xsl:apply-templatesselect="key('addrKey', born/@addressRef)"/>
</xsl:template>
xsl:function
<xsl:stylesheet "version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform
xmlns:cs="http://www.isbe.ch/catalogFunctions"
xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<!-- function definition -->
<xsl:function name="cs:substring"><xsl:param name="str" as="xs:string"/><xsl:param name="n" as="xs:integer"/><xsl:sequence select= "if( string-length($str) >=$n )
then substring($str,1,$n) else error() "/></xsl:function>
Exkurs: XQuery
Übungen