Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
CurrentCVS, 1.8, 1.9
-
None
-
Win2k on ix86.
Description
XPath absolute location path does not work when the context node was obtained from a result tree fragment through exsl:node-set().
Consider the following stylesheet (applied to any input document, the actual input does not matter):
<?xml version="1.0" encoding = "ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common">
<xsl:template match="/">
<xsl:variable name="var-rtf">
<foo>
<bar/>
</foo>
</xsl:variable>
<xsl:variable name="var" select="exsl:node-set($var-rtf)/*"/>
<xsl:apply-templates select="$var">
<xsl:with-param name="root" select="$var"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="foo">
<xsl:param name="root"/>
<!-- Here the context node belongs to the tree fragment -->
<xsl:variable name="count-from-implicit-root" select="count(//*)"/><Unable to render embedded object: File (-- Does not work) not found. -->
<xsl:variable name="count-from-explicit-root" select="count($root/descendant-or-self::node())"/><!-- OK -->
<xsl:choose>
<xsl:when test="$count-from-implicit-root = $count-from-explicit-root">
<xsl:message>No bug: There are <xsl:value-of select="$count-from-implicit-root"/> elements in the tree fragment.</xsl:message>
</xsl:when>
<xsl:otherwise>
<!-- Navigation from the root of the tree fragment does not work. -->
<xsl:message>Bug: There should be <xsl:value-of select="$count-from-explicit-root"/> elements in the tree fragment, not <xsl:value-of select="$count-from-implicit-root"/>.</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Executing this stylesheet prints
"Bug: There should be 2 elements in the tree fragment, not 0."
where as it should print
"No bug: There are 2 elements in the tree fragment."
Apparently, the error lies in XPath.cpp, in function XPath::findRoot().
I think it's because the XalanNodes representing the elements are connected
to the XalanSourceTreeDocumentFragment, not to its owning XalanSourceTreeDocument.
In this particular case, the actual root is not a DOCUMENT_NODE, but a DOCUMENT_FRAGMENT_NODE.
Here is modified version of findRoot() that apparently fixes the problem (old code kept as comment):
XPath::OpCodeMapPositionType
XPath::findRoot(
XPathExecutionContext& /* executionContext */,
XalanNode* context,
OpCodeMapPositionType opPos,
OpCodeMapValueType /* stepType */,
MutableNodeRefList& subQueryResults) const
{
assert(subQueryResults.empty() == true);
const XPathExpression& currentExpression = getExpression();
const OpCodeMapValueType argLen =
currentExpression.getOpCodeArgumentLength(opPos);
// XalanNode* const docContext = XalanNode::DOCUMENT_NODE == context->getNodeType() ?
// context :
// context->getOwnerDocument();
XalanNode* docContext = context;
while (docContext->getNodeType() != XalanNode::DOCUMENT_NODE && docContext->getNodeType() != XalanNode::DOCUMENT_FRAGMENT_NODE)
assert(docContext != 0);
subQueryResults.addNode(docContext);
subQueryResults.setDocumentOrder();
return opPos + argLen + 3;
}
Hope this helps.
Regards,
Alain Le Guennec.