Folgend ist eine Notentabelle zur Benotung nach dem 15-Punkte-Schema für die Kollegstufe abgebildet.

(Link zum PDF mit der vollständigen Notentabelle)
Die Note 6 ist in der Kollegstufe am Gymnasium mit "0 Punkte" bezeichnet. Die Note 5 ist aufgeteilt auf die Stufen "1 Punkt", "2 Punkte" und "3 Punkte". Um die Note 5 zu erzielen muss mindestens ein Drittel der Gesamtpunktzahl erreicht werden. Die Note 4 ist unterteilt in "4 Punkte", "5 Punkte" und "6 Punkte". Um die Note 4 zu erreichen müssen mindestens 50% der Gesamtpunktzahl erzielt werden. Die restlichen 50% der Gesamtpunkte werden dann möglichst gleichverteilt auf die Noten "7 Punkte" bis "15 Punkte".
Die Note "15 Punkte" entspricht dabei der "Note 1 mit Stern". Es können halbe Punkte vergeben werden. Gesucht ist eine homogene Verteilung nach obigen Regeln einer vorgegebenen Gesamtpunktzahl auf die 15 Notenstufen. Das Stylesheet generiert über 200 Tabellen mit verschiedene Werten für die Gesamtpunktzahl aufgeteilt auf 5 DIN A4 Seiten.
Die Logik dazu sieht folgendermassen aus:
<xsl:template name="note-runden"> <xsl:param name="note"/> <xsl:variable name="rest" select="$note * 10 mod 10"/> <xsl:choose> <xsl:when test="$rest > 2.5"> <xsl:value-of select="floor(number($note))"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="floor(number($note))-0.5"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="noten-tabelle"> <xsl:param name="von-punkte"/> <xsl:param name="bis-punkte"/> <xsl:if test="$von-punkte < $bis-punkte+1"> <xsl:variable name="note6" select="$von-punkte div 3"/> <xsl:variable name="note4" select="$von-punkte div 2"/> <xsl:variable name="note5-schrittweite" select="($note4 +(-$note6)) div 3"/> <xsl:variable name="schrittweite" select="$note4 div 12"/> <xsl:variable name="note-6"> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="$note6"/> </xsl:call-template> </xsl:variable> <xsl:variable name="note6-korrigiert"> <xsl:choose> <xsl:when test="3*($note-6+0.5) < $von-punkte"> <xsl:value-of select="$note6+0.5"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$note6"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <fo:block border="1pt solid grey" space-after="3pt" keep-together.within-column="always" padding="2pt"> <fo:block text-align="center" background-color="#999" color="white" padding-bottom="0pt" padding-top="2pt" space-after="2pt"> <xsl:text>Gesamt: </xsl:text> <fo:inline font-weight="bold"> <xsl:value-of select="$von-punkte"/> </fo:inline> </fo:block> <fo:block> <fo:inline font-weight="bold"> <xsl:text>0 P: </xsl:text> </fo:inline> <xsl:text>bis </xsl:text> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="$note6-korrigiert"/> </xsl:call-template> </fo:block> <xsl:call-template name="note5"> <xsl:with-param name="i" select="0"/> <xsl:with-param name="note6" select="$note6-korrigiert"/> <xsl:with-param name="note5-schrittweite" select="$note5-schrittweite"/> <xsl:with-param name="gesamt" select="$von-punkte"/> </xsl:call-template> <xsl:call-template name="ab-note4"> <xsl:with-param name="i" select="0"/> <xsl:with-param name="note4" select="$note4"/> <xsl:with-param name="schrittweite" select="$schrittweite"/> </xsl:call-template> <fo:block/> <fo:block/> </fo:block> <xsl:call-template name="noten-tabelle"> <xsl:with-param name="von-punkte" select="$von-punkte+1"/> <xsl:with-param name="bis-punkte" select="$bis-punkte"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template name="note5"> <xsl:param name="i"/> <xsl:param name="note6"/> <xsl:param name="note5-schrittweite"/> <xsl:param name="gesamt"/> <xsl:if test="$i < 3"> <xsl:variable name="note-von-gerundet"> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="number($note6) + number($i)*number($note5-schrittweite)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="von" select="$note-von-gerundet+0.5"/> <xsl:variable name="bis"> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="number($note6)+ (number($i)+1)*number($note5-schrittweite)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="bis-korrigiert"> <xsl:choose> <xsl:when test="$i=2 and (2*$bis)=number($gesamt)"> <xsl:value-of select="$bis+(-0.5)"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$bis"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <fo:block> <fo:inline font-weight="bold"> <xsl:value-of select="$i+1"/> <xsl:text> P: </xsl:text> </fo:inline> <xsl:value-of select="$von"/> <xsl:text> - </xsl:text> <xsl:value-of select="$bis-korrigiert"/> </fo:block> <xsl:call-template name="note5"> <xsl:with-param name="i" select="$i+1"/> <xsl:with-param name="note6" select="$note6"/> <xsl:with-param name="note5-schrittweite" select="$note5-schrittweite"/> <xsl:with-param name="gesamt" select="$gesamt"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template name="ab-note4"> <xsl:param name="i"/> <xsl:param name="note4"/> <xsl:param name="schrittweite"/> <xsl:if test="$i < 12"> <xsl:variable name="note-von-gerundet"> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="number($note4) + number($i)*number($schrittweite)"/> </xsl:call-template> </xsl:variable> <xsl:variable name="von" select="$note-von-gerundet+0.5"/> <xsl:variable name="bis"> <xsl:call-template name="note-runden"> <xsl:with-param name="note" select="number($note4)+ (number($i)+1)*number($schrittweite)"/> </xsl:call-template> </xsl:variable> <fo:block> <fo:inline font-weight="bold"> <xsl:value-of select="$i+4"/> <xsl:text> P: </xsl:text> </fo:inline> <xsl:value-of select="$von"/> <xsl:text> - </xsl:text> <xsl:value-of select="if ($i=11) then ($bis+0.5) else $bis"/> </fo:block> <xsl:call-template name="ab-note4"> <xsl:with-param name="i" select="$i+1"/> <xsl:with-param name="note4" select="$note4"/> <xsl:with-param name="schrittweite" select="$schrittweite"/> </xsl:call-template> </xsl:if> </xsl:template>Plain Text
Die drei Templates rufen sich so lange selbst auf, bis eine Abbruchbedingung erreicht ist. In den Templates, in denen die zwei Sonderfälle Note 4 und Note 5 behandelt werden, bestimmt die Abbruchbedingung eine Laufvariable $i , die jeweils mit 3 (1P + 2P) und 12 (3P + 4P + 5P) ihren Schwellenwert hat. Das Template notentabelle dispatched auf die Sonderfälle und kümmert sich selbst um die Noten 1 bis 3.
Ohne jetzt groß meine Logik von damals zu überprüfen und in Frage zu stellen, finde ich doch, dass sich XSLT in den letzten Jahren sehr gemausert hat. Musste man sich früher noch mit diversen Saxon Bugs bzgl. der XPath Auswertung herumschlagen, ist diese nun doch äusserst stabil und es gelingen auch komplizierte Prädikate und verschachtelte Selektoren auf Anhieb.
Eine Iteration mittels Endrekursion Programmierkonstrukte Endrekursion ist heute in den meisten Fällen nicht mehr notwendig. Auch Templates, die nur eine Hilfsfunktion realisieren, wie das obige Template note-runden , werden besser mittels xsl:function umgesetzt, was auch innerhalb eines XPath Ausdrucks ausgewertet werden kann.