4.1.2.8  Vererbung

Mit XSLT kann man Konstrukte aus anderen Programmierparadigmen nachbilden, bspw. Vererbung. Dabei wird in einer Spezialisierung eine schon bereits getätigte Implementierung übernommen und erweitert oder eingeschränkt.
Der Vorteil dabei ist, dass man nicht alles nochmal neu schreiben muss. Das verkleinert die Redundanz, führt zu einer besseren Wartbarkeit und einer geringeren Fehleranfälligkeit.

4.1.2.8.1  Beispiel: Parameterisierung

Gewöhnlich implementiert man ein Stylesheet für ein bestimmtes Ausgabeformat und eine Produktvariante. Schrittweise werden dann weitere Varianten und Formate hinzugefügt.
Am komfortabelsten hat man es natürlich, wenn zu Beginn der Implementierung eine vollständige Spezifikation vorliegt... Das ist aber natürlich eher selten der Fall.
Aus diesem Grund ist es wichtig, sich eine gute Strategie zu überlegen, damit die Architektur nicht in Spagetthi-Code auswartet.
Eine gute Option wäre, die XSLT Import Präzedenz auszunutzen, vgl. Kapitel Eindeutigkeit der Regelbasis .
Will man zu einem späteren Zeitpunkt weitere Parameter einzuführen, dann müsste ein Switch, wie der folgende, an mehreren Stellen im Code aktualisiert werden.
<xsl:choose>
    <xsl:when test="$myParameter='this_option'">
        <!-- do this -->
    </xsl:when>
    <xsl:when test="$myParameter='that_option'">
        <!-- do that -->
    </xsl:when>
        [...]
</xsl:choose>
Besser ist es, wenn man ein Core-Stylesheet pflegt, das für ein Format und eine Produktvariante gut ausgetestet ist. Dieses Core-Stylesheet wird dann einfach für eine neue Variante importiert und relevante Teile werden für die neue "Spezialisierung" überschrieben. Beispielsweise könnte eine Regel zum Setzen des Headers auf jeder Seite so implementiert sein:
<xsl:template name="render-header">
    <!-- print logo on the left side spanning two rows-->
    <!-- print some metadata right side first row -->
    <!-- print a running header right side second row -->
</xsl:template>
Wird in einem neuen Format, bspw. A5, diese Logik ausgetauscht und nur eine Zeile gedruckt, z.B. weil man nicht so viel Platz hat, so würde in einem "abgeleiteten" Stylesheet einfach die Regel noch einmal implementiert.
<xsl:choose>
<xsl:template name="render-header">
    <!-- print a running header on left side -->
    <!-- print logo on right side -->
</xsl:template>
Dieses Template hat nun Vorrang und wird zur Auswertung herangezogen, mit der Konsequenz, dass der Header nur einzeilig gedruckt wird. Das schöne an diesen "Named-Templates" ist auch, dass man sie innerhalb von Variablen verwenden kann:
<xsl:variable name="margin-width">
    <xsl:call-template name="get-margin-width"/>
</xsl:variable>
Das Template get-margin-width kann in einem "Sub"-Stylesheet überschrieben werden, ohne dass die Variablen-Zugriffe im Core-Stylesheet angepasst werden müssen. Eine Zuweisung, wie:
width="{$margin-width}"
müsste nirgendwo im Code nochmal angefasst werden, was natürlich sehr komfortabel ist.

4.1.2.8.2  Beispiel: Spezialisierte Fallunterscheidung

Kommt ein Ausgabeformat zu einem späteren Zeitpunkt hinzu, so kann man die Vererbung nutzen um clever zwischen den Ausgabeformaten zu unterscheiden. Ein bestehendes Template "cover" :
<xsl:template match="cover">
  <fo:page-sequence master-reference="coverFront" force-page-count="auto">
    <fo:flow flow-name="xsl-region-body">
    [...]
  <fo:page-sequence master-reference="coverBack" force-page-count="auto">
    <fo:flow flow-name="xsl-region-body">
    [...]
kann aufgesplittet werden in ein Template für eine Vor- und Rückseite:
<xsl:template match="cover">
  <fo:page-sequence master-reference="coverFront" force-page-count="auto">
    <fo:flow flow-name="xsl-region-body">
      [...]
</xsl:template>
    
<xsl:template name="cover-back-switch">
  <xsl:call-template name="cover-back"/>
</xsl:template>
    
<xsl:template name="cover-back">
  <fo:page-sequence master-reference="coverBack" force-page-count="auto">
    <fo:flow flow-name="xsl-region-body">
      [...]
Das Template "cover-back-switch" kann dann in einem Ausgabeformat überschrieben werden, um bspw. die Cover-Rückseite abhängig von einer Bedingung zu schalten.
Einen Algorithmus in einer Superklasse grob zu strukturieren und Details in Unterklassen zu verfeinern, ist ein gängiges Design Pattern in der Objektorientierten Programmierung. Diese Methodik kann auch sehr schön mittels Named-Templates in XSLT realisiert werden. Nicht umsonst heisst das OO Pattern dazu Template Method ↗↗
Previous Page Next Page
Version: 93
Jan 25 2021