XML | XML-Schema | XPath | XSL-T | XSL-FO | XQuery | XProc | SVG |
XSL-T / XSLT-Tipps / XSL-Prozessoren
![]() |
![]() |
➪ In der Entwicklung, im Test- und im Produktivsystem werden mitunter unterschiedliche Prozessoren bzw. Versionen verwendet. Das kann zum Problem führen, wenn unterschiedliche Prozessoren nicht einheitlich arbeiten.
Zur Ausführung der in XSL deklarierten Logik ist ein geeigneter Prozessor erforderlich. Es gibt eine längere Reihe von freien bzw. kommerziellen XSL-Prozessoren, die unterschiedliche Unterstützung bieten.
Einige XSL-1.0-Prozessoren bieten neben den zahlreichen XSL-Standard-Elementen und -Attributen noch diverse Extensions an, die die Standardfunktionalitäten erweitern. Ein Beispiel finden Sie unter max.
Bei jenen XSL-Prozessoren, die verschiedene XSL-Versionen unterstützen, kann die Versionierung des xsl:stylesheet wesentlichen Einfluss auf die interne Verarbeitung der Anweisungen haben, was Informationsverlust nach sich ziehen kann. Ein Beispiel finden Sie unter contains.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
</xsl:stylesheet>
Aber auch bei identischer XSL-Versionierung arbeiten die Prozessoren durchaus nicht einheitlich. Das macht sich u.a. bemerkbar
Ein Beispiel finden Sie bei der sum()-Funktion. Hier lohnt sich ein Type-Cast der zu addierenden Werte, insbesondere, wenn sie erst berechnet werden müssen.
In der Variablen vtmpdemo werden 100 Childnodes generiert:
<xsl:variable name="vtmpdemo">
<root>
<xsl:for-each select="1 to 100">
<k p="0.1" a="3"/>
</xsl:for-each>
</root>
</xsl:variable>
Im Ergebnis stehen für vtmpdemo damit 100 Einzelpositionen mit demselben Inhalt bereit:
<root>
<k p="0.1" a="3"/>
<k p="0.1" a="3"/>
...
<k p="0.1" a="3"/>
</root>
Nun geht es darum, die Werte der Attribute a und p zu multiplizieren und sämtliche Einzelprodukte zu addieren. Dabei arbeite ich einmal mit den Standardsetzungen des jeweiligen Prozessors, ein andermal erzwinge ich einen Type-Cast jedes Einzelwertes auf xs:decimal".
<erg
summe1="{sum($vtmpdemo/root/k/(@p * @a))}"
summe2="{sum
(
$vtmpdemo/root/k/
(xs:decimal(@p) * xs:decimal(@a))
)
}">
<xsl:for-each select="$vtmpdemo/root/k">
<wert>
<xsl:value-of select="@p * @a"/>
</wert>
</xsl:for-each>
</erg>
Bei den Ergebnissen zeigen sich Unterschiede.
Während ein Prozessor die summe2" korrekt berechnet (wo der Type-Cast für jeden Einzelwert auf xs:decimal" erzwungen wurde), wird bei summe1" die Addition der Einzelwerte vermutlich über xs:double" berechnet.
<erg summe2="30" summe1="30.00000000000005">
<wert>0.30000000000000004</wert>
<wert>0.30000000000000004</wert>
<wert>0.30000000000000004</wert>
...
<wert>0.30000000000000004</wert>
</erg>
Völlig dasselbe Ergebnis erhalte ich mit einem anderen Prozessor:
<erg summe1="30.00000000000005" summe2="30">
<wert>0.30000000000000004</wert>
<wert>0.30000000000000004</wert>
...
<wert>0.30000000000000004</wert>
</erg>
Wieder ein anderer Prozessor arbeitet dagegen vermutlich von vornherein auf der Basis von xs:decimal"; zumindest stimmen die tatsächlichen Ergebnisse mit den erwarteten überein.
<erg summe1="30" summe2="30">
<wert>0.3</wert>
<wert>0.3</wert>
...
<wert>0.3</wert>
</erg>
Wegen Abweichungen dieser Art sind vor dem Go-Live detaillierte Tests anzuraten, und zwar mit jenem Prozessor (derselben Version und Konfiguration!), der auch produktiv arbeitet.
wg / 22. April 2018
Fragen? Anmerkungen? Tipps?
Bitte nehmen Sie Kontakt zu mir auf.
ᐃ XSL-T
V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn
☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de