Exemplo n.º 1
0
/**
 * Selects from the descendants of the context node
 * all nodes that match the Expr
**/
nsresult
PathExpr::evalDescendants(Expr* aStep, const txXPathNode& aNode,
                          txIMatchContext* aContext, txNodeSet* resNodes)
{
    txSingleNodeContext eContext(aNode, aContext);
    nsRefPtr<txAExprResult> res;
    nsresult rv = aStep->evaluate(&eContext, getter_AddRefs(res));
    NS_ENSURE_SUCCESS(rv, rv);

    if (res->getResultType() != txAExprResult::NODESET) {
        //XXX ErrorReport: report nonnodeset error
        return NS_ERROR_XSLT_NODESET_EXPECTED;
    }

    txNodeSet* oldSet = static_cast<txNodeSet*>
                                   (static_cast<txAExprResult*>(res));
    nsRefPtr<txNodeSet> newSet;
    rv = aContext->recycler()->getNonSharedNodeSet(oldSet,
                                                   getter_AddRefs(newSet));
    NS_ENSURE_SUCCESS(rv, rv);

    resNodes->addAndTransfer(newSet);

    MBool filterWS = aContext->isStripSpaceAllowed(aNode);

    txXPathTreeWalker walker(aNode);
    if (!walker.moveToFirstChild()) {
        return NS_OK;
    }

    do {
        const txXPathNode& node = walker.getCurrentPosition();
        if (!(filterWS && txXPathNodeUtils::isText(node) &&
              txXPathNodeUtils::isWhitespace(node))) {
            rv = evalDescendants(aStep, node, aContext, resNodes);
            NS_ENSURE_SUCCESS(rv, rv);
        }
    } while (walker.moveToNextSibling());

    return NS_OK;
} //-- evalDescendants
Exemplo n.º 2
0
already_AddRefed<XPathResult>
XPathExpression::EvaluateWithContext(nsINode& aContextNode,
                                     uint32_t aContextPosition,
                                     uint32_t aContextSize,
                                     uint16_t aType,
                                     XPathResult* aInResult,
                                     ErrorResult& aRv)
{
    if (aContextPosition > aContextSize) {
        aRv.Throw(NS_ERROR_FAILURE);
        return nullptr;
    }

    if (!nsContentUtils::LegacyIsCallerNativeCode() &&
        !nsContentUtils::CanCallerAccess(&aContextNode))
    {
        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
        return nullptr;
    }

    if (mCheckDocument) {
        nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
        if (doc != aContextNode.OwnerDoc()) {
            aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
            return nullptr;
        }
    }

    uint16_t nodeType = aContextNode.NodeType();

    if (nodeType == nsIDOMNode::TEXT_NODE ||
        nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
        nsCOMPtr<nsIDOMCharacterData> textNode =
            do_QueryInterface(&aContextNode);
        if (!textNode) {
            aRv.Throw(NS_ERROR_FAILURE);
            return nullptr;
        }

        uint32_t textLength;
        textNode->GetLength(&textLength);
        if (textLength == 0) {
            aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
            return nullptr;
        }

        // XXX Need to get logical XPath text node for CDATASection
        //     and Text nodes.
    }
    else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
             nodeType != nsIDOMNode::ELEMENT_NODE &&
             nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
             nodeType != nsIDOMNode::COMMENT_NODE &&
             nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
        return nullptr;
    }

    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
    if (!contextNode) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
                             mRecycler);
    RefPtr<txAExprResult> exprResult;
    aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
    if (aRv.Failed()) {
        return nullptr;
    }

    uint16_t resultType = aType;
    if (aType == XPathResult::ANY_TYPE) {
        short exprResultType = exprResult->getResultType();
        switch (exprResultType) {
            case txAExprResult::NUMBER:
                resultType = XPathResult::NUMBER_TYPE;
                break;
            case txAExprResult::STRING:
                resultType = XPathResult::STRING_TYPE;
                break;
            case txAExprResult::BOOLEAN:
                resultType = XPathResult::BOOLEAN_TYPE;
                break;
            case txAExprResult::NODESET:
                resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
                break;
            case txAExprResult::RESULT_TREE_FRAGMENT:
                aRv.Throw(NS_ERROR_FAILURE);
                return nullptr;
        }
    }

    RefPtr<XPathResult> xpathResult = aInResult;
    if (!xpathResult) {
        xpathResult = new XPathResult(&aContextNode);
    }

    aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode);

    return xpathResult.forget();
}
Exemplo n.º 3
0
/**
 * Evaluates this Expr based on the given context node and processor state
 * @param context the context node for evaluation of this Expr
 * @param ps the ContextState containing the stack information needed
 * for evaluation
 * @return the result of the evaluation
**/
nsresult
PathExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
{
    *aResult = nsnull;

    // We need to evaluate the first step with the current context since it
    // can depend on the context size and position. For example:
    // key('books', concat('book', position()))
    nsRefPtr<txAExprResult> res;
    nsresult rv = mItems[0].expr->evaluate(aContext, getter_AddRefs(res));
    NS_ENSURE_SUCCESS(rv, rv);

    NS_ENSURE_TRUE(res->getResultType() == txAExprResult::NODESET,
                   NS_ERROR_XSLT_NODESET_EXPECTED);

    nsRefPtr<txNodeSet> nodes = static_cast<txNodeSet*>
                                           (static_cast<txAExprResult*>
                                                       (res));
    if (nodes->isEmpty()) {
        res.swap(*aResult);

        return NS_OK;
    }
    res = nsnull; // To allow recycling

    // Evaluate remaining steps
    PRUint32 i, len = mItems.Length();
    for (i = 1; i < len; ++i) {
        PathExprItem& pxi = mItems[i];
        nsRefPtr<txNodeSet> tmpNodes;
        txNodeSetContext eContext(nodes, aContext);
        while (eContext.hasNext()) {
            eContext.next();

            nsRefPtr<txNodeSet> resNodes;
            if (pxi.pathOp == DESCENDANT_OP) {
                rv = aContext->recycler()->getNodeSet(getter_AddRefs(resNodes));
                NS_ENSURE_SUCCESS(rv, rv);

                rv = evalDescendants(pxi.expr, eContext.getContextNode(),
                                     &eContext, resNodes);
                NS_ENSURE_SUCCESS(rv, rv);
            }
            else {
                nsRefPtr<txAExprResult> res;
                rv = pxi.expr->evaluate(&eContext, getter_AddRefs(res));
                NS_ENSURE_SUCCESS(rv, rv);

                if (res->getResultType() != txAExprResult::NODESET) {
                    //XXX ErrorReport: report nonnodeset error
                    return NS_ERROR_XSLT_NODESET_EXPECTED;
                }
                resNodes = static_cast<txNodeSet*>
                                      (static_cast<txAExprResult*>
                                                  (res));
            }

            if (tmpNodes) {
                if (!resNodes->isEmpty()) {
                    nsRefPtr<txNodeSet> oldSet;
                    oldSet.swap(tmpNodes);
                    rv = aContext->recycler()->
                        getNonSharedNodeSet(oldSet, getter_AddRefs(tmpNodes));
                    NS_ENSURE_SUCCESS(rv, rv);

                    oldSet.swap(resNodes);
                    rv = aContext->recycler()->
                        getNonSharedNodeSet(oldSet, getter_AddRefs(resNodes));
                    NS_ENSURE_SUCCESS(rv, rv);

                    tmpNodes->addAndTransfer(resNodes);
                }
            }
            else {
                tmpNodes = resNodes;
            }
        }
        nodes = tmpNodes;
        if (nodes->isEmpty()) {
            break;
        }
    }

    *aResult = nodes;
    NS_ADDREF(*aResult);
    
    return NS_OK;
} //-- evaluate
Exemplo n.º 4
0
NS_IMETHODIMP
nsXPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode,
                                       PRUint32 aContextPosition,
                                       PRUint32 aContextSize,
                                       PRUint16 aType,
                                       nsISupports *aInResult,
                                       nsISupports **aResult)
{
    NS_ENSURE_ARG(aContextNode);

    if (aContextPosition > aContextSize)
        return NS_ERROR_FAILURE;

    if (!URIUtils::CanCallerAccess(aContextNode))
        return NS_ERROR_DOM_SECURITY_ERR;

    nsresult rv;
    PRUint16 nodeType;
    rv = aContextNode->GetNodeType(&nodeType);
    NS_ENSURE_SUCCESS(rv, rv);

    if (nodeType == nsIDOMNode::TEXT_NODE ||
        nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
        nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aContextNode);
        NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE);

        if (textNode) {
            PRUint32 textLength;
            textNode->GetLength(&textLength);
            if (textLength == 0)
                return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
        }

        // XXX Need to get logical XPath text node for CDATASection
        //     and Text nodes.
    }
    else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
             nodeType != nsIDOMNode::ELEMENT_NODE &&
             nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
             nodeType != nsIDOMNode::COMMENT_NODE &&
             nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE &&
             nodeType != nsIDOMXPathNamespace::XPATH_NAMESPACE_NODE) {
        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    }

    NS_ENSURE_ARG(aResult);
    *aResult = nsnull;

    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(aContextNode));
    if (!contextNode) {
        return NS_ERROR_OUT_OF_MEMORY;
    }

    EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
                             mRecycler);
    nsRefPtr<txAExprResult> exprResult;
    rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
    NS_ENSURE_SUCCESS(rv, rv);

    PRUint16 resultType = aType;
    if (aType == nsIDOMXPathResult::ANY_TYPE) {
        short exprResultType = exprResult->getResultType();
        switch (exprResultType) {
            case txAExprResult::NUMBER:
                resultType = nsIDOMXPathResult::NUMBER_TYPE;
                break;
            case txAExprResult::STRING:
                resultType = nsIDOMXPathResult::STRING_TYPE;
                break;
            case txAExprResult::BOOLEAN:
                resultType = nsIDOMXPathResult::BOOLEAN_TYPE;
                break;
            case txAExprResult::NODESET:
                resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE;
                break;
            case txAExprResult::RESULT_TREE_FRAGMENT:
                NS_ERROR("Can't return a tree fragment!");
                return NS_ERROR_FAILURE;
        }
    }

    // We need a result object and it must be our implementation.
    nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult);
    if (!xpathResult) {
        // Either no aInResult or not one of ours.
        xpathResult = new nsXPathResult();
        NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY);
    }
    rv = xpathResult->SetExprResult(exprResult, resultType);
    NS_ENSURE_SUCCESS(rv, rv);

    return CallQueryInterface(xpathResult, aResult);
}