Hi, Dave,

I have reported a bug to bugzilla: No. 1926, now I can simplify the XSLT to
a more simple one:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template match="/">
        <xsl:apply-templates select="/sss/sss/i" mode="c"/>     
</xsl:template>

<xsl:template match="/sss//*" mode="c"> 
        kk
</xsl:template>

</xsl:stylesheet>

The source file:
<sss>
<sss><i>XML</i></sss>
</sss>

I think it should output "kk" instead of "XML". It seems there is problem in
the pattern matching algorithm of Xalan.

I have made some change to SimpleNodeLocator.cpp, it can fix this problem,
but please verify if my change is right and if it will cause side effects. 

My change was made based on the code of Xalan 1.0, but I find the latest CVS
code still have such bug. Xalan-J also have the same problem.

My change is between #ifdef MFPENG and #endif.





_______________________________________________________
Send a cool gift with your E-Card
http://www.bluemountain.com/giftcenter/

/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in
 *        the documentation and/or other materials provided with the
 *        distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *        if any, must include the following acknowledgment:  
 *               "This product includes software developed by the
 *                Apache Software Foundation (http://www.apache.org/)."
 *        Alternately, this acknowledgment may appear in the software itself,
 *        if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *        not be used to endorse or promote products derived from this
 *        software without prior written permission. For written 
 *        permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache",
 *        nor may "Apache" appear in their name, without prior written
 *        permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file.
#include "SimpleNodeLocator.hpp"



#include <XalanDOM/XalanAttr.hpp>
#include <XalanDOM/XalanElement.hpp>
#include <XalanDOM/XalanNamedNodeMap.hpp>
#include <XalanDOM/XalanNode.hpp>
#include <XalanDOM/XalanDocument.hpp>



#include <DOMSupport/DOMServices.hpp>



#include "FoundIndex.hpp"
#include "NodeRefListBase.hpp"
#include "XObject.hpp"
#include "XObjectFactory.hpp"
#include "XPath.hpp"



SimpleNodeLocator               SimpleNodeLocator::s_defaultInstance;

const XalanDOMString    SimpleNodeLocator::s_emptyString;



SimpleNodeLocator*
SimpleNodeLocator::getDefaultInstance()
{
        return &s_defaultInstance;
}



SimpleNodeLocator::SimpleNodeLocator() :
        XLocator()
{
}



SimpleNodeLocator::~SimpleNodeLocator()
{
}



const XObject*
SimpleNodeLocator::locationPath(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode&                              context, 
                        int                                     opPos)
{
        typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   
BorrowReturnMutableNodeRefList;

        BorrowReturnMutableNodeRefList  mnl(executionContext);

        step(xpath, executionContext, &context, opPos + 2, *mnl.get());

        return executionContext.getXObjectFactory().createNodeSet(mnl);
}



double
SimpleNodeLocator::locationPathPattern(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode&                              context, 
                        int                                     opPos)
{
        double  score = xpath.s_MatchScoreNone;

        stepPattern(xpath, executionContext, &context, opPos + 2, score);

        return score;
}



void
SimpleNodeLocator::step(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        MutableNodeRefList&     queryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // int endStep = xpath.getNextOpPos(opPos);
        const int                       stepType =
                currentExpression.getOpCodeMapValue(opPos);

        int                             argLen = 0;

        typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   
BorrowReturnMutableNodeRefList;

        BorrowReturnMutableNodeRefList  subQueryResults(executionContext);

        bool                            shouldReorder = false;
        bool                            continueStepRecursion = true;

        switch(stepType)
        {
        case XPathExpression::eOP_VARIABLE:
        case XPathExpression::eOP_EXTFUNCTION:
        case XPathExpression::eOP_FUNCTION:
        case XPathExpression::eOP_GROUP:
                argLen = findNodeSet(xpath, executionContext, context, opPos, 
                                                          stepType, *subQueryResults);
                break;

        case XPathExpression::eFROM_ROOT:
                argLen = findRoot(xpath, executionContext, context, opPos, stepType, 
*subQueryResults);
                break;

        case XPathExpression::eFROM_PARENT:
                argLen = findParent(xpath, executionContext, context, opPos, stepType, 
*subQueryResults);
                break;

        case XPathExpression::eFROM_SELF:
                argLen = findSelf(xpath, executionContext, context, opPos, stepType, 
*subQueryResults);
                break;

        case XPathExpression::eFROM_ANCESTORS:
                argLen = findAncestors(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                shouldReorder = true;
                break;

        case XPathExpression::eFROM_ANCESTORS_OR_SELF:
                argLen = findAncestorsOrSelf(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                shouldReorder = true;
                break;

        case XPathExpression::eMATCH_ATTRIBUTE:
                continueStepRecursion = false;
                // fall-through on purpose.

        case XPathExpression::eFROM_ATTRIBUTES:
                argLen = findAttributes(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                break;

        case XPathExpression::eMATCH_ANY_ANCESTOR:
        case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
        case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
                continueStepRecursion = false;
                // fall-through on purpose.

        case XPathExpression::eFROM_CHILDREN:
                argLen = findChildren(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                break;

        case XPathExpression::eFROM_DESCENDANTS:
        case XPathExpression::eFROM_DESCENDANTS_OR_SELF:
                argLen = findDescendants(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                break;

        case XPathExpression::eFROM_FOLLOWING:
                argLen = findFollowing(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                break;

        case XPathExpression::eFROM_FOLLOWING_SIBLINGS:
                argLen = findFollowingSiblings(xpath, executionContext, context, 
opPos, stepType, *subQueryResults);
                break;

        case XPathExpression::eFROM_PRECEDING:
                argLen = findPreceeding(xpath, executionContext, context, opPos, 
stepType, *subQueryResults);
                shouldReorder = true;
                break;

        case XPathExpression::eFROM_PRECEDING_SIBLINGS:
                argLen = findPreceedingSiblings(xpath, executionContext, context, 
opPos, stepType, *subQueryResults);
                shouldReorder = true;
                break;

        case XPathExpression::eFROM_NAMESPACE:
                argLen = findNamespace(xpath, executionContext, context, opPos,  
stepType, *subQueryResults);
                break;

        default:
                argLen = findNodesOnUnknownAxis(xpath, executionContext, context, 
opPos, stepType, *subQueryResults);
                break;
        }

        // Push and pop the PrefixResolver...
        XPathExecutionContext::ContextNodeListSetAndRestore             
theSetAndRestore(
                                                                        
executionContext,
                                                                        
*subQueryResults);

        opPos += argLen;

        int             nextStepType = currentExpression.getOpCodeMapValue(opPos);

        if(XPathExpression::eOP_PREDICATE == nextStepType)
        {
                predicates(xpath,
                                   executionContext,
                                   context,
                                   opPos, 
                                   *subQueryResults,
                                   opPos);

                nextStepType = currentExpression.getOpCodeMapValue(opPos);
        }

        if(XPathExpression::eENDOP != nextStepType && continueStepRecursion == true)
        {
                const unsigned int      nContexts = subQueryResults->getLength();

                for(unsigned int i = 0; i < nContexts; i++)
                {
                        XalanNode* const        node = subQueryResults->item(i);

                        if(0 != node)
                        {
                                BorrowReturnMutableNodeRefList  mnl(executionContext);

                                step(xpath, executionContext, node, opPos, *mnl);

                                if (mnl->getLength() > 0)
                                {
                                        if(queryResults.getLength() == 0)
                                        {
                                                queryResults = *mnl;
                                        }
                                        else
                                        {
                                                queryResults.addNodesInDocOrder(*mnl, 
executionContext);
                                        }
                                }
                        }
                }
        }
        else
        {
                if (shouldReorder == true)
                {
                        queryResults.addNodesInDocOrder(*subQueryResults, 
executionContext);
                }
                else
                {
                        queryResults = *subQueryResults;
                }
        }
}



XalanNode*
SimpleNodeLocator::stepPattern(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        double&                                 scoreHolder)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        const int       startOpPos = opPos;
        const int       stepType = currentExpression.getOpCodeMapValue(opPos);

        const int       endStep = currentExpression.getNextOpCodePosition(opPos);
        int             nextStepType = currentExpression.getOpCodeMapValue(endStep);


        XalanNode*      localContext = context;

        if(XPathExpression::eENDOP != nextStepType)
        {
                // Continue step via recursion...
                localContext = stepPattern(xpath,
                                                                   executionContext,
                                                                   localContext,
                                                                   endStep,
                                                                   scoreHolder);

                if(0 == localContext)
                {
                        scoreHolder = xpath.s_MatchScoreNone;

                }

                if (scoreHolder == xpath.s_MatchScoreNone)
                {
                        // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
                        return 0;
                }

                scoreHolder = xpath.s_MatchScoreOther;

                localContext = executionContext.getParentOfNode(*localContext);

                if(0 == localContext)
                {
                        // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
                        return 0;
                }
        }

        assert(localContext != 0);

        int                     argLen = 0;

        double          score = xpath.s_MatchScoreNone;

        switch(stepType)
        {
        case XPathExpression::eOP_FUNCTION:
                {
                        argLen = currentExpression.getOpCodeLength(opPos);

                        const XObjectGuard              obj(
                                                                                
executionContext.getXObjectFactory(),
                                                                                
xpath.executeMore(localContext, opPos, executionContext));
                        assert(obj.get() != 0);

                        const NodeRefListBase&  nl = obj->nodeset();

                        const unsigned int              len = nl.getLength();

                        score = xpath.s_MatchScoreNone;

                        for(unsigned int i = 0; i < len; i++)
                        {
                                XalanNode* const        n = nl.item(i);

                                score = n == localContext ?
                                        xpath.s_MatchScoreOther : 
xpath.s_MatchScoreNone;

                                if(score == xpath.s_MatchScoreOther)
                                {
                                        localContext = n;

                                        break;
                                }
                        }
                }
                break;

        case XPathExpression::eFROM_ROOT:
                {
                        // $$ ToDO: Can we reduce this to some call on the
                        // XPathExpression interface?
                        argLen =
                                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

                        opPos += 3;

                        const XalanNode::NodeType       nodeType = 
localContext->getNodeType();

                        if (nodeType == XalanNode::DOCUMENT_NODE ||
                                nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
                        {
                                score = XPath::s_MatchScoreOther;
                        }
                #ifdef MFPENG                   
                        else
                        {
                                const int   prevPos = 
currentExpression.getNextOpCodePosition(startOpPos);              
                                const int       prevStepType = 
currentExpression.getOpCodeMapValue(prevPos);
                                
                                if( xpath.s_MatchScoreNone==score  && 
                                        ( 
prevStepType==XPathExpression::eMATCH_ANY_ANCESTOR ||
                                          
prevStepType==XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE ) )
                                {
                                        while(0 != localContext)
                                        {
                                                score = nodeTest(xpath, 
executionContext, localContext, opPos, argLen, stepType);

                                                if(xpath.s_MatchScoreNone != score)
                                                        break;

                                                localContext = 
executionContext.getParentOfNode(*localContext);
                                        }
                                }
                        }
                #endif
                }
                break;

        case XPathExpression::eMATCH_ATTRIBUTE:
                {
                        // $$ ToDO: Can we reduce this to some call on the
                        // XPathExpression interface?
                        argLen =
                                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

                        opPos += 3;

                        score = nodeTest(xpath,
                                                         executionContext,
                                                         localContext,
                                                         opPos,
                                                         argLen,
                                                         
XPathExpression::eFROM_ATTRIBUTES);
                }
                break;

        case XPathExpression::eMATCH_ANY_ANCESTOR:
        case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
                {
                        // $$ ToDO: Can we reduce this to some call on the
                        // XPathExpression interface?
                        argLen =
                                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

                        score = xpath.s_MatchScoreNone;

                        if(localContext->getNodeType() != XalanNode::ATTRIBUTE_NODE)
                        {
                                opPos += 3;

                                while(0 != localContext)
                                {
                                        score = nodeTest(xpath, executionContext, 
localContext, opPos, argLen, stepType);

                                        if(xpath.s_MatchScoreNone != score)
                                                break;

                                        localContext = 
executionContext.getParentOfNode(*localContext);
                                }
                        }
                }
                break;

        case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
                // $$ ToDO: Can we reduce this to some call on the
                // XPathExpression interface?
                argLen =
                                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

                if(localContext->getNodeType() == XalanNode::ATTRIBUTE_NODE)
                {
                        score = xpath.s_MatchScoreNone;
                }
                else
                {
                        opPos += 3;

                #ifdef MFPENG                   
                        const int   prevPos = 
currentExpression.getNextOpCodePosition(startOpPos);              
                        const int       prevStepType = 
currentExpression.getOpCodeMapValue(prevPos);
                        
                        if( prevStepType==XPathExpression::eMATCH_ANY_ANCESTOR ||
                                
prevStepType==XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE ) 
                        {
                                while(0 != localContext)
                                {
                                        score = nodeTest(xpath, executionContext, 
localContext, opPos, argLen, stepType);

                                        if(xpath.s_MatchScoreNone != score)
                                                break;

                                        localContext = 
executionContext.getParentOfNode(*localContext);
                                }
                        }
                        else
                #endif
                        score = nodeTest(xpath, executionContext, localContext, opPos, 
argLen, stepType);
                }
                break;

        default:
                // $$ ToDO: Can we reduce this to some call on the
                // XPathExpression interface?
                argLen =
                                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

                opPos += 3;

                score = xpath.s_MatchScoreNone;
          
                executionContext.error("unknown match operation!", localContext);
                break;
        }

        opPos += argLen;

        nextStepType = currentExpression.getOpCodeMapValue(opPos);

        if(score != xpath.s_MatchScoreNone && XPathExpression::eOP_PREDICATE == 
nextStepType)
        {
                score = xpath.s_MatchScoreOther;

                // Execute the xpath.predicates, but if we have an index, then we have 
                // to start over and do a search from the parent.  It would be nice 
                // if I could sense this condition earlier...
                try
                {
                        executionContext.setThrowFoundIndex(true);

                        // $$$ ToDo: Why is this variable introduced?
                        int startPredicates = opPos;
                        opPos = startPredicates;

                        while(XPathExpression::eOP_PREDICATE == nextStepType)
                        {
                                const XObjectGuard              pred(
                                                                                
executionContext.getXObjectFactory(),
                                                                                
xpath.predicate(localContext, opPos, executionContext));
                                assert(pred.get() != 0);

                                if(XObject::eTypeNumber == pred->getType())
                                {
                                        score = handleFoundIndex(xpath, 
executionContext, localContext, startOpPos);
                                }
                                else if(pred->boolean() == false)
                                {
                                        score = xpath.s_MatchScoreNone;

                                        break; // from while(xpath.OP_PREDICATE == 
nextStepType)
                                }

                                opPos = currentExpression.getNextOpCodePosition(opPos);
                                nextStepType = 
currentExpression.getOpCodeMapValue(opPos);
                        }

                        executionContext.setThrowFoundIndex(false);
                }
                catch(const FoundIndex&)
                {
                        score = handleFoundIndex(xpath, executionContext, 
localContext, startOpPos);
                }
        }

        if (scoreHolder == xpath.s_MatchScoreNone || 
        score == xpath.s_MatchScoreNone)
        {
                scoreHolder = score;
        }

        return score == xpath.s_MatchScoreNone ? 0 : localContext;
}



double
SimpleNodeLocator::handleFoundIndex(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              localContext, 
                        int                                     startOpPos)
{
        // We have an index somewhere in our pattern.  So, we have 
        // to do a full search for our step, using the parent as 
        // localContext, then see if the current localContext is found in the 
        // node set.  Seems crazy, but, so far, it seems like the 
        // easiest way.
        executionContext.setThrowFoundIndex(false);

        XalanNode* const        parentContext =
                                executionContext.getParentOfNode(*localContext);

        typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   
BorrowReturnMutableNodeRefList;

        BorrowReturnMutableNodeRefList  mnl(executionContext);

        step(xpath, executionContext, parentContext, startOpPos, *mnl);

        if (mnl->indexOf(localContext) == MutableNodeRefList::npos)
        {
                return XPath::s_MatchScoreNone;
        }
        else
        {
                return XPath::s_MatchScoreOther;
        }
}



int
SimpleNodeLocator::findNodeSet(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     /* stepType */,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();


        const XObjectGuard              obj(
                                executionContext.getXObjectFactory(),
                                xpath.executeMore(context, opPos, executionContext));

        const NodeRefListBase&  nl = obj->nodeset();

        // $$$ ToDo: Should this be adding in doc order?
        subQueryResults.addNodes(nl);

        return currentExpression.getOpCodeLength(opPos);
}



int
SimpleNodeLocator::findRoot(
                        const XPath&                    xpath,
                        XPathExecutionContext&  /* executionContext */,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     /* stepType */,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        XalanNode* const        docContext = XalanNode::DOCUMENT_NODE == 
context->getNodeType() ?
                                                                        context :
                                                                        
context->getOwnerDocument();
        assert(docContext != 0);

        subQueryResults.addNode(docContext);

        return argLen + 3;
}



int
SimpleNodeLocator::findParent(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        XalanNode* const        theParent = executionContext.getParentOfNode(*context);

        if(0 != theParent)
        {
                if(argLen > 0)
                {
                        const double    score = nodeTest(xpath,
                                                                                       
  executionContext,
                                                                                       
  theParent,
                                                                                       
  opPos,
                                                                                       
  argLen,
                                                                                       
  stepType);

                        if(xpath.s_MatchScoreNone != score)
                        {
                                subQueryResults.addNode(theParent);
                        }
                }
                else
                {
                        subQueryResults.addNode(theParent);
                }
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findSelf(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        if(argLen > 0)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 
context,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(context);
                }
        }
        else
        {
                subQueryResults.addNode(context);
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findAncestors(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        XalanNode*                              contextNode =
                executionContext.getParentOfNode(*context);

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        while(0 != contextNode)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 
contextNode,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(contextNode);
                }

                contextNode = executionContext.getParentOfNode(*contextNode);
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findAncestorsOrSelf(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        // $$ ToDO: Can this function be reduced to calling
        // findSelf() and findAncestors()?      I would think so...

        const XPathExpression&  currentExpression =
                xpath.getExpression();

        XalanNode*                              contextNode = context;

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        while(0 != contextNode)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 
contextNode,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(contextNode);
                }

                contextNode = executionContext.getParentOfNode(*contextNode);
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findAttributes(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        if(0 != context && context->getNodeType() == XalanNode::ELEMENT_NODE)
        {
                const XalanElement* const               e =
#if defined(XALAN_OLD_STYLE_CASTS)
                                        (const XalanElement*)context;
#else
                                        static_cast<const XalanElement*>(context);
#endif

                const XalanNamedNodeMap* const  attributeList = e->getAttributes();

                if(attributeList != 0) 
                {
                        opPos += 3;

                        const unsigned int      nAttrs = attributeList->getLength();

                        for(unsigned int j = 0; j < nAttrs; j++)
                        {
                                XalanNode* const        theNode = 
attributeList->item(j);
                                assert(theNode != 0 && theNode->getNodeType() == 
XalanNode::ATTRIBUTE_NODE);

                                const double    score = nodeTest(xpath,
                                                                                       
          executionContext,
                                                                                       
          theNode,
                                                                                       
          opPos,
                                                                                       
          argLen,
                                                                                       
          stepType);

                                if(xpath.s_MatchScoreNone != score)
                                {
                                        subQueryResults.addNode(theNode);
                                }
                        }
                }
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findChildren(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        XalanNode*      child = context->getFirstChild();

        while(0 != child)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 child,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(child);
                }

                child = child->getNextSibling();
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findDescendants(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        // Perform a pre-order traversal of descendents.
        // Note that I would like to be able to do optimization here 
        // where if I have a simple tag name node test, I would 
        // like to be able to call 
        // ((Element)context).getElementsByTagName(m_token).
        // One problem is that it would return a NodeList, not a 
        // NodeListImpl.
        /*
        if(lookahead('[', 1) || lookahead('(', 1) 
        || (Node.ELEMENT_NODE != context.getNodeType()))
        {
        */
        XalanNode*      pos = context;

        while(0 != pos)
        {                                       
                if(stepType == XPathExpression::eFROM_DESCENDANTS_OR_SELF ||
                   context != pos)
                {
                        const double    score = nodeTest(xpath,
                                                                                       
  executionContext,
                                                                                       
  pos,
                                                                                       
  opPos,
                                                                                       
  argLen,
                                                                                       
  stepType);

                        if(xpath.s_MatchScoreNone != score)
                        {
                                subQueryResults.addNode(pos);
                        }
                }

                XalanNode*      nextNode = pos->getFirstChild();

                while(0 == nextNode)
                {
                        if(context == pos)
                                break;

                        nextNode = pos->getNextSibling();

                        if(0 == nextNode)
                        {
                                pos = executionContext.getParentOfNode(*pos);

                                if(context == pos || pos == 0)
                                {
                                        nextNode = 0;
                                        break;
                                }
                        }
                }

                pos = nextNode;
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findFollowing(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        // What fun...
        XalanDocument* const    doc = context->getOwnerDocument();

        XalanNode*                              pos = context;

        while(0 != pos)
        {
                XalanNode*      nextNode = 0;

                if(pos != context)
                {
                        const double    score = nodeTest(xpath,
                                                                                       
  executionContext,
                                                                                       
  pos,
                                                                                       
  opPos,
                                                                                       
  argLen,
                                                                                       
  stepType);

                        if(xpath.s_MatchScoreNone != score)
                        {
                                subQueryResults.addNodeInDocOrder(pos, 
executionContext);
                        }

                        nextNode = pos->getFirstChild();
                }
                else
                {
                        nextNode = 0;
                }

                while(0 == nextNode)
                {
                        // This requires some explanation.  pos could be an attribute
                        // node, so getNextSibling() will always return 0.  In that
                        // case, I want to continue the search with the first child of
                        // the owner element, as if attribute nodes are children which
                        // are always _before_ the first child element.  I don't have 
to
                        // consider following attributes, since they _never_ match the
                        // following axis.
                        if (pos->getNodeType() == XalanNode::ATTRIBUTE_NODE)
                        {
                                assert(executionContext.getParentOfNode(*pos) != 0);

                                nextNode = 
executionContext.getParentOfNode(*pos)->getFirstChild();
                        }
                        else
                        {
                                nextNode = pos->getNextSibling();
                        }

                        if(0 == nextNode)
                        {
                                pos = executionContext.getParentOfNode(*pos);

                                if(doc == pos || 0 == pos)
                                {
                                        nextNode = 0;

                                        break;
                                }
                        }
                }

                pos = nextNode;
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findFollowingSiblings(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        XalanNode*      pos = context->getNextSibling();

        while(0 != pos)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 pos,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(pos);
                }

                pos = pos->getNextSibling();
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findPreceeding(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        // Ugh.  Reverse document order, no parents, I guess.
        XalanDocument* const    doc = context->getOwnerDocument();

        XalanNode*                              pos = doc;

        // If the context node is an attribute, we need to perform some
        // magic to stop the search at the appropriate point, which is when
        // we arrive back at the parent.
        const bool                              contextIsAttribute =
                        context->getNodeType() == XalanNode::ATTRIBUTE_NODE ? true : 
false;

        const XalanNode* const  theAttributeContextParent =
                contextIsAttribute == true ? 
executionContext.getParentOfNode(*context) : 0;

        while(0 != pos)
        {
                if(context == pos)
                {
                        break;
                }

                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 pos,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        // Ugh. If I could think a little better tonight, I'm
                        // sure there's a better way to check for the parent.
                        bool            isParent = false;

                        XalanNode*      parent = 
executionContext.getParentOfNode(*context);

                        while(0 != parent)
                        {
                                if(parent == pos)
                                {
                                        isParent = true;
                                        break;
                                }

                                parent = executionContext.getParentOfNode(*parent);
                        }

                        if(isParent == false)
                        {
                                subQueryResults.insertNode(pos, 0);
                        }
                }

                XalanNode*      nextNode = 0;

                // Check to see if we're back at the attribute context node's
                // parent, in which case, we should stop.
                if (contextIsAttribute == true &&
                        pos == theAttributeContextParent)
                {
                        nextNode = context;
                }
                else
                {
                        nextNode = pos->getFirstChild();
                }

                while(0 == nextNode)
                {
                        nextNode = pos->getNextSibling();

                        if(0 == nextNode)
                        {
                                pos = executionContext.getParentOfNode(*pos);

                                if(doc == pos)
                                {
                                        nextNode = 0;
                                        break;
                                }
                        }
                }

                pos = nextNode;
        }

        return argLen + 3;
}


int
SimpleNodeLocator::findPreceedingSiblings(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        XalanNode*      pos = context->getPreviousSibling();

        while(0 != pos)
        {
                const double    score = nodeTest(xpath,
                                                                                 
executionContext,
                                                                                 pos,
                                                                                 opPos,
                                                                                 
argLen,
                                                                                 
stepType);

                if(xpath.s_MatchScoreNone != score)
                {
                        subQueryResults.addNode(pos);
                }

                pos = pos->getPreviousSibling();
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findNamespace(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     subQueryResults)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        opPos += 3;

        if(context != 0 && context->getNodeType() == XalanNode::ELEMENT_NODE)
        {
                const XalanNamedNodeMap* const  attributeList =
                        context->getAttributes();

                if(attributeList != 0) 
                {
                        const unsigned int      nAttrs = attributeList->getLength();

                        for(unsigned int i = 0; i < nAttrs; ++i)
                        {
                                XalanNode* const        attr = attributeList->item(i);

                                if(nodeTest(xpath,
                                                        executionContext,
                                                        attr,
                                                        opPos,
                                                        argLen,
                                                        stepType) != 
xpath.s_MatchScoreNone)
                                {
                                        subQueryResults.addNode(attr);
                                        // If we have an attribute name here, we can 
quit.
                                }
                        }
                }
        }

        return argLen + 3;
}



int
SimpleNodeLocator::findNodesOnUnknownAxis(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     stepType,
                        MutableNodeRefList&     /* subQueryResults */)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        // $$ ToDO: Can we reduce this to some call on the
        // XPathExpression interface?
        const int       argLen =
                currentExpression.getOpCodeMapValue(opPos + 
XPathExpression::s__opCodeMapLengthIndex + 1) - 3;

        executionContext.error("unknown axis: " + stepType, context);

        return argLen + 3;
}



double
SimpleNodeLocator::nodeTest(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              context, 
                        int                                     opPos,
                        int                                     argLen,
                        int                                     stepType)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        double score = xpath.s_MatchScoreNone;

        const int       testType = currentExpression.getOpCodeMapValue(opPos);

        const XalanNode::NodeType       nodeType = context->getNodeType();

        opPos++;

        switch(testType)
        {
        case XPathExpression::eNODETYPE_COMMENT:
                if (XalanNode::COMMENT_NODE == nodeType)
                {
                        score = xpath.s_MatchScoreNodeTest;
                }
                break;

        case XPathExpression::eNODETYPE_TEXT:
                if ((XalanNode::CDATA_SECTION_NODE == nodeType ||
                         XalanNode::TEXT_NODE == nodeType) &&
                        executionContext.shouldStripSourceNode(*context) == false)
                {
                          score = xpath.s_MatchScoreNodeTest;
                }
          break;

        case XPathExpression::eNODETYPE_PI:
                if(XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType)
                {
                        if(argLen == 1)
                        {
                                score = xpath.s_MatchScoreNodeTest;
                        }
                        else if(argLen == 2)
                        {
                                const int                               tokenPosition =
                                        currentExpression.getOpCodeMapValue(opPos);

                                const XObject* const    name =
                                        currentExpression.getToken(tokenPosition);
                                assert(name != 0);

                                if (equals(context->getNodeName(), name->str()) == 
true)
                                {
                                        score = xpath.s_MatchScoreQName;
                                }
                        }
                        else
                        {
                                executionContext.error("Arg length of 
processing-instruction() node test is incorrect!");
                        }
                }

                break;

        case XPathExpression::eNODETYPE_NODE:
                if (nodeType == XalanNode::CDATA_SECTION_NODE ||
                        nodeType == XalanNode::TEXT_NODE)
                {
                        if (executionContext.shouldStripSourceNode(*context) == false)
                        {
                                score = xpath.s_MatchScoreNodeTest;
                        }
                }
                else
                {
                        score = xpath.s_MatchScoreNodeTest;
                }
                break;

        case XPathExpression::eNODETYPE_ROOT:
                if (XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType ||
                        XalanNode::DOCUMENT_NODE == nodeType)
                {
                        score =  xpath.s_MatchScoreOther;
                }
                break;

        case XPathExpression::eNODENAME:
                {
                        if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType == 
XalanNode::ELEMENT_NODE)
                        {
                                bool                                    test = false;

                                int                                     queueIndex = 
currentExpression.getOpCodeMapValue(opPos);

                                const XalanDOMString&   targetNS = queueIndex >= 0 ?
                                                                                
currentExpression.getToken(queueIndex)->str() :
                                                                                       
 s_emptyString;

                                opPos++;

                                // From the draft: "Two expanded names are equal if 
they 
                                // have the same local part, and either both have no 
URI or 
                                // both have the same URI."
                                // "A node test * is true for any node of the 
principal node type. 
                                // For example, child::* will select all element 
children of the 
                                // context node, and attribute::* will select all 
attributes of 
                                // the context node."
                                // "A node test can have the form NCName:*. In this 
case, the prefix 
                                // is expanded in the same way as with a QName using 
the context 
                                // namespace declarations. The node test will be true 
for any node 
                                // of the principal type whose expanded name has the 
URI to which 
                                // the prefix expands, regardless of the local part of 
the name."
                                const bool      isTotallyWild =
                                                        0 == length(targetNS) &&
                                                        
currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eELEMWILDCARD;

                                const bool      processNamespaces = 
executionContext.getProcessNamespaces();

                                bool            didMatchNS = false;

                                if(isTotallyWild == false && processNamespaces == true)
                                {
                                        const XalanDOMString    contextNS = 
executionContext.getNamespaceOfNode(*context);

                                        if(0 != length(targetNS) && 0 != 
length(contextNS))
                                        {
                                                test = equals(contextNS, targetNS);

                                                didMatchNS = true;
                                        }
                                        else
                                        {
                                                test = XPathExpression::eELEMWILDCARD 
== queueIndex || 
                                                   (0 == length(contextNS) && 0 == 
length(targetNS));
                                        }
                                }
                                else
                                {
                                        test = true;
                                }

                                queueIndex = 
currentExpression.getOpCodeMapValue(opPos);

                                if(test == true)
                                {
                                        const XalanDOMString&   targetLocalName =
                                                                queueIndex >= 0 ? 
currentExpression.getToken(queueIndex)->str() : s_emptyString;

                                        switch(nodeType)
                                        {
                                        case XalanNode::ATTRIBUTE_NODE:
                                                if(stepType == 
XPathExpression::eFROM_ATTRIBUTES ||
                                                        stepType == 
XPathExpression::eFROM_NAMESPACE)
                                                {
                                                        assert(context->getNodeType() 
== XalanNode::ATTRIBUTE_NODE);

                                                        const XalanDOMString    
attrName =
                                                                                
context->getNodeName();

                                                        const bool                     
         isNamespace =
                                                                        
startsWith(attrName, DOMServices::s_XMLNamespaceWithSeparator) ||
                                                                        
equals(attrName, DOMServices::s_XMLNamespace);

                                                        
if(XPathExpression::eELEMWILDCARD == queueIndex)
                                                        {
                                                                if(stepType == 
XPathExpression::eFROM_ATTRIBUTES)
                                                                {
                                                                        if 
(isNamespace == false)
                                                                        {
                                                                                score 
= xpath.s_MatchScoreNodeTest;
                                                                        }
                                                                }
                                                                else
                                                                {
                                                                        if 
(isNamespace == true)
                                                                        {
                                                                                score 
= xpath.s_MatchScoreNodeTest;
                                                                        }
                                                                }
                                                        }
                                                        else
                                                        {
                                                                if(stepType == 
XPathExpression::eFROM_ATTRIBUTES)
                                                                {
                                                                        if 
(isNamespace == false)
                                                                        {
                                                                                const 
XalanDOMString    localAttrName =
                                                                                       
 executionContext.getLocalNameOfNode(*context);

                                                                                if 
(equals(localAttrName, targetLocalName) == true)
                                                                                {
                                                                                       
 score = xpath.s_MatchScoreQName;
                                                                                }
                                                                        }
                                                                }
                                                                else
                                                                {
                                                                        if 
(isNamespace == true)
                                                                        {
                                                                                const 
XalanAttr* const  theAttrNode =
#if defined(XALAN_OLD_STYLE_CASTS)
                                                                                       
 (const XalanAttr*)context;
#else
                                                                                       
 static_cast<const XalanAttr*>(context);
#endif
                                                                                
assert(theAttrNode != 0);

                                                                                const 
XalanDOMString    theNamespace =
                                                                                       
                 theAttrNode->getValue();

                                                                                if 
(equals(theNamespace, targetLocalName) == true)
                                                                                {
                                                                                       
 score = xpath.s_MatchScoreQName;
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                                break;

                                        case XalanNode::ELEMENT_NODE:
                                                if(stepType != 
XPathExpression::eFROM_ATTRIBUTES)
                                                {
                                                        
if(XPathExpression::eELEMWILDCARD == queueIndex)
                                                        {
                                                                score = didMatchNS == 
true ?
                                                                        
XPath::s_MatchScoreNSWild : XPath::s_MatchScoreNodeTest;
                                                        }
                                                        else
                                                        {
                                                                if 
(equals(executionContext.getLocalNameOfNode(*context),
                                                                                   
targetLocalName) == true)
                                                                {
                                                                        score = 
xpath.s_MatchScoreQName;
                                                                }
                                                        }
                                                }
                                                break;

                                        default:
                                                // Trying to match on anything else 
causes nasty bugs.
                                                break;
                                        } // end switch(nodeType)
                                } // end if(test)
                        } // end if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType 
== XalanNode::ELEMENT_NODE)
                } // end case XPathExpression::eNODENAME
                break;

        default:
                break;
        } // end switch(testType)

        return score;
}



void
SimpleNodeLocator::predicates(
                        const XPath&                    xpath,
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              /* context */, 
                        int                                     opPos,
                        MutableNodeRefList&     subQueryResults,
                        int&                                    endPredicatesPos)
{
        const XPathExpression&  currentExpression =
                xpath.getExpression();

        int                                     nextStepType =
                        currentExpression.getOpCodeMapValue(opPos);

        while(XPathExpression::eOP_PREDICATE == nextStepType)
        {
                unsigned int            i = 0;

                const unsigned int      theLength = subQueryResults.getLength();

                while(i < theLength)
                {
                        XalanNode* const        theNode = subQueryResults.item(i);
                        assert(theNode != 0);

                        const XObjectGuard              pred(
                                                executionContext.getXObjectFactory(),
                                                xpath.predicate(theNode, opPos, 
executionContext));
                        assert(pred.get() != 0);

                        // Remove any node that doesn't satisfy the predicate.
                        if(XObject::eTypeNumber == pred->getType() &&
                                        i + 1 != pred->num() ||
                           pred->boolean() == false)
                        {
                                // Set the node to 0.  After we're done,
                                // we'll clear it out.
                                subQueryResults.setNode(i, 0);
                        }

                        ++i;
                }

                // Clear out any null entries...
                subQueryResults.clearNulls();

                opPos = currentExpression.getNextOpCodePosition(opPos);

                nextStepType = currentExpression.getOpCodeMapValue(opPos);

                if(XPathExpression::eOP_PREDICATE == nextStepType)
                {
                        executionContext.setContextNodeList(subQueryResults);

                        // Don't break, loop 'till end so that opPos will be set to 
end.
                        // if(0 == subQueryResults.getLength())
                        //      break;
                }
        }

        endPredicatesPos = opPos;
}

Reply via email to