Archiv für Kategorie Allgemeines
XSLT-SB: asin(), acos(), atan(), atan2(), dynamische Typung
Verfasst von Stf unter Allgemeines, XSLT-SB am 27. Juni 2011
Mit dem Sprung auf Version 0.2.37 kann die XSLT-SB, genauer math.xsl
, jetzt auch die Arkusfunktionen und dynamische Typung. In Ergänzung der knappen Release-Notes hier ein paar Anmerkungen dazu.
Arkusfunktionen
Die Gruppe der Arkusfunktion lässt sich einfach auf der Grundlage von atan()
implementieren – wenn man den richtigen Ansatz gefunden hat. Meine ersten Versuche, asin()
und atan()
über Taylor-Reihen zu implementierten scheiterten daran, dass diese Reihen zu langsam konvergieren. Zusammen mit den in der Reihenbildung verwendeten rekursiven Funktionen (Fakultät und Potenz) war schnell das Limit der Rekursionstiefe erreicht: Saxon bricht die Verarbeitung mit Hinweis auf das Überschreiten der maximalen Rekursionstiefe ab.
Die Lösung brachte ein alternativer Algorithmus zur Berechnung von atan()
, den ich bei WolframMathWorld fand (Gleichungen Nr. 44 bis 48). Mittels des Arkustangens lässt sich einfach der Arkussinus und Arkuskosinus berechnen, so dass diese Implementierung ein Kinderspiel war (siehe Wikipedia).
dynamische Typung
Zweites großes Thema der Überarbeitung von math.xsl
war die dynamische Typung. Die mathematischen Operatoren und Funktionen in XPath geben ihr Ergebnis i.d.R. mit dem Typ der Argumente zurück. Zum Beispiel ist das Ergebnis von fn:round-half-to-even()
mit einem Argument vom Typ xs:decimal
vom Typ xs:decimal
, während mit einem xs:double
-Argument das Ergebnis vom Typ xs:double
ist.
Die Implementierung dieses Verhaltens barg einige Schwierigkeiten, weil manche Funktionen als Ergebnis NaN
, -INF
oder INF
zurückgeben können. Diese speziellen Werte sind zwar mit den Typen xs:float
und xs:double
darstellbar, nicht aber mit xs:decimal
(das aber genauere Ergebnisse als xs:double
liefert) und xs:integer
. Das gewünschte Verhalten ist wohl sehr vom Einsatzzweck der Funktionen abhängig. Der jetzige Kompromiss ist daher, dass bei diesen Werten der Cast von NaN
, -INF
oder INF
auf ungeeignete Typen scheitert; wer Wert auf hohe Genauigkeit legt, kann vielleicht auch die kritischen Werte umschiffen.
Genauigkeit
Laut Standard müssen XPath-Implementierungen mit 18 signifikanten Stellen rechnen. Für die XSLT-SB habe ich mittels intern:round()
die Genauigkeit auf 16 Stellen begrenzt, weil damit die meisten Tests erfolgreich absolviert werden. Trotzdem wird für manche Testwerte (etwa exp(100)
) nicht das richtige Ergebnis ermittelt (bei vielen Berechnungsschritten summieren sich die Fehler halt). In diesen Fällen wird im Testprotokoll (hier z.B. für Saxon EE) eine Warnung (orange hinterlegt) ausgegeben. Diese sind zu unterscheiden von den gelb hinterlegten Fällen, bei denen ein Cast der Ergebnisse auf xs:decimal
(den Typ der Tests) nicht möglich ist, siehe oben. In den Tests nicht berücksichtigt sind die Fälle, für die eine Funktion nicht definiert ist, etwa asin(3)
.
Intern (d.h. bei den Funktionen mit intern:
-Prefix) wird mit einer höhren Stellenzahl gerechnet, diese müssen aber weder signifikant noch richtig sein.
AltovaXML in OxygenXML einbinden
Verfasst von Stf unter Allgemeines, Grundlagen am 30. Mai 2011
Um AltovaXML in OxygenXML nutzen zu können, muss man diesen XSLT-Prozessor als »Custom Engine« einrichten. So geht’s:
Unter Einstellungen/XML/XSLT-FO-XQuery/Custom Engines
einen neuen Prozessor anlegen:
Als Prozessortyp ist »XSLT« vorausgewählt und richtig. Name und Beschreibung eingeben und dann in das Feld Kommandozeile »"C:\Program Files (x86)\Altova\AltovaXML2011\AltovaXML.exe" /xslt2 ${xsl} /in ${xml} /out ${out}
« eintragen (Pfad zu AltovaXML bitte an lokale Gegebenheiten anpassen).
Speichern, fertig. In den Transformationsszenarien kann jetzt der neu angelegte Prozessor ausgewählt werden:
Leider kann OxygenXML keine Parameter oder initiale Modes bzw. initiale Templates an den so erzeugten Prozessor übergeben. Ein Workaround ist, für definierte Fälle eigene Prozessoren anzulegen. Für den ad-hoc-Selbsttest der XSL-SB sieht das so aus:
Der erste Teil der Kommandozeile »"C:\Program Files (x86)\Altova\AltovaXML2011\AltovaXML.exe" /xslt2 ${xsl} /in ${xml} /out ${out} /m internals.self-test -param internals.logging-level="'DEBUG'" -param internals.errors.die-on-critical-errors="'no'"
« ist identisch zu oben, initialer Mode und Parameter werden zusätzlich hart codiert übergeben. Hier sollten die Entwickler von OxygenXML gelegentlich einmal nachbessern, es kann ja nicht so schwer sein, einen benannten Parameter als benanntes Makro anzubieten.