Bug #6419
closedUnion of nodes in a Template Match produces wrong output in Trace
100%
Description
When using the latest version of xspec, 3.0.3, I had some odd results with a match template that included multiple nodes in a union. Having looked at the Saxon trace I can see that is causing xspec problems.
The problem happens when the template processes a node that is not first in the union e.g.
when <xsl:template match="dummyNode | nodeB"> processes nodeB.
The Saxon trace has some column numbers that are wrong but it also says that the source node is nodeB with the template matching dummyNode rather than nodeB. It seems to just use the first node from the union in the trace.
It is the column numbers that cause problems for xspec.
The example stylesheet has a variable with both nodeA and nodeB nodes and the main template uses apply-templates to process those nodes. There are 2 templates to handle nodeA and nodeB. I've used dummyNode to represent a non-existant node as far as the test is concerned. 1 template has "nodeA | dummyNode" and this is fine. 1 template has "dummyNode | nodeB" and this is where I see the problems. The stylesheet does not need a source file.
I've attached the trace output from Saxon as well as the stylesheet.
Adrian
Files
Updated by Michael Kay 8 months ago
Getting exact line and column numbers is always going to be a problem, because of the limitations of what SAX reports. As described at https://saxonica.plan.io/issues/6415#change-26038 I've recently been experimenting to see if I can associate an element with the location data from the previous SAX event rather than the current SAX event. That's giving good results overall, but doesn't work when there are multiple XML external entities (e.g. a DTD) - there's no way as far as I can see of getting an accurate position for a start tag that immediately follows a DOCTYPE declaration or an external entity reference. As the SAX specification clearly states, the best you can hope for is an approximation.
The issue with the match patterns arises here because Saxon, as required by the spec (XSLT 3.0 ยง6.5 para 2) treats a rule with a union pattern as two separate templates: "If the top-level pattern is a UnionExprP consisting of multiple alternatives separated by | or union, then the template rule is treated equivalently to a set of template rules, one for each alternative. " It looks as if both are being given the same pattern for tracing purposes, based on the first branch of the union. I suspect that is easily fixed. (IIRC we try to output the pattern as written, not as reconstructed by reverse-compiling its internal form. But for a union pattern that has been split in this way, there isn't a version "as written", so we have to do something else.)
Updated by Michael Kay 8 months ago
Right: complicated.
It's creating two separate TemplateRule objects that have different match patterns but share the same compiled Body representing the content of the template rule. The trace instruction on entry to the template is part of this compiled body, and it looks upwards to see what template rule it is part of in order to display the match pattern, and it happens to be linked to the first one rather than the second.
The answer to that would seem to be that the shared top-level trace instruction should contain the full match pattern before it was split into parts, but achieving that may be a bit fiddly.
Updated by Michael Kay 8 months ago
The logic is at XSLTemplate line 788. For the first template in a group (derived by splitting a union pattern), the body is compiled from scratch, and then trace code is injected. For subsequent templates in the group, the body (including the trace instructions) is deep-copied (this is so that the optimizer can handle each branch individually, using knowledge of the context item). This is why the trace instructions reflect the first match pattern. The solution isn't obvious.
Updated by Michael Kay 8 months ago
- Category set to Diagnostics
- Status changed from New to In Progress
- Assignee set to Michael Kay
- Priority changed from Low to Normal
- Applies to branch 12, trunk added
- Platforms Java added
Solved, rather inelegantly, by modifying the properties of the ComponentTracer
after copying.
Updated by Michael Kay 8 months ago
- Status changed from In Progress to Resolved
- Fix Committed on Branch 12, trunk added
Updated by O'Neil Delpratt 6 months ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 12.5 added
Bug fix applied in the Saxon 12.5 Maintenance release.
Please register to edit this issue