XSLT & XSLT 2.0
Markus Luczak-Rösch Freie Universität Berlin Institut für Informatik
Netzbasierte Informationssysteme markus.luczak-roesch@fu-berlin.de
Wie geht es weiter?
letzte Woche
Navigation & Verknüpfungen mit XPath & Co.
heutige Vorlesung
XSLT
mehrere Ursprungsdokumente
Sortieren
Gruppieren
XSLT 2.0
Bild-Quelle: http://www.w3schools.com/xquery/default.asp
eXtensible Stylesheet Language (XSL)
XSL
• eine Familie von Sprachen zur Erzeugung von Layouts für XML-Dokumente
• keine vordefinierten Tags
• besteht aus:
• XPath – Navigations-/Selektionssprache für XML- Dokumente
• XSLT – Transformationssprache für XML-Dokumente
• XSL-FO – Formatierungssprache für XML-Dokumente
XSL beschreibt, wie XML-Dokumente
dargestellt werden sollen
XML Transformation
Warum XML transformieren?
Trennung Inhalt und Präsentation
XML trennt Inhalt von Präsentation (Layout)
Für eine entsprechende Darstellung müssen XML- Inhalte transformiert werden:
XML-Inhalt Layout
Inhaltliche Transformationen
Daten mit XML repräsentiert
unterschiedliche Sichten (Views) auf XML-Inhalte erfordern Transformationen:
XML-Inhalt XML-Inhalt
XML-Inhalt Layout
Multi-Delivery: unterschiedliches Layout von Inhalten
ASCII EXCEL
XHTML
Transformation (XSLT)
WML
Inhalt (XML)
XML-Inhalt XML-Inhalt
Zulieferer Großhandel
interner Kundenauftrag
Name des Verkäufers
Datum
Produktbezeichnung aus Großhandelskatalog
Anzahl
Kunde
externer Zulieferauftrag
Datum
Produktbezeichnung aus Zuliefererkatalog
Anzahl
Auftraggeber übernehmen
anpassen
anpassen
XML-Inhalt XML-Inhalt
<?xml version="1.0"?>
<order>
<salesperson>John Doe</salesperson>
<item>Production-Class Widget</item>
<quantity>16</quantity>
<date>
<month>1</month>
<day>13</day>
<year>2000</year>
</date>
<customer>Sally Finkelstein</customer>
</order>
<?xml version="1.0" encoding="UTF-8"?>
<order>
<customer>Company A</customer>
<date>2000/1/13</date>
<item>
<part-number>E16-25A</part-number>
<description>Production-Class Widget</description>
<quantity>16</quantity>
</item>
</order>
Kundenauftrag
Zulieferauftrag
andere Sicht (view)
auf XML-Inhalt
eXtensible Stylesheet Language
Transformation (XSLT) - Einführung
Was ist XSLT?
• in XML beschriebene Sprache zur Transformation von XML-Dokumenten
• eine beschreibende Sprache
• XSLT-Programme (stylesheets) haben XML-Syntax
plattformunabhängig
• erlaubt XML-Dokumente in beliebige Textformate zu transformieren:
• XML XML/HTML/XHTML/WML/RTF/ASCII …
• W3C-Standard seit 1999
XSLT: Ziele
Kopplung zweier Prozesse:
• Transformation des Quelldokuments in das Ergebnisdokument
• Formatierung für die Ausgabe in dem gewünschten
Format
XSLT: Anfragesprache für XML?
SQL
• Anfrage = Sicht (View) auf Menge von Relationen
• abgeschlossen: SQL-Anfrage liefert immer eine Relation
XSLT
• Transformation = Sicht (View) auf Menge von XML-Dokumenten
Anfragesprache für XML
• nicht abgeschlossen: kann beliebige Textformate
liefern, nicht nur wohlgeformtes XML
Was passiert?
Quelle: http://www.oio.de/m/konf/jaxw2004/jaxw2004-XSLT-2.0.pdf, Angepasst
Allg. Schema der Transformation
XML- Dokument
XSLT- Stylesheet
XSLT-Prozessor
Ergebnis- Dokument
• Verknüpfung zwischen Stylesheet & Dokument im Dokument
<?xml version=".. "?>
<?xml-stylesheet type="text/xsl" href="file.xlst"?>
<element>
…
</element>
XSLT Prozessoren
• Xalan
• Open Source XSLT-Prozessor
• http://xalan.apache.org/
• default Xerces XML-Parser
• unterstützt W3C Recommendations: XSLT 1.0 & XPath 1.0
• Xalan C (C++) & Xalan J (Java)
• SAXON
• Open Source XSLT-Prozessor
• http://saxon.sourceforge.net/
• Saxon in Version 9.0.0.5 unterstützt XSLT 2.0, XQuery
1.0, & XPath 2.0
Programmierparadigma
• XSLT-Programm (stylesheet) = Menge von Transformationsregeln
• Transformationsregel (template)
• Erzeuge aus Unterstruktur X im Ursprungsdokument Y im Ergebnisdokument
• Beispiel:
• Identifizierung von Unterstrukturen mit XPath
<xsl:template match="order/item">
<p><xsl:value-of select="."/></p>
</xsl:template>
<order>
… <item>Item</item>
</order> …
<p>Item</p>
Ursprungs- und Ergebnisdokument
<?xml version="1.0"?>
<order>
<salesperson>John Doe</salesperson>
<item>Production-Class Widget</item>
<quantity>16</quantity>
<date>…</date>
<customer>Sally
Finkelstein</customer>
</order>
<p>Production-Class Widget</p>
Ursprungsdokument Ursprungsbaum
(source document source tree)
Ergebnisbaum Ergebnisdokument
(result tree result document)
<xsl:template match="order/item">
<p><xsl:value-of select="."/></p>
</xsl:template>
Template
Tr ansfor ma ti on
Schema der Transformation im Detail
XML- Dokument
XSLT- Stylesheet
XSLT- Prozessor
Ergebnis- dokument
Quelle: H. Vonhoegen„Einstig in XML: Grundlagen, Praxis, Referenzen“,ISBN 978-3-8362-1074-4, 2007
Quelldokumentenbaum/
Ursprungsbaum
Stylesheetbaum
Ergebnisbaum
Weitere Programmierparadigmen XSLT-Transformationsregeln
• immer auf Ursprungsdokument(en) angewandt, niemals auf Zwischenergebnissen
• keine Seiteneffekte:
• Template angewandt auf X liefert immer das gleiche Ergebnis
= Templates haben keine Zustände
keine Variablen, die überschrieben werden können
oft auch funktionales Programmierparadigma
genannt
Grundstruktur von Stylesheets
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
…
</xsl:stylesheet>
• XML-Dokument
• Dokument-Wurzel:
• stylesheet oder transform aus entsprechendem W3C- Namensraum
• stylesheet und transform gleichbedeutend
• obligatorisches Attribut: version
XSLT-
Namensraum Deklaration XML-
Präfix
Top-Level-Elemente (I)
• Kinder des Elements
<xsl:stylesheet>
• beliebige Reihenfolge, nur
<xsl:import> immer am Anfang
• <xsl:import> & <xsl:include> - importieren Stylesheets
<xsl:stylesheet>
<xsl:import/>
<xsl:include/>
<xsl:attribute-set/>
<xsl:output/>
<xsl:variable/>
<xsl:param/>
<xsl:template/>
…
</xsl:stylesheet>
• <xsl:attribute-set> - definiert eine Menge, die aus einer Sammlung von Attributen besteht, die mit Hilfe von
<xsl:attribute> festgelegt wird
Top-Level-Elemente (II)
• <xsl:output> - legt eine Methode fest, die bei der Erzeugung des
Ergebnisdokuments beachtet werden soll
<xsl:stylesheet>
<xsl:import/>
<xsl:include/>
<xsl:attribute-set/>
<xsl:output/>
<xsl:variable/>
<xsl:param/>
<xsl:template/>
…
</xsl:stylesheet>
• <xsl:output method= " xml " /> - erzeugt wohlgeformtes XML
• <xsl:output method= " html " /> - HTML-Elemente & - Attribute werden erkannt
• <xsl:output method ="text"/> - ergibt die String-Werte
XSLT - Templates
Grundstruktur von Stylesheets
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="…">
…
</xsl:template>
</xsl:stylesheet>
Template (Template-Regeln)
Suchmuster
Inhalte erzeugen
• Template: „Suche im Ursprungsdokument Unterstruktur X und erzeuge hieraus
Ergebnisdokument Y!“ (ungefähr…)
• zwei Möglichkeiten, Y zu erzeugen:
1. neue Inhalte erzeugen
2. Inhalte von X nach Y übertragen.
• beide Möglichkeiten beliebig miteinander
kombinierbar
1. Neue Inhalte erzeugen (I)
• Templates können alle XML-Inhalte erzeugen:
PCDATA, Elemente und Attribute
• einfach normale XML-Syntax verwenden:
<xsl:template match="…">
<p style="color:red">neuer Text</p>
</xsl:template>
• Beachte: Stylesheets müssen wohlgeformte XML- Dokumente sein, daher z.B. nicht erlaubt:
<xsl:template match="…">
<br>neuer Text
</xsl:template>
1. Neue Inhalte erzeugen (II)
• statt üblicher XML-Syntax
<xsl:template match="…">
<p style="color:red">neuer Text</p>
</xsl:template>
• auch möglich:
<xsl:template match="…">
<xsl:element name="p">
<xsl:attribute name="style">color:red</xsl:attribute>
<xsl:text>neuer Text</xsl:text>
</xsl:element>
</xsl:template>
2. Inhalte übertragen
<xsl:copy-of select="."> Element
• Kopiert aktuellen Teilbaum
• aktueller Teilbaum: Baum, der vom aktuellen Knoten aufgespannt wird, einschließlich aller Attribute und PCDATA
<xsl:copy> Element
• Kopiert aktuellen Knoten ohne Kind-Elemente, Attribute und PCDATA
Kopiert nur Wurzel-Element des aktuellen Teilbaums
<xsl:value-of select="."> Element
• Extrahiert PCDATA, das im aktuellen Teilbaum
vorkommt
Beispiel
<xsl:template match="p">
<DIV>
<xsl:copy-of select="."/>
</DIV>
<DIV>
<xsl:copy/>
</DIV>
<DIV>
<xsl:value-of select="."/>
</DIV>
</xsl:template>
<source>
<p id="a12">Compare
<B>these constructs</B>.
</p>
</source>
<DIV>
<p id="a12">Compare
<B>these constructs</B>.
</p>
</DIV>
<DIV>
<p/>
</DIV>
<DIV>
Compare these constructs.
</DIV>
Ergebnisdokument
oder mit "text()" statt "."
<DIV>
Compare
</DIV>
XSLT-Prozessor im Transformationsprozess
XML- Dokument
XSLT- Stylesheet
XSLT- Prozessor
Ergebnis- Dokument
Quelle: H. Vonhoegen„Einstig in XML: Grundlagen, Praxis, Referenzen“,ISBN 978-3-8362-1074-4, 2007
Quelldokumentenbaum/
Ursprungsbaum
Stylesheetbaum
Ergebnisbaum
Was passiert hier?
Funktionsweise des XSLT-Prozessors
1. K := Dokument-Wurzel (" ") des Ursprungsdokumentes
2. Identifiziere alle Templates, die auf K anwendbar sind.
a) Ist genau ein Template anwendbar, dann wende dieses an.
Fertig.
a) Sind mehre Templates anwendbar, dann wende das speziellste an:
z.B. ist "/order" spezieller als "/*".
Fertig.
c) Ist kein Template anwendbar, dann wiederhole für
alle Kinder K' von K Schritt 2 mit K := K'.
Template-Konflikte
• mehrere Templates auf den gleichen Knoten anwendbar
• Lösung Prioritätsregeln:
1. Eine spezifische Information hat Vorrang vor einer Regel für allgemeinere Information
Beispiel: match=“/buch/authors/autor“
match=“//autor“
2. Suchmuster mit Wildcards (* oder @*) sind allgemeiner als entsprechende Muster ohne Wildecards
3. NUR wenn 1. & 2. nicht zutreffen Reihenfolge der Templates entscheidend
4. Priorität der Templates durch Attribut priority bestimmbar
• Standard = 0
Transformations-Beispiel
<source>
<A id="a1">
<B id="b1"/>
<B id="b2"/>
</A>
<A id="a2">
<B id="b3"/>
<B id="b4"/>
<C id="c1">
<D id="d1"/>
</C>
<B id="b5">
<C id="c2"/>
</B>
</A>
</source>
<xsl:template match="A">
<xsl:value-of select="@id"/>
</xsl:template>
<xsl:template match="B">
<xsl:value-of select="@id"/>
</xsl:template>
<xsl:template match="C">
<xsl:value-of select="@id"/>
</xsl:template>
<xsl:template match="D">
<xsl:value-of select="@id"/>
</xsl:template>
a1 a2
Stylesheet kein Template
anwendbar Template "A"
wird angewandt
Template "B"
wäre anwendbar, es werden aber keine Templates
aufgerufen!
Template "A"
wird angewandt
Template "B"
wäre anwendbar, es werden aber keine Templates
aufgerufen!
Dokument
Ausgabe
Templates mit Rekursion
<source>
<A id="a1">
<B id="b1"/>
<B id="b2"/>
</A>
<A id="a2">
<B id="b3"/>
<B id="b4"/>
<C id="c1">
<D id="d1"/>
</C>
<B id="b5">
<C id="c2"/>
</B>
</A>
</source>
<xsl:template match="A">
<xsl:value-of select="@id"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="B">
<xsl:value-of select="@id"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="C">
<xsl:value-of select="@id"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="D">
<xsl:value-of select="@id"/>
<xsl:apply-templates/>
</xsl:template>
a1 b1 b2 a2
b3 b4 c1
d1 b5
c2
Stylesheet Dokument
Ausgabe
Rekursiver Aufruf aller Templates
versucht Templates auf Kinder des aktuellen Knotens anzuwenden
Kind bedeutet hier: Kind-Element, Text-Knoten oder Attribut-Knoten
Mit <xsl:apply-templates select = "…"/> auch rekursiver Aufruf an beliebiger Stelle möglich
Vorsicht: Terminierung nicht automatisch sichergestellt!
Beispiel:
<xsl:apply-templates/>
<xsl:template match="A">
<xsl:value-of select="@id"/>
<xsl:apply-templates select="/"/>
</xsl:template>
Iteration statt Rekursion
<source>
<A id="a1">
<B id="b1"/>
<B id="b2"/>
</A>
<A id="a2">
<B id="b3"/>
<B id="b4"/>
<C id="c1">
<D id="d1"/>
</C>
<B id="b5">
<C id="c2"/>
</B>
</A>
</source>
<xsl:template match="A">
<xsl:for-each select="*">
<xsl:value-of select="@id"/>
</xsl:for-each>
</xsl:template> b1
b2 b3 b4 c1 b5
xsl:value-of wird auf alle select-Pfade der for-each- Schleife angewandt.
Beachte: select-Pfad von xsl:for-each relativ zum Kontext-Knoten des
Templates, hier also "A/*"
XSLT – Templates: vordefinierte Templates
Vordefinierte Templates
1. vordefiniertes Template
realisiert rekursiven Aufruf des Prozessors, wenn kein Template anwendbar ist
2. vordefiniertes Template
kopiert PCDATA und Attribut-Werte des aktuellen Knotens in das Ergebnisdokument
Leeres Stylesheet
traversiert gesamtes Ursprungsdokument und extrahiert dabei PCDATA und Attribut-Werte Überschreiben
Vordefinierte Templates können durch speziellere
Templates überschrieben werden
1. vordefinierte Template
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
1. wird zuerst auf Dokument-Wurzel ("/") angewandt
2. versucht alle Templates anzuwenden
3. wird auf alle Kind-Elemente ("*") angewandt
realisiert rekursiven Aufruf des XSLT-Prozessors
wird von jedem speziellerem Template überschrieben:
z.B. sind "/" und "item" spezieller als "*|/"
spezielleres Template anwendbar kein
automatischer rekursiver Aufruf
2. vordefinierte Template
<xsl:template match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
Template wird auf PCDATA text() und Attribute @*
angewandt
text(): XPath-Funktion, selektiert PCDATA
Template überträgt PCDATA bzw. Attribut-Wert in
das Ergebnisdokument
Leeres Stylesheet
Bei Stylesheet ohne Templates sind nur die beiden vordefinierten Templates aktiv:
<xsl:template
match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
Gesamtes Ursprungsdokument wird traversiert,
dabei werden PCDATA und Attribut-Werte extrahiert
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
Beispiel
<xsl:template
match="text()|@*">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
<?xml version="1.0"?>
<name>
<first>
John
</first>
<middle>
Fitzgerald Johansen
</middle>
<last>
Doe
</last>
match="/" apply-templates match="*" apply-templates
match="*" apply-templates match="text()" John
match="*" apply-templates
match="text()" Fitzgerald Johansen match="*" apply-templates
match="text()" Doe
Identitäts-Stylesheet
• Stylesheet mit lediglich einem Template:
• überschreibt 1. vordefinierte Template <xsl:template match="*|/"> , da spezieller
• Zusammen mit 2. vordefinierten Template
<xsl:template match="text()|@*"> wird Ursprungsdokument kopiert
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
wird auf jedes Element ( ) angewandt
kopiert Wurzel des aktuellen Teilbaumes
ruft rekursiv alle Templates
auf
Position des rekursiven Aufrufes?
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<root>
<a>aaa</a>
<b>bbb</b>
<c>ccc</c>
</root>
<root/>
<a/>
aaa
<b/>
bbb
<c/>
<xsl:template match="*">
<xsl:copy>
</xsl:copy>
<xsl:apply-templates/>
</xsl:template>
<root>
<a>aaa</a>
<b>bbb</b>
<c>ccc</c>
</root>
Ergebnis:
Templates für Kommentare
• vordefiniertes Template
• Kommentare und Prozessanweisungen werden nicht übernommen
<xsl:template match="comment()|/processing-instruction()"/>
• Beispiel für Template, wenn Kommentare im Ergebnisdokument
erscheinen sollen
<xsl:template match="comment()">
<xsl:comment>
<xsl:value-of select ="."/>
<xsl:/comment>
</xsl:template>
XSLT – Templates: benannte Templates, Variablen &
Parameter
Benannte Templates
• Templates können auch einen Namen haben:
<xsl:template match="/order/item" name="order-template">
…
</xsl:template>
• Benannte Templates können gezielt mit
<xsl:call-template name="order-template"/>
aufgerufen werden
Template-Modi
• Attribute mode - um Templates, die dasselbe match-Kriterium verwenden, unterscheiden zu können
<xsl:stylesheet …>
<xsl:template match="/">
…
<xsl:apply-templates select="//buch" mode="kurzfassung">
<xsl:apply-templates select="//buch" mode="langfassung">
</xsl:template>
<xsl:template match="buch" mode="kurzfassung">
…
</xsl:template>
<xsl:template match="buch" mode="langassung">
…
</xsl:template>
</xsl:stylesheet …> Definition der Templates
Verwendung der Templetes
entsprechend des mode-Attributes
Variablen
<xsl:variable name="X">
<xsl:copy-of select=".">
<xsl:variable>
• Initiale Zuweisung kann nicht überschrieben werden!
• Wert von :
• Beispiel:
• werden z.B. verwendet um Wiederholungen gleicher Ausdrucke zu vermeiden
• Beispiel: deklariert Variable mit := aktuellen Teilbaum
<xsl:variable name="N">2</xsl:variable>
...
<xsl:value-of select="item[position()=$N]"/>
Gültigkeit von Variablen
• Variablen kommen innerhalb von <xsl:stylesheet> vor und dann entweder
• außerhalb von <xsl:template> (d.h. auf dem Top-Level)
globale Variable - steht allen Templates zur Verfügung oder
• innerhalb von <xsl:template>
lokale Variable - gültig nur innerhalb des Templates, in
dem sie notiert wurde
Parameter
<xsl:template name="printRows">
<xsl:param name="N"/>
…
<xsl:call-template name="printRows">
<xsl:with-param name="N" select="$N + 1"/>
</xsl:call-template>
</xsl:template>
• Templates können Parameter haben:
Festlegung/Überschreibung des Parameters
Aufruf des
Parameters
XSLT: und was gibt es noch?
Nummerierung <xsl:number>
• zahlreiche Formate für Nummerierung über <xsl:number>
<xsl:template match="kurs">
<p>
<xsl:number/>
<xsl:text> </xsl:text>
<xsl:value-of select ="@name"/>
</p>
</xsl:template>
<kursprogramm>
<kurs name="XML Technologien">
…
</kurs>
<kurs name="Datenbanken">
…
</kurs>
</kursprogramm>
1 XML-Technologien 2 Datenbanken
Template
Ausschnitt aus dem Quelldokument
• mit <xsl:number format="i"/>
i XML-Technologien
ii Datenbanken Ausgabe
Bedingte Ausführung <xsl:if>
• das bedingte Template als Kindelement von
<xsl:if>
• Wenn es sich bei der Bedingung um einen XPath- Ausdruck handelt
• bei einem Knotenset ist der Ausdruck "true", wenn das Knotenset mindestens einen Knoten enthält
• bei einem String ist er "true", wenn der String nicht leer ist
• bei einer Nummer ist er "true", wenn diese ungleich Null ist
<xsl:template match="kurs">
<xsl:if test=referent=‘Luczak-Rösch‘>
<h3><xsl:value-of select ="@name"/></h3>
<p>Referent: <xsl:value-of select ="referent"/></p>
</xsl:if>
</xsl:template>
Template
Beispiel für <xsl:if>
<xsl:template match="kurs">
<xsl:if test=referent=‘Luczak-Rösch‘>
<h3><xsl:value-of select ="@name"/></h3>
<p>Referent: <xsl:value-of select ="referent"/></p>
</xsl:if>
</xsl:template>
<kursprogramm>
<kurs name="XML Technologien">
<referent>Luczak-Rösch</referent>
</kurs>
<kurs name="Datenbanken">
<referent>Bodin</referent>
</kurs>
</kursprogramm>
XML-Technologien
Luczak-Rösch Template
Ausschnitt aus dem Quelldokument
Ausgabe
Wahlmöglichkeiten <xsl:choose>
<xsl:template match="item">
<part-number>
<xsl:choose>
<xsl:when test=". = 'Production-Class Widget'">
E16-25A
</xsl:when>
<xsl:when test=". = 'Economy-Class Widget'">
E16-25B
</xsl:when>
<xsl:otherwise>00</xsl:otherwise>
</xsl:choose>
</part-number>
</xsl:template>
Beispiel
Switch-Anweisung in Java ähnlich
Abarbeitung von oben nach unten
Falls Inhalt von item =
'Production-Class Widget',
dann erzeuge E16-25A
Schleifen <xsl:for-each>
• Anweisungen als Kinderknoten von <xsl:for-each>
…
<table width="..." border="1" cellspacing="1">
…
<xsl:template name="...">
<xsl:for-each select="//kurs">
<tr>
<td width="..." height="...">
<xsl:value-of select="position()">
</td>
<td width ="..." height="...">
<xsl:value-of select="@name">
</td>
</tr>
</xsl:for-each>
</xsl:template>
…
1 XML Technologien 2 Datenbanken
<kursprogramm>
<kurs name="XML Technologien">
<referent>Luczak-Rösch</referent>
</kurs>
<kurs name="Datenbanken">
<referent>Bodin</referent>
</kurs>
</kursprogramm>
Template
Ausgabe
Sonstige Möglichkeiten
• Sortieren
• XPath-Funktionen
• Mehrere Ursprungsdokumente
• … und vieles mehr!
<xsl:sort select="name/nachname"/>
<xsl:sort select="name/vorname"/>
<xsl:if test="not(position()=last())">…</xsl:if>
<xsl:apply-templates select="document('bib.xml)"
XSLT: Verarbeitung von Stylesheets
Verarbeitung von Stylesheets
Stylesheets können auf zwei Arten verarbeitet werden:
1. auf dem Server
+ Ursprungsdokument verdeckt
- alle Transformationen auf zentralen Server
2. im Client
+ Transformationen auf Clients verteilt: spart Server- Ressourcen
- Ursprungsdokument sichtbar
Mächtigkeit von XSLT
Variablen machen Stylesheets zu einem mächtigen Termersetzungssystem mit unbeschränkten Registern
www.unidex.com/turing definiert universelle Turingmaschine als XSLT-Stylesheet
- Eingabe: Programm p (XML), Input i (XML) - Ausgabe: p(i)
Browser = vollwertiger Computer!
Stylesheets tatsächlich berechnungsvollständig und damit vollwertige Programmiersprache
(Kepser 2002) Terminierung von Stylesheets kann
prinzipiell nicht garantiert werden.
Vorteile von XSLT
+ plattformunabhängig
+ relativ weit verbreitet
+ Verarbeitung in Web-Browsern
+ Standard-Transformationen (wie XML HTML) einfach zu realisieren.
+ Nicht nur HTML, sondern beliebige andere Sprachen können erzeugt werden.
+ extrem mächtig
Nachteile von XSLT
- Entwickler müssen speziell für die Transformation von XML-Dokumenten neue Programmiersprache lernen.
- Anbindung von Datenbanken umständlich
- manche komplexe Transformationen nur umständlich zu realisieren
- Termination kann nicht garantiert werden
Fazit: XSLT nur für Standard-Transformationen
verwenden!
Mehrere Ursprungsdokumente
Mehrere Ursprungsdokumente
• Verbinden von
• Buchkapitel
• Brief-Templates
• Adresslisten
• Erstellen von Inhaltverzeichnissen, die mehrere Dateien erfassen
• Wiederverwenden von Bildbeschreibungen in
verschiedenen Galerien
3 Dokumente
<?xml version="1.0"?>
<ph:photo
xmlns:ph="http://page.mi.fu-berlin.de/mochol/xml_xsl/">
<ph:title>Jet d Eau</ph:title>
<ph:location>Genf (Geneve)</ph:location>
<ph:date>Juni 2008</ph:date>
<ph:description>
Der Jet d Eau (franz. Wasserstrahl) ist ein bis zu 140 Meter hoher Springbrunnen im Genfersee und eines der
Wahrzeichen der Stadt Genf.
</ph:description>
</ph:photo>
<?xml version="1.0"?>
<ph:photo xmlns:ph="http://page.mi.fu-berlin.de/mochol/xml_xsl/">
<ph:title>Tower-Bridge</ph:title>
<ph:location>London</ph:location>
<ph:date>Juni 2008</ph:date>
<ph:description>
Die Tower Bridge ist eine Strassenbruecke ueber den Fluss Themse in London. Sie wurde 1894 eroeffnet und verbindet die City of London auf der Nordseite mit dem Stadtteil Southwark im Stadtbezirk London Borough of Southwark auf der Suedseite.
</ph:description>
<?xml version="1.0"?>
<ph:photo xmlns:ph="http://page.mi.fu-berlin.de/mochol/xml_xsl/">
<ph:title>Brandenburger Tor</ph:title>
<ph:location>Berlin</ph:location>
<ph:date>Juni 2008</ph:date>
<ph:description>
Das Brandenburger Tor am Pariser Platz in der Dorotheenstadt im Ortsteil Mitte (Bezirk Mitte) von Berlin wurde in den Jahren von 1788 bis 1791 auf Anweisung des preussischen
Koenigs Friedrich Wilhelm II. ….
</ph:description>
</ph:photo>
geneve.xml
berlin.xml
Allg. Schema der Transformation
XML- Dokument
XSLT- Stylesheet
XSLT-Prozessor
Ergebnis- Dokument
• Problem:
3 XML-Dokumente (geneve.xml, london.xml &
berlin.xml) aber erlaubt ist nur ein XML-Dokument als
Input
Main & secondary sources
Hier: main source = Ursprungsdokument
<?xml version="1.0"?>
<ph:index
xmlns:ph="http://page.mi.fu-berlin.de/mochol/xml_xsl/">
<ph:title>City sights</ph:title>
<ph:entry>geneva</ph:entry>
<ph:entry>london</ph:entry>
<ph:entry>berlin</ph:entry>
</ph:index>
geneve.xml london.xml berlin.xml
main
source secondary
sources index.xml
ruft auf
Stylesheet (I)
Namespace index-Knoten aus
index.xml
titel-Knoten aus index.xml
entry-Knoten
aus index.xml
concat()
• string concat(string s1, string s2)
• string concat(string s1, string s2, string s3)
• string concat(string s1, string s2, string s3, …)
• Argumente werden von links nach rechts verkettet
• Anzahl der Argumente beliebig
• nicht-Strings werden mit der Funktion string()
konvertiert
Auflösung von concat()
<xsl:template match="ph:entry">
<img src="{concat(.,'.jpg')}" align="right"/>
<xsl:apply-templates select="document(concat(.,'.xml'))"/>
…
</xsl:template>
entry-Knoten aus index.xml
geneve/london/berlin (Inhalt von entry-Knoten)
<img src="geneve.jpg" align="right">
<img src="london.jpg" align="right">
<img src="berlin.jpg" align="right">
<xsl:apply-templates select="document(geneve.xml)"/>
<xsl:apply-templates select="document(london.xml)"/>
<xsl:apply-templates select="document(berlin.xml)"/>
Stylesheet (II)
Namespace index-Knoten aus
index.xml
titel-Knoten aus index.xml
entry-Knoten
aus index.xml
location/date/describtion
Knoten aus secondary sources
Ablauf der Verarbeitung
MSXML = Prozessor geneve.xml
london.xml berlin.xml secondary
sources ruft auf
XSLT- Prozessor XML-Dokument
(Ursprungsdokument)
XSLT-Stylesheet
Ergebnis-Dokument merge_result.html =
Ergebnis-Dokument merge.xml =
XSLT-Stylesheet index.xml = main source
(Ursprungsdokument)
MSXML = Prozesso
r
Ausgabe in Firefox
Sortieren mit <xsl:sort>
<xsl:sort>
• definiert in welcher Reihenfolge die Knoten bearbeitet werden
• mehrere Sortierungsschlüssel möglich
• die Elemente werden nach dem ersten <xsl:sort>, dann nach dem zweiten <xsl:sort> usw. sortiert
• Position:
• innerhalb von <xsl:apply-templates> oder <xsl:for-each>
Attribute von <xsl:sort>
• order {"ascending | descending"} - aufsteigende oder absteigende Reihenfolge
• case-order {"upper-first | lower-first"}
Großbuchstaben vor Kleinbuchstaben oder Kleinbuchstaben vor Großbuchstaben folgen
• lang {language-code} Sprach-Code, z.B.: "ä" nach "a"
für den deutschen Sprach-Code oder "ä" nach "z" für den schwedischen Sprach-Code
• data-type {"text | number"} alphabetische oder numerische Sortierung
<xsl:sort select="price" order="descending" data-type="number"/>
Zu sortieren
<employees>
<employee>
<name>
<given>James</given>
<family>Clark</family>
</name>
...
</employee>
</employees>
[XSL Transformations (XSLT) Version 1.0 W3C
Templates
<xsl:template match="employees">
<ul>
<xsl:apply-templates select="employee">
<xsl:sort select="name/family"/>
<xsl:sort select="name/given"/>
</xsl:apply-templates>
</ul>
</xsl:template>
<xsl:template match="employee">
<li>
<xsl:value-of select="name/given"/>
<xsl:text> </xsl:text>
<xsl:value-of select="name/family"/>
</li>
</xsl:template>
Gruppieren von XML-Daten
Gruppieren in XSLT 1.0
<records>
<contact id="0001">
<title>Mr</title>
<forename>John</forename>
<surname>Smith</surname>
</contact>
<contact id="0002">
<title>Dr</title>
<forename>Amy</forename>
<surname>Jones</surname>
</contact>
<contact id="0003">
<title>Mr</title>
<forename>Brian</forename>
<surname>Jones</surname>
</contact>
<contact id="0004">
<title>Ms</title>
<forename>Fiona</forename>
<surname>Smith</surname>
</contact>
</records>
Jones,<br />
Amy (Dr)<br />
Brian (Mr)<br />
Smith,<br />
Fiona (Ms)<br />
John (Mr)<br />
Ursprungsdokument
Ergebnis:
gruppieren nach Nachnamen und
sortieren
XSLT
Gruppierung – mögliche Lösung (Schritte)
1. Ermitteln der auftretenden Nachnamen
• jeweils einen Eintrag für jeden Nachnamen bestimmen
• alle Einträge bestimmen, die einen Nachnamen besitzen, der nicht bereits bei einem vorhergehenden Eintrag zu finden ist
2. Bestimmen aller Einträge (contact) auf den gleichen Nachnamen
contact[not(surname = preceding-sibling::contact/surname)]
<xsl:apply-templates
select="/records/contact[surname = current()/surname]" />
Gruppierung – mögliche Lösung (Probleme)
• zwei XPath Ausdrücke, die bearbeitet werden
müssen viel Prozessor-Zeit im Falle von großen XML-Dateien
• Durchsuchen aller Vorgänger mit 'preceding- siblings'-Achse sehr aufwändig (besonders am Ende der Liste)
• Bestimmung aller Einträge mit einem bestimmten Nachnamen erfordert jeweils den Zugriff auf
jeden Eintrag
sehr ineffiziente Vorgehensweise
Gruppierung – Bessere Lösung
• effizientere Gruppierung durch Benutzung von Keys (entwickelt von Steve Muench)
• Key weist einem XML-Knoten einen Schlüssel zu
• Zugriff auf Knoten über den dazugehörigen Schlüssel
bei vielen Knoten mit dem gleichen Schlüsselwert werden alle diese Knoten durch Benutzung dieses Schlüsselwertes ermittelt
Keys sehr effizient fürs Gruppieren einer bestimmten
Anzahl von Knoten bezüglich einer gewissen Eigenschaft
Zugriffsschlüssel <xsl:key>
• xsl:key - definiert einen Zugriffsschlüssel auf Elemente oder Attribute
• key() – Verwendung des Zugriffsschlüssels
• Attribute von xsl:key
• name(obligatorisch) – legt einen Namen für den Schlüssel fest, unter dem er angewendet werden kann.
• use(obligatorisch) gibt an, woraus der Wert des Schlüssels ermittelt wird
• match(optional) – gibt an, wo der Schlüssel im
Elementenbaum ansetzen soll
Zurück zum Beispiel …
1. Schlüssel, der jedem Eintrag als Schlüsselwert den dazugehörigen Nachnamen zuweist
<xsl:key name="contacts-by-surname"
use="surname"
match="contact" />
Name des Keys
Wert des Schlüssels aus dem Element <surname>
Schlüssel soll im Element
<contact> ansetzen
Zurück zum Beispiel (II) …
2a. Bestimmung alle Einträge mit einem bestimmten Nachnamen (d.h. Nachname bekannt, z.B.: "Smith")
2b. Bestimmung aller Einträge mit dem gleichen Nachnamen (d.h. Nachname unbekannt)
<xsl:apply-templates select="key('contacts-by-surname', surname)" />
(key('contacts-by-surname', 'Smith')
Zurück zum Beispiel (II) …
3. Überprüfung, ob der Eintrag der erste in der durch einen Schlüssel zurückgegebenen Liste ist
• Vergleich der mittels generate-id() erzeugten eindeutigen Bezeichner für die beiden Knoten:
• „The generate-id function returns a string that uniquely identifies the node in the argument node-set that is first in document order. […] the string is syntactically an XML
name.“
contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]
XSLT-Dokument des Beispiels
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" media-type="text/html" />
<xsl:key name="contacts-by-surname" match="contact" use="surname" />
<xsl:template match="records">
<h2>Gruppierung nach Nachname:</h2>
<xsl:for-each
select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]">
<xsl:sort select="surname" />
<h3><xsl:value-of select="surname" />,</h3>
<xsl:for-each select="key('contacts-by-surname', surname)">
<xsl:sort select="forename" />
<xsl:value-of select="forename" />
(<i><xsl:value-of select="title" /></i>)<br />
</xsl:for-each><br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
key setzen
ist der jeweilige Eintrag der erste in
der Liste?
sortieren nach Nachname
key-Elemente Verwenden sortieren nach
Vorname display
Nachname,
Vorname, Titel
Ergebnis
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" media-type="text/html" />
<xsl:key name="contacts-by-surname" match="contact" use="surname" />
<xsl:template match="records">
<h2>Gurppierung nach Nachnemane:</h2>
<xsl:for-each
select="contact[generate-id() = generate-id(key('contacts-by-surname', surname)[1])]">
<xsl:sort select="surname" />
<h3><xsl:value-of select="surname" />,</h3>
<xsl:for-each select="key('contacts-by-surname', surname)">
<xsl:sort select="forename" />
<xsl:value-of select="forename" />
(<i><xsl:value-of select="title" /></i>)<br />
</xsl:for-each><br />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<records>
<contact id="0001">
<title>Mr</title>
<forename>John</forename>
<surname>Smith</surname>
</contact>
<contact id="0002">
<title>Dr</title>
<forename>Amy</forename>
<surname>Jones</surname>
</contact>
<contact id="0003">
<title>Mr</title>
<forename>Brian</forename>
<surname>Jones</surname>
</contact>
<contact id="0004">
<title>Ms</title>
<forename>Fiona</forename>
<surname>Smith</surname>
</contact>
</records>
Ursprungsdokument
Ergebnis in Cooktop
XSLT-Stylesheet
Vor & Nachteile der
Muench'schen Methode
+ erfordert nicht das Durchsuchen einer großen Anzahl von Knoten
+ kann sehr effizient ausgeführt werden
- nicht alle XSLT-Prozessoren unterstützen Keys
- kann speicherintensiv sein, weil alle Knoten & ihre Schlüsselwerte im Speicher gehalten werden müssen
- reichlich kompliziert, wenn die Knoten über mehrere
Quelldokumente verteilt sind
XSLT 2.0
XSLT 2.0
• XSLT 2.0 wurde entwickelt um
• die Gestaltungsmöglichkeiten durch Stylesheets zu erweitern
• einige Schwächen von XSLT 1.0 zu beseitigen
• hinsichtlich der Sprachen viele neue und gleichzeitige prägnantere, effizientere, flexiblere und erheblich
leistungsstärkere Features
• XPath 2.0 liefert
• Vereinfachung & Erweiterung der Zugriffe auf Daten
XSLT 2.0 & XPath 2.0 rückwärts kompatibel !
Was ist neu in XSLT 2.0?
1. neue Funktionen und Operatoren
2. Benutzerdefinierte Funktionen
3. mehrere Ergebnisdokumente
4. Unterstützung der Ausgabe in XHTML
5. weitere neue Elemente
6. einfachere Gruppierung
1. Neue Funktionen
• format-date – formatiert ein Datum
• format-dateTime – formatiert einen Datums/Zeit-Wert
• format-time – formatiert einen Zeitwert
• type-available – prüft die Verfügbarkeit eines
bestimmten Datentyps
2. Benutzerdefinierte Funktionen mit <xsl:function>
• Erzeugen von benutzerdefinierten XSLT-Funktionen
• benutzt XPath-Ausdrücke
• legt den Namen der Funktion fest
• legt die Benötigten Parameter fest
• implementier die gewünschte Funktionalität
<xsl:function name="a:nextNumber">
<xsl:param name="number" as="xs:integer"/>
<xsl:choose>
<xsl:when test="$number = 1">
<xsl:sequence select="string('Two')"/>
</xsl:when>
<xsl:when test="$number = 2">
<xsl:sequence select="string('Three')"/>
</xsl:when>
</xsl:choose>
</xsl:function>
Name der Funktion
Parameter
Funktionalität
<xsl:function> Beispiel
• Benutzerdefinierte Funktionen sind an allen Stellen im Stylesheet für XPath-Ausdrücke verfügbar
<xsl:function name="a:nextNumber">
<xsl:param name="number" as="xs:integer"/>
<xsl:choose>
<xsl:when test="$number = 1">
<xsl:sequence select="string('Two')"/>
</xsl:when>
<xsl:when test="$number = 2">
<xsl:sequence select="string('Three')"/>
</xsl:when>
</xsl:choose>
</xsl:function>
<xsl:value-of select="a:nextNumber( 1 )"/>
Aufruf der Funktion a:nextNumber Definition der Funktion
a:nextNumber
3. Mehrere Ergebnisdokumente
• Transformation produziert mehrere Ergebnisbäume
• Basis für Erzeugung mehrerer Ergebnisdokumenten
• z.B. gleichzeitige Erzeugung von dem Gesamtdokument und einer Dokumentübersicht
<xsl:template match="/">
<xls:result-document href="output_1.xml" >
Beschreibung des ersten Ausgabebaumes (z.B.: Gesamtdokument )
</xls:result-document>
<xls:result-document href="output_2.xml">
Beschreibung des zweiten Ausgabebaumes (z.B.: Dokumentübersicht)
</xls:result-document>
</xsl:template>
4. Unterstützung der Ausgabe in XHTML
• in XSLT 1.0 nur:
• <xsl:output method= " xml " /> - erzeugt wohlgeformtes XML
• <xsl:output method= " text " /> - HTML-Elemente & -Attribute werden erkannt
• <xsl:output method= " xml " /> - gibt die String-Werte aller Textknoten, die im Ausgabebaum enthalten sind
• in XSLT 2.0 auch XHTML als Ausgabeformat vorgesehen
<xsl:output method="xhtml"/>
5. Weitere neue Elemente
• <xsl:charachter-map> – verwendet, um während der Serialisierung bestimmte Zeichen durch andere zu
erstetzen
• <xsl:document> – erzeugt einen neuen Dokumentknoten
• <xsl:result-document> – erweitert die Möglichkeiten von output in XSLT 1.0; erlaubt die Eigenschaften des Ausgabebaum detailiert festzulegen
• <xsl:sequence> – verwendet innerhalb eines
Sequenzkonstruktors, um eine Sequenz von Knoten
oder Einzelwerten zu bilden
Gruppieren in XSLT 2.0
Funktionen in <xsl:for-each-group>
• <xsl:for-each-group> vereinfacht die Gruppierung von Sequenzen
• current-group() – liefert die Inhalte der aktuelle Gruppe in <xsl:for-each-group>
• current-grouping-key() – liefert den aktuellen Gruppenschlüssel in
<xsl:for-each-group>
<xsl:for-each-group select="paper" group-by="author">
…
</xsl:for-each-group>
Suchmuster Gruppierungsmuster
Beispiel: Ursprung & Ergebnis
<author>
<name>Caisley, Phil</name>
<paper>On the Way to XML</paper>
</author>
<author>
<name>Myers, Charles</name>
<paper>Publishing Workflows</paper>
</author>
<author>
<name>Parsons, Jonathan</name>
<paper>On the Way to XML</paper>
</author>
<paper>
<title>Publishing Workflows</title>
<author>Myers, Charles</author>
</paper>
<paper>
<title>On the Way to XML</title>
<author>Parsons, Jonathan</author>
<author>Caisley, Phil</author>
</paper> XML-Ergebnisdokument
XSLT
XML-Ursprungsdokument
Beispiel: XSLT-Stylsheet
<xsl:for-each-group select="paper" group-by="author">
<xsl:sort select="current-grouping-key()" />
<author>
<name>
<xsl:value-of select="current-grouping-key()" />
</name>
<xsl:for-each select="current-group()">
<paper>
<xsl:value-of select="title" />
</paper>
</xsl:for-each>
</author>
</xsl:for-each-group>
Such- und Gruppierungsmuster
sortieren nach dem aktuellen
Gruppenschlüssel (hier: Element
<author>)
für alle Inhalte der aktuellen Gruppe (hier:
Inhalte von <paper>) aktueller
Gruppenschlüssel (hier: Element
<author>)
Inhalt des
Elements <title>
group-starting-with: Beispiel
<h1>Überschrift</h1>
<p>Absatz</p>
<p>Absatz</p>
<h1>Überschrift</h1>
<p>Absatz</p>
<p>Absatz</p>
<section>
<title>Überschrift</title>
<para>Absatz</para>
<para>Absatz</para>
</section>
<section>
<title>Überschrift</title>
<para>Absatz</para>
<para>Absatz</para>
</section>
Quelle Ziel
<xsl:for-each-group select="*" group-starting-with="h1">
<section>
<title>
<xsl:value-of select="current-group()[self::h1]"/>
</title>
<xsl:for-each select="current-group()[self::p]">
<param><xsl:apply-templates/></param>
</xsl:for-each>
</section>
</xsl:for-each-group>
Stylesheet
Vor- und Nachteile von XSLT 2.0
+ mächtiger als XSLT 1.0
+ unterstützt Datentypen von XML-Schema
+ wichtige Funktionen verfügbar, die in Version 1.0 fehlten
+ ermöglicht etwas einfachere und effizientere Entwicklung
+ rückwärts kompatibel
+ flache Lernkurve für die neue Spezifikation
- immer noch wenig Prozessoren (Tools), die XSLT
2.0 unterstützen
Wie geht es weiter?
heutige Vorlesung
Warum XML-Dokumente transformieren?
XSLT
XSLT-Editoren
mehrere Ursprungsdokumente
Gruppieren