Support #4496
closedUnexpected order of data stored for a variable.
0%
Description
Below is the transcript of some unexpected results, boiled down to a simple example. I spent hours assuming that in the following declaration my copied variable content would be found in order in advance of the entity content:
<xsl:variable name="builtinPhrases" as="element(phrases)+"> <xsl:copy-of select="$additionalPhrases"/> &builtinPhrases; </xsl:variable>
Why would the variable content be stored in the variable after the entity content (as indicated by the output)? Is it related to how the stylesheet tree is constructed from the input source? Certainly it seems un-intuitive that the variable comes after the entity.
I've attached the sample file.
Thank you for your thoughts on this!
. . . . . . Ken
~/t $ cat unexpectedVariableResults.xsl
Hello world '> ]> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xsd" version="2.0">
<xsl:variable name="additionalPhrases" as="element(phrases)"> Don't worry, be happy </xsl:variable>
<xsl:variable name="builtinPhrases" as="element(phrases)+"> <xsl:copy-of select="$additionalPhrases"/> &builtinPhrases; </xsl:variable>
<xsl:output method="text"/>
<xsl:template match="/"> <xsl:value-of select="system-property('xsl:product-name'), system-property('xsl:product-version')"/> xsl:text </xsl:text> <xsl:value-of select="$builtinPhrases/@source"/> xsl:text </xsl:text> </xsl:template>
</xsl:stylesheet>~/t $ xslt2 unexpectedVariableResults.xsl unexpectedVariableResults.xsl SAXON HE 9.8.0.15 doctype variable ~/t $
Files
Updated by Ken Holman over 4 years ago
Retry with preformatted text:
~/t $ cat unexpectedVariableResults.xsl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet
[
<!ENTITY builtinPhrases '
<phrases source="doctype">
<phrase>Hello world</phrase>
</phrases>'>
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xsd"
version="2.0">
<xsl:variable name="additionalPhrases" as="element(phrases)">
<phrases source="variable">
<phrase>Don't worry, be happy</phrase>
</phrases>
</xsl:variable>
<xsl:variable name="builtinPhrases" as="element(phrases)+">
<xsl:copy-of select="$additionalPhrases"/>
&builtinPhrases;
</xsl:variable>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="system-property('xsl:product-name'),
system-property('xsl:product-version')"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="$builtinPhrases/@source"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>~/t $ xslt2 unexpectedVariableResults.xsl unexpectedVariableResults.xsl
SAXON HE 9.8.0.15
doctype variable
~/t $
Updated by Michael Kay over 4 years ago
I think the essential issue here is that
$builtinPhrases/@source
sorts nodes into document order, and document order is unpredictable for nodes in different trees. Clearly the nodes constructed by xsl:copy-of and those constructed by expanding the entity are in different trees.
We've often tried to keep things intuitive by making document order across trees equate to the sequence of execution - if node A was created before node B, then node A is before node B in document order. That's been more an accident of the implementation than a deliberate design principle. One problem with it is that it can only be maintained in a multithreaded environment if threads communicate. So we've tended to move more towards distributed allocation of node identifiers rather than sequential allocation - which means in effect that it's truly random.
Try to get into the habit of using "!" rather than "/" if you don't actually want deduplication and sorting into document order. It means breaking the habits of a lifetime, but this expression should almost certainly be written as
$builtinPhrases!@source
Updated by Ken Holman over 4 years ago
Excellent observation and suggestion, Mike! Please forgive me for not having considered that. I figured it must have been something straightforward.
. . . . . . Ken
Updated by Michael Kay over 4 years ago
- Tracker changed from Bug to Support
- Status changed from New to Closed
- Assignee set to Michael Kay
- Priority changed from Low to Normal
Please register to edit this issue