XSLT-Funktion liefert unterschiedliche Ergebnisse [Saxon-EE vs Saxon-HE / PE]

8

Ich arbeite gerade an einer reinen XSL-Transformation mit Saxon-Prozessor in verschiedenen Versionen. Unten ist mein kurzes Stylesheet, vereinfacht für die Bedürfnisse meiner Frage:

%Vor%

Beschreibung

foo:func_1 ist eine Wrapper-Funktion, um den Wert einer zweiten Funktion zurückzugeben und andere Dinge zu tun, die ignoriert werden können. Dieses Konzept der Funktion ruft andere Funktion auf, ist Pflicht!

foo:func_2 erzeugt eine eindeutige ID für ein Element. Dieses Element wird in einer lokalen Bereichsvariablen namens "node" erstellt.

Unterschiedliche Ergebnisse basierend auf sächsischen Versionen

erwartetes Ergebnis:

%Vor%

Saxon-EE 9.6.0.7 / Saxon-EE 9.6.0.5 Ergebnis

%Vor%

Saxon-HE 9.6.0.5 / Saxon-PE 9.6.0.5 / Saxon-EE 9.5.1.6 / Saxon-HE 9.5.1.6 Ergebnis

%Vor%

Frage / weiter vertieft

Ich habe das Problem soweit wie möglich selbst gelöst. WENN ich das xsl:value-of in der Funktion "func_1" zu xsl:sequence ändern würde, wären die Ergebnisse für alle Versionen gleich [wie erwartet]. Aber das ist nicht meine Absicht!

Ich möchte verstehen, was ist der Unterschied zwischen xsl:value-of und xsl:sequence in allen sächsischen Versionen. Gibt es ein "verstecktes" Caching? Was ist die richtige Art, mit xsl:sequence und xsl:value-of in meinem Fall zu arbeiten? [Btw: Ich weiß bereits, Wert-von erstellt einen Textknoten mit dem Ergebnis der Select-Anweisung. Sequenz könnte eine Referenz auf einen Knoten oder atomaren Wert sein. Löse mein Problem nicht afaik]

    
uL1 08.09.2016, 09:20
quelle

1 Antwort

2

Das ist ein langjähriges und ziemlich tiefes Problem. In einer reinen funktionalen Sprache führt das zweimalige Aufrufen einer reinen Funktion mit denselben Argumenten immer zum selben Ergebnis. Dies macht viele Optimierungen möglich, z. B. das Ziehen eines Funktionsaufrufs aus einer Schleife, wenn die Argumente invariant sind, oder das Einfügen eines Funktionsaufrufs, wenn dieser nicht rekursiv ist. Leider sind XSLT- und XQuery-Funktionen nicht ganz rein funktional: Insbesondere sind sie so definiert, dass, wenn die Funktion neue Knoten erzeugt, der Aufruf der Funktion zwei verschiedene Knoten erzeugt ( f() is f() gibt false zurück).

Der Saxon-Optimierer versucht innerhalb dieser Einschränkungen, so weit wie möglich zu optimieren, insbesondere indem er Funktionen erkennt, die neue Knoten erzeugen und eine aggressive Optimierung solcher Funktionen vermeiden.

Aber die Spezifikation selbst ist nicht 100% vorgeschrieben. Wenn beispielsweise in Ihrem Beispiel eine lokale Variable ohne Abhängigkeiten von Funktionsargumenten vorhanden ist, gibt die Spezifikation der Implementierung die Lizenz, ob der Wert der Variablen bei jeder Auswertung derselbe Knoten ist oder ob es sich um einen neuen Knoten handelt .

Wie Martin sagt, ist das neue XSLT 3.0-Attribut new-each-time ein Versuch, dies unter Kontrolle zu bringen: Wenn Sie bei jedem Aufruf der Funktion wirklich einen neuen Knoten wünschen, sollten Sie new-each-time="yes" angeben.

Hinweis:

Die spezifische Optimierung, die hier stattfindet (die Sie mit der Option -explain sehen können), besteht darin, dass func_2 zuerst inline ist und dann sein Body in eine globale Variable extrahiert wird. Einige Releases tun dies und andere nicht - es kann sehr empfindlich auf geringfügige Änderungen reagieren. Der beste Rat ist, nicht auf Funktionen mit dieser Art von Nebenwirkung angewiesen zu sein. Es würde helfen, wenn Sie Ihr wirkliches Problem erklären, dann könnten wir vielleicht einen Ansatz finden, der in der Sprachsemantik für Kantenfälle nicht so empfindlich ist.

    
Michael Kay 08.09.2016, 12:26
quelle

Tags und Links