- 1 Intro
- 2 Anwendungsgebiete
- 2.1 XSLT - die Programmiersprache im XML Bereich
- 2.2 Aktuelle und vergangene Anwendungen
- 2.3 Professionelle XML Verarbeitung
- 2.4 Technische Dokumentation
- 3 Wichtige Konzepte
- 3.1 Push vs. Pull Stylesheets
- 3.2 Eindeutigkeit der Regelbasis
- 3.3 Namespaces
- 3.4 Schemata
- 3.5 Standards
- 3.5.1 DITA
- 3.5.2 DITA Inhaltsmodell
- 3.5.1 DITA
- 4 Ausgewählte Themen
- 4.1 Transformationen mit XSLT
- 4.1.1 Vortransformationen
- 4.1.2 Komplexe XML-2-XML Transformationen
- 4.1.2.8 Vererbung
- 4.1.2.8 Vererbung
- 4.1.3 XSLT Streaming
- 4.1.3.1 XSLT Akkumulator
- 4.1.3.2 XSLT Iterator
- 4.1.4 Reguläre Ausdrücke
- 4.1.5 Modus vs. Tunnel Lösung
- 4.1.6 Identifikation mit
generate-id()
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.7 Webservice Calls mit doc() und unparsed-text()
- 4.1.8 Stylesheet-Parameter auf der Kommandozeile
- 4.1.9 Leerzeichenbehandlung
- 4.1.10 Mit
translate
Zeichen ersetzen
- 4.1.10.1 Spass mit dem Sequenzvergleich
- 4.1.11 Character Mappings in der Ausgabe
- 4.1.12 JSON mit XSLT 1.0 und Python lxml
- 4.1.1 Vortransformationen
- 4.2 Abfragen mit XQuery
- 4.2.5 XQuery als Programmiersprache
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.5.3.2 SQL Views in MarkLogic
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.6 Hilfreiche XQuery Schippsel
- 4.2.5 XQuery als Programmiersprache
- 4.3 XML Datenbanken
- 4.3.1 Connector zu Marklogic in Oxygen
- 4.3.2 Bi-Temporale Dokumente
- 4.3.2.1 Anlegen des Testszenarios auf der ML Konsole
- 4.3.2.2 Ausführen einiger Beispiel-Queries
- 4.3.3 Webapps mit MarkLogic
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.4 Dokument-Rechte in MarkLogic
- 4.3.5 MarkLogic Tools
- 4.3.5.1 EXPath Konsole
- 4.3.5.2 mlcp - MarkLogic Content Pump
- 4.3.5.3 Deployment-Tools
- 4.4 XSL-FO mit XSLT1.x
- 4.5 Testing
- 4.5.1 Validierung mit Schematron
- 4.5.2 Erste Schritte mit XSpec
- 4.5.1 Validierung mit Schematron
- 4.6 Performanz-Optimierung
- 4.1 Transformationen mit XSLT
- 5 Zusätzliches Know-How
- 5.1 XML Editoren
- 5.2 Quellcode-Versionskontrolle
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.2.2 GIT Kommandos
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.1 XML Editoren
- 6 Glossary
- 7 Tektur CCMS
3.2 Eindeutigkeit der Regelbasis
Die Regelbasis von XSLT kann wahrscheinlich unendlich viele Regeln aufnehmen, wenn man unsere Limitierung bzgl. der Hardware nicht beachtet. Für die Vollständigkeit, Eindeutigkeit und Konsistenz der Regelbasis ist der Programmierer aber selbst verantwortlich.
Um die Eindeutigkeit der Regeln zu gewährleisten, gibt es verschiedene Mechanismen.
3.2.1 Reihenfolge der Match-Regeln
Im Normalfall sollte auf einen bestimmten Knoten in einem bestimmten Szenario genau eine Regel matchen. Falls es einen Konflikt gibt, wird zumindest bei Saxon diejenige Regel herangezogen, die im Stylesheet zuletzt deklariert wurde.
Diesen Umstand zu kennen, ist genau dann wichtig, wenn man einen bestehenden Stylesheet-Code übernehmen muss. Getreu dem Motto "Never change a running system" sollte man die Sache diesbzgl. sehr behutsam aufräumen.
3.2.2 Präzedenz der Auswertung
Match-Regeln werden gemäß ihrer Spezifität sortiert und diejenige, die auf einem Knoten in einem bestimmten Szenario am besten zutrifft, wird zur Auswertung herangezogen. Grds. werden die Regeln anhand folgender Kriterien sortiert:
1. | Importierte Template Regeln haben immer eine niedrigere Priorität als die Regeln des importierenden Stylesheets. |
2. | Templates mit einem höheren Priority Attribut haben Vorrang. |
3. | Templates ohne Priorität bekommen automatisch eine Default-Priorität. Die höchste Default-Priorität ist 0.5 . |
4. | Diese Default Priorität errechnet sich anhand der Bedingungen oder Wildcards, die an einen Match-Regel geknüpft sind: Beispiele: |
-
Wenn mehrere Templates matchen, dann wird das am meisten spezifische zur Auswertung herangezogen.
-
Das am meisten spezifische Template wird anhand der Prioritäten berechnet.
-
Einfache Elementnamen (z.B. "para") haben Prio 0 .
-
Wildcards (z.B. *, @* ) haben Priorität -0.25
-
Knoten-Tests für andere Knoten (e.g. comment(), node() , etc. ) haben Priorität -0.5
-
In allen anderen Fällen ist die Prio 0.5 .
-
para -> 0
-
h:* -> -0.25
-
* -> -0.25
-
node() -> -0.25
-
contents/para -> 0.5
-
contents/* -> 0.5
5. | Mit einer Kommandozeilen-Option kann bei Saxon festgelegt werden, dass die Transformation abbricht, sobald es einen Konflikt bei der Regelauswertung gibt. |
3.2.3 Import und Default-Regel
Wie in der obigen Sektion unter Punkt 1. angegeben, haben alle Regeln in einem importierten Stylesheet eine geringere Priorität als im importierenden Stylesheet. Diesen Umstand kann man sich zunutze machen, um eine Default-Regel einzubinden, bspw:
<xsl:template match="*" mode="#all"/>
Da diese Regel sich in einem importierten Stylesheet befindet, hat sie geringere Priorität als alle anderen Regeln und greift nur dann, wenn für einen betretenen Knoten keine anderen Match-Regeln definiert sind.
Das ist z.B. praktisch, um nicht "gehandelte" Element zu identifizieren - dazu wäre die obige Regel nicht leer, sondern würde bspw. einen gelb markierten Warntext direkt in das Ausgabeformat schreiben.
Eine leere Default-Regel ist dagegen gut, wenn bspw. in einer XML-2-XML Migration automatisch Knoten im XML Baum abgetrennt werden sollen...
3.2.4 Prioritäten
Alle
Match-Regeln werden mit einer Priorität ausgestattet. Der Stylesheet-Entwickler hat die Möglichkeit diese Priorität zu überschreiben. Dazu wird das Attribut
@priority
an der Match-Regel verwendet. Ein Use-Case für die Prioritäten wäre bspw. folgendes Filter-SzenarioBeispiel Seminarverwaltung
-
Die Eingabeinstanz soll in einer Vorprozessierung gefiltert werden.
-
Dabei sollen Seminar-Elemente markiert werden, die nicht besonderen Bedingungen entsprechen:
-
Das Seminar-Element hat ein Feld "Ende-Datum" das abgelaufen ist.
-
Am Seminar-Element sind mehrere Dozenten angestellt, obwohl das Seminar-Element vom Typ "Single" ist.
-
Einem Seminar-Element ist kein Dozent zugeordnet.
-
-
Sicherlich kann es Seminar-Elemente geben, die alle drei Bedingungen erfüllen. Um das Error-Log aber nicht zu überfüllen, sollen die Filter nach ihren Prioritäten ausgeführt werden.
In XSLT Templates überführt, könnte diese Anforderung so umgsetzt werden:
<xsl:template match="Seminar[Ende-Datum/xs:date(.) le current-date()]" priority="30" mode="filter-seminare"> <xsl:element name="Filtered-Seminar" namespace="{namespace-uri()}"> <xsl:attribute name="reason">termed-seminar</xsl:attribute> <xsl:apply-templates select="node()|@*" mode="filter-seminare"/> </xsl:element> </xsl:template> <xsl:template match="Seminar[Type eq 'SINGLE' and count(dozenten/dozent) gt 1]" priority="20" mode="filter-seminare"> <xsl:element name="filtered-Seminar" namespace="{namespace-uri()}"> <xsl:attribute name="reason">dozenten-count</xsl:attribute> <xsl:apply-templates select="node()|@*" mode="filter-seminare"/> </xsl:element> </xsl:template> <xsl:template match="Seminar[not(dozenten/dozent)]" mode="filter-seminare"> <xsl:element name="filtered-Seminar" namespace="{namespace-uri()}"> <xsl:attribute name="reason">dozenten-missing</xsl:attribute> <xsl:apply-templates select="node()|@*" mode="filter-seminare"/> </xsl:element> </xsl:template>
Neben des Einsatzes des
@priority
Attributs
und des nachfolgend beschriebenen
@mode
Attributs ist sicherlich auch noch interessant, dass die gefilterten Seminar-Elemente hier nicht gelöscht werden, sondern umbenannt werden. Auf diese Weise können sie in einem nachfolgenden Transformationsschritt (Stichwort: Vortransformationen ) weiterbehandelt werden, stören aber in der regulären Verarbeitung nicht.
3.2.5 Modus Attribute
An allen Templates hat man die Möglichkeit einen selbst deklarierten Modus anzugeben. Wenn dann der XSLT Prozessor in eine bestimmte Richtung gepusht, vgl. Push vs. Pull Stylesheets , wird, werden nur diejenigen Regeln zur Auswertung herangezogen, die im selben Modus sind, wie der
apply-templates
Call selbst.
Beispielsweise möchte man die Titel im Kapitel anders behandeln als die Kapitel im Inhaltsverzeichnis, denn im TOC sollen z.B. keine Fussnoten-Marker angezeigt werden.
In Templates formuliert würde so eine Anweisung folgendermassen aussehen:
<xsl:template match="title" mode="toc"> <div class="toc-entry"> <xsl:apply-templates select="node()[not(self::footnote)]"/> </div> </xsl:template> <xsl:template match="title"> <h1> <xsl:apply-templates/> </h1> </xsl:template>
Die Generierung des TOC könnte dann so ablaufen:
<xsl:for-each select="chapter"> <xsl:apply-templates select="title" mode="toc"> </xsl:for-each>
Bzgl. der Eindeutigkeit der Regelbasis kann man so anhand des Mode-Attributes
Ausführungsgruppen bilden.
Wie auch bei Angabe der Priorities kann man auf diese Weise Regeln setzen, die nie ausgeführt werden, weil sie vllt. im Zuge einer Refactoring-Massnahme abgeklemmt und dann vergessen werden.
Auch das
mode
-Attribut ist also mit Vorsicht zu geniessen und sparsam einzusetzen.