[ 
http://issues.apache.org/jira/browse/XALANC-540?page=comments#action_12318399 ] 

Alain Le Guennec commented on XALANC-540:
-----------------------------------------

David,
I found a little problem in your patch when reviewing it.
It happens in the (quite unlikely) situation where the context node in which 
the absolute location path is evaluated is an empty document.
In that case, the "go to parent" loop will cause a crash (it stops on 
DOCUMENT_FRAGMENT_NODE, but not on DOCUMENT_NODE).
To reproduce the crash, try to execute the following stylesheet in a directory 
with a file called empty.xml containing an invalid document:

<?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:apply-templates select="document('empty.xml')" 
mode="debug">
                </xsl:apply-templates>
        </xsl:template>

        <xsl:template match="/" mode="debug">
                <!-- Here the context node is an empty document... -->
                <xsl:variable name="root" select="/"/>
                <xsl:message>In empty document...</xsl:message>
        </xsl:template>
</xsl:stylesheet>

I would propose the following code:

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*  docContext;
        XalanNode::NodeType   nodeType = context->getNodeType();
        if (nodeType == XalanNode::DOCUMENT_NODE) {
                // The context node is the document itself, nothing to do.
                docContext = context;
        } else {
                // The context node is part of either a non empty document or a 
rtf.
                docContext = context->getOwnerDocument();
#if defined(XALAN_OLD_STYLE_CASTS)
                if (((const XalanDocument*)docContext)->getDocumentElement() == 
0)
#else
                if (static_cast<const 
XalanDocument*>(docContext)->getDocumentElement() == 0)
#endif
                {
                        // This is a special case for RTFs, as the (empty) 
"owner document" is just a factory for the RTF.
                        // Instead, we have to search for the containing 
XalanDocumentFragment node.
                        docContext = context;
                        
                        for(;;)
                        {
                                if (nodeType == 
XalanNode::DOCUMENT_FRAGMENT_NODE)
                                {
                                        break;
                                }
                                else
                                {
                                        docContext =
                                                
DOMServices::getParentOfNode(*docContext);
                                        
                                        nodeType = docContext->getNodeType();
                                        
                                }
                        }
                }
        }
        assert(docContext != 0);

        subQueryResults.addNode(docContext);

        subQueryResults.setDocumentOrder();

        return opPos + argLen + 3;
}

Best regards.
Alain

> XPath absolute location path does not work when the context node was obtained 
> from a result tree fragment through exsl:node-set()
> ---------------------------------------------------------------------------------------------------------------------------------
>
>          Key: XALANC-540
>          URL: http://issues.apache.org/jira/browse/XALANC-540
>      Project: XalanC
>         Type: Bug
>   Components: XPathC
>     Versions: CurrentCVS, 1.8, 1.9
>  Environment: Win2k on ix86.
>     Reporter: Alain Le Guennec
>     Assignee: David Bertoni
>  Attachments: patch.txt
>
> 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(//*)"/><!-- Does not work! -->
>               <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) {
>               docContext = DOMServices::getParentOfNode(*docContext);
>       }
>       assert(docContext != 0);
>       subQueryResults.addNode(docContext);
>       subQueryResults.setDocumentOrder();
>       return opPos + argLen + 3;
> }
> Hope this helps.
> Regards,
> Alain Le Guennec.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to