Bei einer komplexen Transformation ist es ratsam und sogar manchmal unabdingbar die Konvertierung in einzelne Stufen aufzuteilen. Das hat folgende Vorteile:
Der Prozess ist transparenter, da die einzelnen Stufen leichter überschaubar sind.
Die Zwischenergebnisse können für Debug-Zwecke ausgewertet werde oder dienen als Eingabe für andere Prozesse.
Nicht-relevante oder invalide Teilbäume können aus der Eingabeinstanz gefiltert werden, um so die weitere Verarbeitung zu beschleunigen.
Hilfskonstrukte können erzeugt werden. Diese erleichtern die weitere Verarbeitung.
Es gibt zwei Möglichkeiten, wie eine Vortransformation Verarbeitungsmethoden Vortransformation eingebunden werden kann:
In einem separaten File bzw. einer XML Instanz, die vom XSLT Prozessor vor der eigentlichen Transformation aufgerufen wird und einen Zwischenstand produziert. Dieser kann dann als Eingabe für den Haupttransformationsschritt dienen.
Innerhalb des eigentlichen XSLT Stylesheets. Hier wird das Ergebnis der Vortransformation in einer Variablen erzeugt.
Den zweiten Punkt möchte ich anhand eines Beispiel XSLT Skripts vorführen. Betrachten wir folgende Input Daten:
<education-system> <administrative-regions> [...] <dministrative-region id="31" name="Bavaria"> <shools> <school id="45"> <teachers> <teacher id="576"/> <teacher id="345"/> <teacher id="12"/> </teachers> </school> <school id="36"> <teachers> <teacher id="576"/> <teacher id="8"/> </teachers> </school> [...] </shools> </dministrative-region> [...] </administrative-regions> </education-system>Plain Text
Die erste Datei beinhaltet eine Zuordnung von Lehrern zu Schulen in verschiedenen Regierungsbezirken. Um die Daten zu den beiden referenzierten Objekten einzusehen, müssen zwei weitere Dateien konsultiert werden. Die Datei, welche die Lehrer auflistet:
<teachers> [...] <teacher id="576"> <first-name>Alfons</first-name> <last-name>Blimetsrieder</last-name> <subjects> <subject>Biology</subject> <subject>Math</subject> <subject>Sport</subject> </subjects> <suspended>2017-12-31</suspended> [...] </teacher> [...] </teachers>Plain Text
Und die Datei, welche die Schulen auflistet:
<schools> [...] <school id="45"> <name>Gymnasium Bad Aibling</name> <type>Oberschule</type> [...] </school> [...] </schools>Plain Text
Um diese Daten verarbeiten zu können ist es sinnvoll, die drei Dateien in einem ersten "Resolver" Schritt zusammenzuführen und ggf. irrelevante Strukturen zu entfernen. Lehrer aus obigem Beispiel können beispielsweise suspendiert worden sein. Das folgende Skript erledigt dies mittels einer zusätzlichen Transformation in eine Variable:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="#all"> <xsl:output indent="yes" method="xml"/> <xsl:strip-space elements="*"/> <xsl:param name="file-1" required="yes"/> <xsl:param name="file-2" required="yes"/> <xsl:param name="file-3" required="yes"/> <xsl:variable name="files" select="(doc($file-1), doc($file-2), doc($file-3))"/> <xsl:variable name="bavaria-region-ids" select="(31, 58)"/> <xsl:key name="teachers" match="teacher" use="@id"/> <xsl:key name="schools" match="school" use="@id"/> <xsl:template name="main"> <xsl:variable name="resolve-result"> <xsl:apply-templates select="$files/administrative-regions" mode="resolve"/> </xsl:variable> <xsl:apply-templates select="$resolve-result/administrative-regions"/> </xsl:template> <xsl:template match="administrative-region[not(@id = $bavaria-region-ids)]" mode="resolve"/> <xsl:template match="school" mode="resolve"> <xsl:copy> <xsl:copy-of select="key('schools',@id, $files/schools[1]/root())/node()"/> <xsl:apply-templates select="node()|@*" mode="resolve"/> </xsl:copy> </xsl:template> <xsl:template match="teacher" mode="resolve"> <xsl:copy-of select="key('teachers',@id, $files/teachers[1]/root())/node()"/> </xsl:template> <xsl:template match="teacher[suspended/xs:date(.) le current-date()]"/> <xsl:template match="node()|@*" mode="#all"> <xsl:copy> <xsl:apply-templates mode="#current"/> </xsl:copy> </xsl:template> </xsl:stylesheet>Plain Text
Im ersten Resolve-Schritt werden die Referenzen zu den Lehrer- und Schul-Objekten aufgelöst, d.h. die Attribute des Schul-Objekts werden in die Struktur aus der ersten Datei kopiert.
Die Liste der Lehrer an diesen Schul-Objekten bleibt erhalten und wird mit dem Inhalt aus der zweiten Datei bestückt.
Zusätzlich werden alle Regierungsbezirke entfernt, die nicht zu Bayern gehören - was die weitere Verarbeitung wesentlich beschleunigen wird. Lehrer die suspendiert worden sind fliegen ebenfalls raus ...