Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
2.7.1, 2.7, 2.6
-
None
-
None
Description
The bug can be demonstrated with the following stylesheet:
<?xml version="1.0"?>
<!-- bug2.xsl -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="input">
<result>
preceding:
<xsl:for-each select="node[not(@group = preceding::node/@group)]">
<xsl:element name="
</xsl:for-each>
following:
<xsl:for-each select="node[not(@group = following::node/@group)]">
<xsl:element name="{@group}
"/>
</xsl:for-each>
preceding-sibling:
<xsl:for-each select="node[not(@group = preceding-sibling::node/@group)]">
<xsl:element name="
</xsl:for-each>
following-sibling:
<xsl:for-each select="node[not(@group = following-sibling::node/@group)]">
<xsl:element name="{@group}
"/>
</xsl:for-each>
</result>
</xsl:template>
</xsl:stylesheet>
Given the (already sorted) input:
<?xml version="1.0"?>
<!-- in2.xml -->
<input>
<node group="a"/>
<node group="a"/>
<node group="a"/>
<node group="b"/>
<node group="b"/>
<node group="c"/>
<node group="c"/>
</input>
The correct result produced by the Xalan interpreter is the three unique groups:
xalan -in in2.xml -xsl bug2.xsl
<result>
preceding:
<a/><b/><c/>
following:
<a/><b/><c/>
preceding-sibling:
<a/><b/><c/>
following-sibling:
<a/><b/><c/>
</result>
XSLTC 2.6.0 produces the wrong nodesets where preceding:: duplicates the first group <a/> while following:: misses the last group <c/>:
xalan -in in2.xml -xsl bug2.xsl -xsltc -v
>>>>>>> Xalan Version Xalan Java 2.6.0, <<<<<<<
<result>
preceding:
<a/><a/><b/><c/>
following:
<a/><b/>
preceding-sibling:
<a/><b/><c/>
following-sibling:
<a/><b/><c/>
</result>
WORKAROUNDS
If the selected nodes are all on the same level, use preceding-sibling:: or following-sibling:: which do not have this bug.
If you must use preceding::, suppress the second node in case it is the same as the first node:
<xsl:variable name="nodes" select="node[not(@group = preceding::node/@group)]"/>
<!-- Workaround for XSLTC 2.6.0 bug. -->
<xsl:for-each select="$nodes[position() != 2 or $nodes[1]/@group != $nodes[2]/@group]">
<xsl:element name="
"/>
</xsl:for-each>
Avoid using following::, or you'll have to invent a way to recuperate the lost last node.