Bug #2606
closedFailure to allow debugging of global variables in the applyTemplate path
Added by O'Neil Delpratt almost 9 years ago. Updated about 7 years ago.
100%
Description
Bug initially reported by Alex Jitianu.
Failure to allow debugging of global variables in the applyTemplate path
Updated by Michael Kay almost 9 years ago
The design intention is that when a TraceListener is enabled, global variables should be evaluated eagerly when the transformation starts, rather than lazily on first reference as happens otherwise. This is designed on the assumption that debugging will be easier this way.
At present in 9.7 this is happening on the traditional "transformDocument" invocation, and on callTemplate invocation, but not on applyTemplates or callFunction invocation.
With the new XSLT 3.0 invocation design, the idea is to separate the process of priming the stylesheet (which is done once), from invocation of specific templates or functions (which can be done multiple times). Global variables should only be evaluated once, while "priming", though of course it can be done lazily if the value is not yet needed. During priming of the stylesheet, the global context item needs to be available, but this is not necessarily the same as the items to which an initial applyTemplates is applied.
Priming in Saxon corresponds to the method Controller.initializeController() and I think it is here that the pre-evaluation of global variables should be done. This is also the point at which the TraceListener is opened. Note that the evaluation of global variables is itself traced by calling the TraceListener, so the TraceListener cannot assume that global variables will be immediately available when it is first called. (There are also some stylesheets where evaluating global variables is nearly all the work.)
Updated by Michael Kay almost 9 years ago
- Status changed from New to Resolved
A patch was committed whose effect is to move the code that pre-evaluates global variables when a TraceListener is set, to the initializeController() method, so that it happens regardless which style of invocation is used (and only happens once during "priming" of the stylesheet.
Updated by O'Neil Delpratt almost 9 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.7.0.3 added
Bug fix applied in the Saxon 9.7.0.3 maintenance release.
Updated by Michael Kay over 8 years ago
- Status changed from Closed to In Progress
Reopened. There are problems with the patch.
(a) reports of a NullPointerException when pre-evaluating a global variable that refers to the global context item. It seems that the context passed to preEvaluateGlobalVariables does not initialize the currentIterator which means the focus is absent.
(b) reports that the attempt to access the global variables from the package returns an empty list.
Updated by Michael Kay over 8 years ago
As a first step, I have created a copy of all the unit tests in TestXslt30Transformer (copied to TestXslt30TransformerDebug) in which the transformation is run with a TraceListener present, to force the controller down the paths that are used when debugging is enabled. I'm seeing one test failure: testErrorLocationFromXdm outputs an error with incorrect line number information (expected 5, actual 3). The actual results seem equally valid (it's reporting the start of the sequence constructor that delivers an incorrect value rather than the end of the sequence constructor, which is a consequence of wrapping the sequence constructor in a trace expression) - so I'm taking no action on that.
Updated by Michael Kay over 8 years ago
My next step was to modify one of the unit tests to use the supplied stylesheet which contains a global variable that references the global context item. This test uses Controller.applyTemplates() invocation. It works fine. The method GlobalVariable.actuallyEvaluate() creates a context for the evaluation based on the the Controller's globalContextItem, and evaluates the variable successfully during the preEvaluateGlobals() phase, as it should.
Updated by Michael Kay over 8 years ago
Next I created a variant of this test using the JAXP API. This failed:
Error at char 6 in xsl:value-of/@select on line 5 column 60
XPDY0002: The context item for axis step (/)/descendant::element() is absent
JAXP invokes the old-style s9api XsltTransformer.transform() method.
This invokes Controller.initializeController() followed by Controller.transform(). The problem is that when initializeController() is called, the (StreamSource) source object has not yet been built into a tree, and no global context item is therefore available: hence the error message.
I have added the code to build the tree before calling initializeController(). (The code is extracted from Controller.transform(); it is still there because transform() is called from other paths where the input will not necessarily be a tree.)
This code is on a commonly used path so it will need careful testing. Even with testing, it is almost certain that there will be side-effects.
Updated by Michael Kay over 8 years ago
In the s9api unit tests I'm seeing 7 failures, all of which are in the area of schema validation and appear to be due to work-in-progress on another problem report.
The JAXP unit tests are all passing.
It has also been reported that global variables aren't being pre-evaluated in XQuery (because they aren't obtained from the package details). I will test that next.
Updated by Michael Kay over 8 years ago
- Status changed from In Progress to Resolved
As far as I can tell, all now seems to be working: marking as Resolved.
Updated by O'Neil Delpratt over 8 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.7.0.6 added
- Fixed in Maintenance Release deleted (
9.7.0.3)
Bug fixed in maintenance release 9.7.0.6.
Updated by Radu Coravu about 7 years ago
I'm not quite happy with how the call to "preEvaluateGlobals" in the Controller affects the processing when there is a trace listener set up on the controller.
For example for this XSLT stylesheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:variable name="bam">
<xsl:apply-templates mode="mod2"></xsl:apply-templates>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$bam"></xsl:copy-of>
</xsl:template>
<xsl:template match="*" mode="mod2">
<xsl:copy>
<xsl:copy-of select="@*"></xsl:copy-of>
<!-- The folloing will break-->
<xsl:variable name="er" as="node()" select="/Nonothing"/>
<xsl:message>AAAAAA <xsl:copy-of select="$er"></xsl:copy-of></xsl:message>
<xsl:apply-templates mode="mod2"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
if I apply it using Saxon 9 over any XML document with the trace listener attached, the error is reported at line 9 (in the global variable which does the apply templates).
Also for a very similar stylesheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:variable name="bam">
<xsl:apply-templates mode="mod2"></xsl:apply-templates>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$bam"></xsl:copy-of>
</xsl:template>
<xsl:template match="*" mode="mod2">
<xsl:copy>
<xsl:copy-of select="@*"></xsl:copy-of>
<xsl:message select="'processing'"></xsl:message>
<xsl:message>
<xsl:value-of select="name(.)"/>
</xsl:message>
<xsl:apply-templates mode="mod2"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
with the trace listener attached, the listener will receive "enter" and "leave" events with XSLMessage items before the xsl messages are actually output in the console, making it impossible for us to identify the actual message output in the console for each XSLMessage item.
Please register to edit this issue