Bug #5845
closedMigrating TEI stylesheets to 12.0 produces XPDY0002 (context item is absent)
100%
Updated by Michael Kay almost 2 years ago
I've managed to breakpoint at the point of failure.
It's failed during the deferred (lazy) evaluation of the parameter on line 708 of verbatim.xsl
<xsl:with-param name="content" select="string(@name)"/>
because the saved context for lazy evaluation has no context item.
Looking backwards, it appears that the template verbatim-nextAttribute
was called with no context item. The call was from line 670 of the same module, and the puzzling thing is that it is a tail call; the xsl:call-template
instruction is within an xsl:for-each
loop so this feels wrong. It's still within the xsl:for-each
at run-time so it doesn't look like an incorrect expression rewrite.
Updated by Michael Kay almost 2 years ago
The logic in XSLForEach.markTailCalls() is prepared to treat the last instruction in the for-each
body as a tail call if the select attribute is known to return a single item, which is the case here (in $Atts/*[1]
, $Atts
is a single document node, so *[1]
selects zero or one elements).
Updated by Michael Kay almost 2 years ago
Observed that at the time we create the CallTemplatePackage for the tail call, it is saved with an evaluation context whose current item is the element selected by the xsl:for-each; but when we come to evaluate the CallTemplatePackage, the current item is null. I'm slightly surprised that we aren't saving a snapshot of the context as it is a mutable object, but this seems to be unchanged from 11.x.
So it's clear what's going wrong: within the ForEach, we create a CallTemplatePackage with a reference to a context containing a current iterator which is the select iterator of the ForEach; the ForEach then resumes and does iterator.next() on this iterator, setting the context item to null, and this is the state in which it is found when the CallTemplatePackage then gets executed.
What's not clear is why Saxon 11 didn't fail in exactly the same way.
Updated by Michael Kay almost 2 years ago
It seems that in Saxon 11 ForEach
there is a special path for a ForEach
instruction that contains a tail call; this has not been replicated in the new elaboration code. The special path ensures that after processing the single item in the select
expression, the focus iterator is not advanced any further.
Added the corresponding path to the elaboration code, and fixed the fact that ForEach.containsTailCall
was no longer being set.
The test case now appears to be working; regression testing needed.
Looking at the elaboration code, I'm not convinced its making all the right calls to the TraceListener
when tracing is enabled.
Updated by Michael Kay almost 2 years ago
Also noted, the property ForEach.containsTailCall
does not survive exporting to a SEF file. This is equally true in 11.x.
Updated by Michael Kay almost 2 years ago
- Status changed from In Progress to Resolved
- Fix Committed on Branch 12, trunk added
- Platforms .NET, Java added
Added test case call-template-1003
Updated by O'Neil Delpratt over 1 year ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 12.1 added
Bug fix applied in the Saxon 12.1 maintenance release.
Please register to edit this issue