Bug #1968
closed
Shared indexes when xsl:key definition is context sensitive
Category:
XSLT conformance
Applies to branch:
9.5, 9.6
Fix Committed on Branch:
9.6
Fixed in Maintenance Release:
Description
I haven't confirmed this by testing, but I suspect there could be a problem if a key is defined like this:
<xsl:variable name="v" select="base-uri(.)"/>
<xsl:key name="k" match="*[. = $v]" use="name()"/>
<xsl:param name="p" as="document-node()"/>
<xsl:template match="/">
<xsl:value-of select="key('k', 'abcd', $p)"/>
</xsl:template>
If this stylesheet is invoked twice with different initial context items but with the same value of $p, the two invocations will attempt to share the same index supporting the key definition k, but actually the key definitions are different for the two stylesheet invocations because of the dependency on $v.
I have written xslt30 test key-085a/b which confirms that this bug exists. There are two tests using the same stylesheet and source document but with different values of a global parameter; the key index is incorrectly reused for the second test if both tests are run together.
- Priority changed from Low to Normal
The first step is to detect that an xsl:key declaration is not reusable across transformations. As a first step it is sufficient to test whether either the match pattern or use expression contains a global variable reference. We ought also to test that the key is not dependent on a non-reusable key, which is a rather more complex test, and is getting pretty arcane.
The next step is that if a key is non-reusable, we need to hold details of the document indexes at the level of the Controller rather than the Executable (currently the KeyManager is owned by the Executable). This is trickier because all requests for indexed access (for example the selectByKey() method) go directly to the shared KeyManager. Probably the cleanest approach is to have a local KeyManager owned by the Transformer, and a shared KeyManager owned by the Executable, and for all requests to go first to the local KeyManager, which delegates to the shared one if the key is reusable.
- Status changed from New to In Progress
- Found in version set to 9.5
I have implemented a solution to this in the 9.6 branch, but I'm not going to retro-fit it to 9.5 unless anyone actually encounters the problem.
The solution involves:
-
changes to XSLKey to detect that the match pattern or use expression has dependencies on global variables, user-written functions, or user-written templates
-
in this case, marking the KeyDefinitionSet as non-shareable
-
in KeyManager, where the KeyDefinitionSet is non-shareable, storing and retrieving indexes locally in the Controller, rather than in the shared WeakHashMap contained within the KeyManager itself
- Status changed from In Progress to Resolved
- Fixed in version set to 9.6
- Fixed in version changed from 9.6 to 9.6.0.1
- Status changed from Resolved to Closed
- Applies to branch 9.5, 9.6 added
- Fix Committed on Branch 9.6 added
Please register to edit this issue
Also available in: Atom
PDF