Beispiel #1
0
nsresult
PredicateList::evaluatePredicates(txNodeSet* nodes,
                                  txIMatchContext* aContext)
{
    NS_ASSERTION(nodes, "called evaluatePredicates with nullptr NodeSet");
    nsresult rv = NS_OK;

    uint32_t i, len = mPredicates.Length();
    for (i = 0; i < len && !nodes->isEmpty(); ++i) {
        txNodeSetContext predContext(nodes, aContext);
        /*
         * add nodes to newNodes that match the expression
         * or, if the result is a number, add the node with the right
         * position
         */
        int32_t index = 0;
        while (predContext.hasNext()) {
            predContext.next();
            RefPtr<txAExprResult> exprResult;
            rv = mPredicates[i]->evaluate(&predContext,
                                          getter_AddRefs(exprResult));
            NS_ENSURE_SUCCESS(rv, rv);

            // handle default, [position() == numberValue()]
            if (exprResult->getResultType() == txAExprResult::NUMBER) {
                if ((double)predContext.position() == exprResult->numberValue()) {
                    nodes->mark(index);
                }
            }
            else if (exprResult->booleanValue()) {
                nodes->mark(index);
            }
            ++index;
        }
        // sweep the non-marked nodes
        nodes->sweep();
    }

    return NS_OK;
}
bool txStepPattern::matches(const txXPathNode& aNode, txIMatchContext* aContext)
{
    NS_ASSERTION(mNodeTest, "Internal error");

    if (!mNodeTest->matches(aNode, aContext))
        return false;

    txXPathTreeWalker walker(aNode);
    if ((!mIsAttr &&
         txXPathNodeUtils::isAttribute(walker.getCurrentPosition())) ||
        !walker.moveToParent()) {
        return false;
    }
    if (isEmpty()) {
        return true;
    }

    /*
     * Evaluate Predicates
     *
     * Copy all siblings/attributes matching mNodeTest to nodes
     * Up to the last Predicate do
     *  Foreach node in nodes
     *   evaluate Predicate with node as context node
     *   if the result is a number, check the context position,
     *    otherwise convert to bool
     *   if result is true, copy node to newNodes
     *  if aNode is not member of newNodes, return false
     *  nodes = newNodes
     *
     * For the last Predicate, evaluate Predicate with aNode as
     *  context node, if the result is a number, check the position,
     *  otherwise return the result converted to boolean
     */

    // Create the context node set for evaluating the predicates
    nsRefPtr<txNodeSet> nodes;
    nsresult rv = aContext->recycler()->getNodeSet(getter_AddRefs(nodes));
    NS_ENSURE_SUCCESS(rv, false);

    bool hasNext = mIsAttr ? walker.moveToFirstAttribute() :
                               walker.moveToFirstChild();
    while (hasNext) {
        if (mNodeTest->matches(walker.getCurrentPosition(), aContext)) {
            nodes->append(walker.getCurrentPosition());
        }
        hasNext = mIsAttr ? walker.moveToNextAttribute() :
                            walker.moveToNextSibling();
    }

    Expr* predicate = mPredicates[0];
    nsRefPtr<txNodeSet> newNodes;
    rv = aContext->recycler()->getNodeSet(getter_AddRefs(newNodes));
    NS_ENSURE_SUCCESS(rv, false);

    PRUint32 i, predLen = mPredicates.Length();
    for (i = 1; i < predLen; ++i) {
        newNodes->clear();
        bool contextIsInPredicate = false;
        txNodeSetContext predContext(nodes, aContext);
        while (predContext.hasNext()) {
            predContext.next();
            nsRefPtr<txAExprResult> exprResult;
            rv = predicate->evaluate(&predContext, getter_AddRefs(exprResult));
            NS_ENSURE_SUCCESS(rv, false);

            switch(exprResult->getResultType()) {
                case txAExprResult::NUMBER:
                    // handle default, [position() == numberValue()]
                    if ((double)predContext.position() ==
                        exprResult->numberValue()) {
                        const txXPathNode& tmp = predContext.getContextNode();
                        if (tmp == aNode)
                            contextIsInPredicate = true;
                        newNodes->append(tmp);
                    }
                    break;
                default:
                    if (exprResult->booleanValue()) {
                        const txXPathNode& tmp = predContext.getContextNode();
                        if (tmp == aNode)
                            contextIsInPredicate = true;
                        newNodes->append(tmp);
                    }
                    break;
            }
        }
        // Move new NodeSet to the current one
        nodes->clear();
        nodes->append(*newNodes);
        if (!contextIsInPredicate) {
            return false;
        }
        predicate = mPredicates[i];
    }
    txForwardContext evalContext(aContext, aNode, nodes);
    nsRefPtr<txAExprResult> exprResult;
    rv = predicate->evaluate(&evalContext, getter_AddRefs(exprResult));
    NS_ENSURE_SUCCESS(rv, false);

    if (exprResult->getResultType() == txAExprResult::NUMBER)
        // handle default, [position() == numberValue()]
        return ((double)evalContext.position() == exprResult->numberValue());

    return exprResult->booleanValue();
} // matches