bug 113611, XPath and XSLT contexts. fixes bugs 96410, 102293, 92106, 110266, 116534 and a bunch of other cases not filed. This mostly fixes namespaces and some really bad speed issues by fixing the time when namespaces are resolved, how default priorities are computed and how templates are matched.

HUGE PERFWIN :-)
r=peterv, sr=jst
This commit is contained in:
axel%pike.org 2005-11-02 07:37:50 +00:00
Родитель 72cbe9dea6
Коммит f555da27e1
55 изменённых файлов: 2994 добавлений и 1231 удалений

Просмотреть файл

@ -68,4 +68,9 @@ typedef PRUint32 nsresult;
#endif // TX_EXE
#define NS_ERROR_XPATH_EVAL_FAILED NS_ERROR_FAILURE
#define NS_ERROR_XPATH_PARSE_FAILED NS_ERROR_FAILURE
#define NS_ERROR_XPATH_INVALID_ARG NS_ERROR_INVALID_ARG
#define NS_ERROR_XSLT_INVALID_URL NS_ERROR_INVALID_ARG
#endif // __TX_ERROR

Просмотреть файл

@ -28,6 +28,7 @@
#include "baseutils.h"
#include "TxString.h"
#include "txError.h"
#include <iostream.h>
/**
@ -37,23 +38,26 @@ class ErrorObserver {
public:
enum ErrorLevel {FATAL = 0, NORMAL, WARNING};
/**
* Default Destructor for ErrorObserver
**/
virtual ~ErrorObserver() {};
/**
* Notifies this Error observer of a new error, with default
* level of NORMAL
* Notifies this Error observer of a new error aRes
**/
virtual void recieveError(String& errorMessage) = 0;
virtual void receiveError(const String& errorMessage, nsresult aRes) = 0;
/**
* Notifies this Error observer of a new error using the given error level
* Notifies this Error observer of a new error, with default
* error code NS_ERROR_FAILURE
**/
virtual void recieveError(String& errorMessage, ErrorLevel level) = 0;
void receiveError(String& errorMessage)
{
receiveError(errorMessage, NS_ERROR_FAILURE);
}
}; //-- ErrorObserver
@ -79,15 +83,9 @@ public:
virtual ~SimpleErrorObserver() {};
/**
* Notifies this Error observer of a new error, with default
* level of NORMAL
* Notifies this Error observer of a new error aRes
**/
virtual void recieveError(String& errorMessage);
/**
* Notifies this Error observer of a new error using the given error level
**/
virtual void recieveError(String& errorMessage, ErrorLevel level);
void receiveError(const String& errorMessage, nsresult aRes);
virtual void supressWarnings(MBool supress);

Просмотреть файл

@ -45,39 +45,21 @@ SimpleErrorObserver::SimpleErrorObserver(ostream& errStream) {
hideWarnings = MB_FALSE;
} //-- SimpleErrorObserver
/**
* Notifies this Error observer of a new error, with default
* level of NORMAL
**/
void SimpleErrorObserver::recieveError(String& errorMessage) {
#ifdef TX_EXE
*errStream << "error: " << errorMessage << endl;
errStream->flush();
#endif
} //-- recieveError
/**
* Notifies this Error observer of a new error using the given error level
**/
void SimpleErrorObserver::recieveError(String& errorMessage, ErrorLevel level) {
void SimpleErrorObserver::receiveError(const String& errorMessage,
nsresult aRes)
{
#ifdef TX_EXE
switch ( level ) {
case ErrorObserver::FATAL :
*errStream << "fatal error: ";
break;
case ErrorObserver::WARNING :
if ( hideWarnings ) return;
*errStream << "warning: ";
break;
default:
*errStream << "error: ";
break;
if (NS_FAILED(aRes)) {
*errStream << "error: ";
}
*errStream << errorMessage << endl;
errStream->flush();
#endif
} //-- recieveError
}
void SimpleErrorObserver::supressWarnings(MBool supress) {
this->hideWarnings = supress;

Просмотреть файл

@ -61,19 +61,13 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xml/dom/standalone/ProcessingInstruction.$(OBJ_SUFFIX) \
../xml/dom/standalone/Text.$(OBJ_SUFFIX) \
../xpath/AdditiveExpr.$(OBJ_SUFFIX) \
../xpath/AttributeExpr.$(OBJ_SUFFIX) \
../xpath/AttributeValueTemplate.$(OBJ_SUFFIX) \
../xpath/BasicNodeExpr.$(OBJ_SUFFIX) \
../xpath/BooleanExpr.$(OBJ_SUFFIX) \
../xpath/BooleanFunctionCall.$(OBJ_SUFFIX) \
../xpath/BooleanResult.$(OBJ_SUFFIX) \
../xpath/ElementExpr.$(OBJ_SUFFIX) \
../xpath/ErrorFunctionCall.$(OBJ_SUFFIX) \
../xpath/Expr.$(OBJ_SUFFIX) \
../xpath/ExprLexer.$(OBJ_SUFFIX) \
../xpath/ExprLexerChars.$(OBJ_SUFFIX) \
../xpath/ExprParser.$(OBJ_SUFFIX) \
../xpath/ExtensionFunctionCall.$(OBJ_SUFFIX) \
../xpath/FilterExpr.$(OBJ_SUFFIX) \
../xpath/FunctionCall.$(OBJ_SUFFIX) \
../xpath/LocationStep.$(OBJ_SUFFIX) \
@ -90,7 +84,10 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xpath/StringExpr.$(OBJ_SUFFIX) \
../xpath/StringFunctionCall.$(OBJ_SUFFIX) \
../xpath/StringResult.$(OBJ_SUFFIX) \
../xpath/TextExpr.$(OBJ_SUFFIX) \
../xpath/txNameTest.$(OBJ_SUFFIX) \
../xpath/txNodeTypeTest.$(OBJ_SUFFIX) \
../xpath/txForwardContext.$(OBJ_SUFFIX) \
../xpath/txNodeSetContext.$(OBJ_SUFFIX) \
../xpath/UnionExpr.$(OBJ_SUFFIX) \
../xpath/UnaryExpr.$(OBJ_SUFFIX) \
../xpath/VariableRefExpr.$(OBJ_SUFFIX) \
@ -111,6 +108,8 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
../xslt/txTextHandler.$(OBJ_SUFFIX) \
../xslt/txTextOutput.$(OBJ_SUFFIX) \
../xslt/txXMLOutput.$(OBJ_SUFFIX) \
../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \
../xslt/txPatternParser.$(OBJ_SUFFIX) \
../xslt/VariableBinding.$(OBJ_SUFFIX) \
../xslt/XSLTProcessor.$(OBJ_SUFFIX) \
../xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \

Просмотреть файл

@ -40,19 +40,13 @@ REQUIRES = string \
endif
CPPSRCS = AdditiveExpr.cpp \
AttributeExpr.cpp \
AttributeValueTemplate.cpp \
BasicNodeExpr.cpp \
BooleanExpr.cpp \
BooleanFunctionCall.cpp \
BooleanResult.cpp \
ElementExpr.cpp \
ErrorFunctionCall.cpp \
Expr.cpp \
ExprLexer.cpp \
ExprLexerChars.cpp \
ExprParser.cpp \
ExtensionFunctionCall.cpp \
FilterExpr.cpp \
FunctionCall.cpp \
LocationStep.cpp \
@ -69,7 +63,10 @@ CPPSRCS = AdditiveExpr.cpp \
StringExpr.cpp \
StringFunctionCall.cpp \
StringResult.cpp \
TextExpr.cpp \
txNameTest.cpp \
txNodeTypeTest.cpp \
txForwardContext.cpp \
txNodeSetContext.cpp \
UnionExpr.cpp \
UnaryExpr.cpp \
VariableRefExpr.cpp \
@ -87,6 +84,7 @@ include $(topsrcdir)/config/rules.mk
INCLUDES += -I$(srcdir) -I$(srcdir)/../base \
-I$(srcdir)/../xml -I$(srcdir)/../xml/dom \
-I$(srcdir)/../xslt -I$(srcdir)/../xslt/util \
-I$(srcdir)/../xslt/functions
-I$(srcdir)/../xslt/functions \
-I$(srcdir)
libs:: $(OBJS)

Просмотреть файл

@ -45,6 +45,8 @@
#include "nsXPathNSResolver.h"
#include "nsXPathResult.h"
#include "ProcessorState.h"
#include "nsContentCID.h"
#include "ExprParser.h"
NS_IMPL_ADDREF(nsXPathEvaluator)
NS_IMPL_RELEASE(nsXPathEvaluator)
@ -69,8 +71,8 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression,
nsIDOMXPathExpression **aResult)
{
String expressionString(PromiseFlatString(aExpression).get());
// XXX (pvdb) TODO Set the right resolver on the ExprParser
Expr* expression = mParser.createExpr(expressionString);
ParseContextImpl pContext(aResolver);
Expr* expression = ExprParser::createExpr(expressionString, &pContext);
if (!expression)
return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
@ -114,3 +116,58 @@ nsXPathEvaluator::Evaluate(const nsAString & aExpression,
return expression->Evaluate(aContextNode, aType, aInResult, aResult);
}
/*
* Implementation of txIParseContext private to nsXPathEvaluator
* ParseContextImpl bases on a nsIDOMXPathNSResolver
*/
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
nsresult nsXPathEvaluator::ParseContextImpl::resolveNamespacePrefix
(txAtom* aPrefix, PRInt32& aID)
{
nsAutoString prefix;
if (aPrefix) {
aPrefix->ToString(prefix);
}
nsAutoString ns;
nsresult rv = NS_OK;
if (mResolver) {
mResolver->LookupNamespaceURI(prefix, ns);
NS_ENSURE_SUCCESS(rv, rv);
}
aID = kNameSpaceID_None;
if (ns.IsEmpty()) {
return NS_OK;
}
if (!mResolver) {
aID = kNameSpaceID_Unknown;
return NS_OK;
}
if (!mNSMan) {
mNSMan = do_CreateInstance(kNameSpaceManagerCID);
if (!mNSMan) {
return NS_ERROR_FAILURE;
}
}
// get the namespaceID for the URI
return mNSMan->RegisterNameSpace(ns, aID);
}
nsresult nsXPathEvaluator::ParseContextImpl::resolveFunctionCall(txAtom* aName,
PRInt32 aID,
FunctionCall*& aFn)
{
return NS_ERROR_XPATH_PARSE_FAILED;
}
void nsXPathEvaluator::ParseContextImpl::receiveError(const String& aMsg,
nsresult aRes)
{
mLastError = aRes;
// forward aMsg to console service?
}

Просмотреть файл

@ -41,7 +41,8 @@
#define nsXPathEvaluator_h__
#include "nsIDOMXPathEvaluator.h"
#include "ExprParser.h"
#include "txIXPathContext.h"
#include "nsINameSpaceManager.h"
/**
* A class for evaluating an XPath expression string
@ -59,7 +60,34 @@ public:
NS_DECL_NSIDOMXPATHEVALUATOR
private:
ExprParser mParser;
// txIParseContext implementation
class ParseContextImpl : public txIParseContext
{
public:
ParseContextImpl(nsIDOMXPathNSResolver* aResolver)
: mResolver(aResolver), mLastError(NS_OK)
{
}
~ParseContextImpl()
{
}
nsresult getError()
{
return mLastError;
}
nsresult resolveNamespacePrefix(txAtom* aPrefix, PRInt32& aID);
nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID,
FunctionCall*& aFunction);
void receiveError(const String& aMsg, nsresult aRes);
private:
nsIDOMXPathNSResolver* mResolver;
nsresult mLastError;
nsCOMPtr<nsINameSpaceManager> mNSMan;
};
};
/* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */

Просмотреть файл

@ -43,7 +43,6 @@
#include "nsIDOMClassInfo.h"
#include "nsIDOMXPathNamespace.h"
#include "nsXPathResult.h"
#include "ProcessorState.h"
NS_IMPL_ADDREF(nsXPathExpression)
NS_IMPL_RELEASE(nsXPathExpression)
@ -112,8 +111,8 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
Document document(ownerDOMDocument);
Node* node = document.createWrapper(aContextNode);
ProcessorState processorState;
ExprResult* exprResult = mExpression->evaluate(node, &processorState);
EvalContextImpl eContext(node);
ExprResult* exprResult = mExpression->evaluate(&eContext);
NS_ENSURE_TRUE(exprResult, NS_ERROR_OUT_OF_MEMORY);
PRUint16 resultType = aType;
@ -152,3 +151,43 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode,
return CallQueryInterface(xpathResult, aResult);
}
/*
* Implementation of the txIEvalContext private to nsXPathExpression
* EvalContextImpl bases on only one context node and no variables
*/
nsresult nsXPathExpression::EvalContextImpl::getVariable(PRInt32 aNamespace,
txAtom* aLName,
ExprResult*& aResult)
{
aResult = 0;
return NS_ERROR_INVALID_ARG;
}
MBool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(Node* aNode)
{
return MB_FALSE;
}
void nsXPathExpression::EvalContextImpl::receiveError(const String& aMsg,
nsresult aRes)
{
mLastError = aRes;
// forward aMsg to console service?
}
Node* nsXPathExpression::EvalContextImpl::getContextNode()
{
return mNode;
}
PRUint32 nsXPathExpression::EvalContextImpl::size()
{
return 1;
}
PRUint32 nsXPathExpression::EvalContextImpl::position()
{
return 1;
}

Просмотреть файл

@ -41,6 +41,7 @@
#define nsXPathExpression_h__
#include "nsIDOMXPathExpression.h"
#include "txIXPathContext.h"
class Expr;
@ -61,6 +62,29 @@ public:
private:
Expr* mExpression;
class EvalContextImpl : public txIEvalContext
{
public:
EvalContextImpl(Node* aContextNode)
:mNode(aContextNode), mLastError(NS_OK)
{
}
~EvalContextImpl()
{
}
nsresult getError()
{
return mLastError;
}
TX_DECL_EVAL_CONTEXT;
private:
Node* mNode;
nsresult mLastError;
};
};
#endif

Просмотреть файл

@ -53,21 +53,20 @@ AdditiveExpr::~AdditiveExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AdditiveExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* AdditiveExpr::evaluate(txIEvalContext* aContext)
{
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}

Просмотреть файл

@ -62,12 +62,13 @@ void AttributeValueTemplate::addExpr(Expr* expr) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* AttributeValueTemplate::evaluate(Node* context, ContextState* cs) {
ExprResult* AttributeValueTemplate::evaluate(txIEvalContext* aContext)
{
ListIterator* iter = expressions.iterator();
String result;
while ( iter->hasNext() ) {
Expr* expr = (Expr*)iter->next();
ExprResult* exprResult = expr->evaluate(context, cs);
ExprResult* exprResult = expr->evaluate(aContext);
exprResult->stringValue(result);
delete exprResult;
}

Просмотреть файл

@ -57,13 +57,12 @@ BooleanExpr::~BooleanExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* BooleanExpr::evaluate(txIEvalContext* aContext)
{
MBool lval = MB_FALSE;
ExprResult* exprRes = 0;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) lval = exprRes->booleanValue();
delete exprRes;
}
@ -75,7 +74,7 @@ ExprResult* BooleanExpr::evaluate(Node* context, ContextState* cs) {
MBool rval = MB_FALSE;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rval = exprRes->booleanValue();
delete exprRes;
}

Просмотреть файл

@ -29,6 +29,7 @@
#include "FunctionLib.h"
#include "txAtoms.h"
#include "txIXPathContext.h"
/**
* Creates a default BooleanFunctionCall, which always evaluates to False
@ -62,27 +63,26 @@ BooleanFunctionCall::BooleanFunctionCall(BooleanFunctions aType)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* BooleanFunctionCall::evaluate(Node* aContext, ContextState* aCs)
ExprResult* BooleanFunctionCall::evaluate(txIEvalContext* aContext)
{
ListIterator iter(&params);
switch (mType) {
case TX_BOOLEAN:
{
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
return new BooleanResult(evaluateToBoolean((Expr*)iter.next(),
aContext,
aCs));
aContext));
}
case TX_LANG:
{
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
String lang;
Node* node = aContext;
Node* node = aContext->getContextNode();
while (node) {
if (node->getNodeType() == Node::ELEMENT_NODE) {
Element* elem = (Element*)node;
@ -96,7 +96,7 @@ ExprResult* BooleanFunctionCall::evaluate(Node* aContext, ContextState* aCs)
MBool result = MB_FALSE;
if (node) {
String arg;
evaluateToString((Expr*)iter.next(),aContext, aCs, arg);
evaluateToString((Expr*)iter.next(), aContext, arg);
arg.toUpperCase(); // case-insensitive comparison
lang.toUpperCase();
result = lang.indexOf(arg) == 0 &&
@ -108,23 +108,22 @@ ExprResult* BooleanFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case TX_NOT:
{
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
return new BooleanResult(!evaluateToBoolean((Expr*)iter.next(),
aContext,
aCs));
aContext));
}
case TX_TRUE:
{
if (!requireParams(0, 0, aCs))
if (!requireParams(0, 0, aContext))
return new StringResult("error");
return new BooleanResult(MB_TRUE);
}
case TX_FALSE:
{
if (!requireParams(0, 0, aCs))
if (!requireParams(0, 0, aContext))
return new StringResult("error");
return new BooleanResult(MB_FALSE);
@ -132,7 +131,7 @@ ExprResult* BooleanFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
String err("Internal error");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_UNEXPECTED);
return new StringResult("error");
}

Просмотреть файл

@ -35,7 +35,7 @@
#ifndef TRANSFRMX_EXPR_H
#define TRANSFRMX_EXPR_H
#include "txError.h"
#include "TxString.h"
#include "ErrorObserver.h"
#include "NodeSet.h"
@ -50,51 +50,12 @@
Much of this code was ported from XSL:P.
*/
//necessary prototypes
class FunctionCall;
typedef class Expr Pattern;
typedef class Expr PatternExpr;
/**
* The expression context and state class used when evaluating XPath Expressions.
**/
class ContextState : public ErrorObserver {
public:
/**
* Returns the value of a given variable binding within the current scope
* @param the name to which the desired variable value has been bound
* @return the ExprResult which has been bound to the variable with
* the given name
**/
virtual ExprResult* getVariable(String& name) = 0;
/**
* Returns the Stack of context NodeSets
* @return the Stack of context NodeSets
**/
virtual Stack* getNodeSetStack() = 0;
virtual MBool isStripSpaceAllowed(Node* node) = 0;
/**
* Returns a call to the function that has the given name.
* This method is used for XPath Extension Functions.
* @return the FunctionCall for the function with the given name.
**/
virtual FunctionCall* resolveFunctionCall(const String& name) = 0;
/**
* Returns the namespace URI for the given namespace prefix, this method should
* only be called for determining a namespace declared within the context
* (ie. the stylesheet)
**/
virtual void getNameSpaceURIFromPrefix(const String& aPrefix, String& aNamespaceURI) = 0;
}; //-- ContextState
/*
* necessary prototypes
*/
class txIParseContext;
class txIMatchContext;
class txIEvalContext;
/**
* A Base Class for all XSL Expressions
@ -106,7 +67,9 @@ public:
/**
* Virtual destructor, important for subclasses
**/
virtual ~Expr();
virtual ~Expr()
{
}
/**
* Evaluates this Expr based on the given context node and processor state
@ -115,19 +78,7 @@ public:
* for evaluation
* @return the result of the evaluation
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
/**
* Determines whether this Expr matches the given node within
* the given context
**/
virtual MBool matches(Node* node, Node* context, ContextState* cs);
/**
* Returns the default priority of this Expr based on the given Node,
* context Node, and ContextState.
**/
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual ExprResult* evaluate(txIEvalContext* aContext) = 0;
/**
* Returns the String representation of this Expr.
@ -141,6 +92,14 @@ public:
}; //-- Expr
#define TX_DECL_EVALUATE \
ExprResult* evaluate(txIEvalContext* aContext)
#define TX_DECL_EXPR \
TX_DECL_EVALUATE; \
void toString(String& aDest)
/**
* This class represents a FunctionCall as defined by the XPath 1.0
* Recommendation.
@ -157,22 +116,22 @@ public:
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs) = 0;
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual ExprResult* evaluate(txIEvalContext* aContext) = 0;
virtual void toString(String& dest);
/**
* Adds the given parameter to this FunctionCall's parameter list
* @param expr the Expr to add to this FunctionCall's parameter list
**/
void addParam(Expr* expr);
nsresult addParam(Expr* aExpr);
virtual MBool requireParams(int paramCountMin, ContextState* cs);
virtual MBool requireParams(int paramCountMin,
int paramCountMax,
ContextState* cs);
/*
* XXX txIEvalContext should be txIParseContest, bug 143291
*/
virtual MBool requireParams(int aParamCountMin, txIEvalContext* aContext);
virtual MBool requireParams(int aParamCountMin,
int aParamCountMax,
txIEvalContext* aContext);
protected:
@ -185,24 +144,24 @@ protected:
* Evaluates the given Expression and converts its result to a String.
* The value is appended to the given destination String
*/
void evaluateToString(Expr* aExpr, Node* aContext,
ContextState* aCs, String& aDest);
void evaluateToString(Expr* aExpr, txIEvalContext* aContext,
String& aDest);
/*
* Evaluates the given Expression and converts its result to a number.
*/
double evaluateToNumber(Expr* aExpr, Node* aContext, ContextState* aCs);
double evaluateToNumber(Expr* aExpr, txIEvalContext* aContext);
/*
* Evaluates the given Expression and converts its result to a boolean.
*/
MBool evaluateToBoolean(Expr* aExpr, Node* aContext, ContextState* aCs);
MBool evaluateToBoolean(Expr* aExpr, txIEvalContext* aContext);
/*
* Evaluates the given Expression and converts its result to a NodeSet.
* If the result is not a NodeSet NULL is returned.
*/
NodeSet* evaluateToNodeSet(Expr* aExpr, Node* aContext, ContextState* aCs);
NodeSet* evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext);
String name;
}; //-- FunctionCall
@ -224,172 +183,91 @@ public:
**/
void addExpr(Expr* expr);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
List expressions;
};
/**
* This class represents a NodeTestExpr as defined by the XSL
* Working Draft
**/
class NodeExpr : public Expr {
/*
* This class represents a NodeTest as defined by the XPath spec
*/
class txNodeTest
{
public:
virtual ~txNodeTest() {}
/*
* Virtual methods
* pretty much a txPattern, but not supposed to be used
* standalone. The NodeTest node() is different to the
* Pattern "node()" (document node isn't matched)
*/
virtual MBool matches(Node* aNode, txIMatchContext* aContext) = 0;
virtual double getDefaultPriority() = 0;
virtual void toString(String& aDest) = 0;
};
//-- NodeExpr Types
//-- LF - changed from const short to enum
enum NodeExprType {
ATTRIBUTE_EXPR = 1,
ELEMENT_EXPR,
TEXT_EXPR,
COMMENT_EXPR,
PI_EXPR,
NODE_EXPR
#define TX_DECL_NODE_TEST \
MBool matches(Node* aNode, txIMatchContext* aContext); \
double getDefaultPriority(); \
void toString(String& aDest)
/*
* This class represents a NameTest as defined by the XPath spec
*/
class txNameTest : public txNodeTest
{
public:
/*
* Creates a new txNameTest with the given type and the given
* principal node type
*/
txNameTest(txAtom* aPrefix, txAtom* aLocalName, PRInt32 aNSID,
Node::NodeType aNodeType);
~txNameTest();
TX_DECL_NODE_TEST;
private:
txAtom* mPrefix;
txAtom* mLocalName;
PRInt32 mNamespace;
Node::NodeType mNodeType;
};
/*
* This class represents a NodeType as defined by the XPath spec
*/
class txNodeTypeTest : public txNodeTest
{
public:
enum NodeType {
COMMENT_TYPE,
TEXT_TYPE,
PI_TYPE,
NODE_TYPE
};
virtual ~NodeExpr() {};
/*
* Creates a new txNodeTypeTest of the given type
*/
txNodeTypeTest(NodeType aNodeType);
//------------------/
//- Public Methods -/
//------------------/
~txNodeTypeTest();
/**
* Virtual methods from Expr
**/
virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0;
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0;
virtual void toString(String& dest) = 0;
}; //-- NodeExpr
/**
* This class represents a AttributeExpr as defined by the XSL
* Working Draft
**/
class AttributeExpr : public NodeExpr {
public:
//------------------/
//- Public Methods -/
//------------------/
AttributeExpr(String& name);
/**
* Virtual methods from NodeExpr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
private:
static const String WILD_CARD;
String prefix;
String name;
MBool isNameWild;
MBool isNamespaceWild;
}; //-- AttributeExpr
/**
*
**/
class BasicNodeExpr : public NodeExpr {
public:
//------------------/
//- Public Methods -/
//------------------/
/**
* Creates a new BasicNodeExpr of the given type
**/
BasicNodeExpr(NodeExprType nodeExprType);
/**
/*
* Sets the name of the node to match. Only availible for pi nodes
**/
void setNodeName(const String& name);
*/
void setNodeName(const String& aName);
/**
* Virtual methods from NodeExpr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_NODE_TEST;
private:
NodeExprType type;
String nodeName;
MBool nodeNameSet;
}; //-- BasicNodeExpr
/**
* This class represents a ElementExpr as defined by the XSL
* Working Draft
**/
class ElementExpr : public NodeExpr {
public:
//------------------/
//- Public Methods -/
//------------------/
ElementExpr(String& name);
/**
* Virtual methods from NodeExpr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
private:
static const String WILD_CARD;
String name;
MBool isNamespaceWild;
MBool isNameWild;
String prefix;
}; //-- ElementExpr
/**
* This class represents a TextExpr, which only matches any text node
**/
class TextExpr : public NodeExpr {
public:
//------------------/
//- Public Methods -/
//------------------/
/**
* Virtual methods from NodeExpr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
}; //-- TextExpr
NodeType mNodeType;
txAtom* mNodeName;
};
/**
* Represents an ordered list of Predicates,
@ -415,8 +293,7 @@ public:
**/
void add(Expr* expr);
void evaluatePredicates(NodeSet* nodes, ContextState* cs);
void evaluatePredicates(NodeSet* aNodes, txIMatchContext* aContext);
/**
* returns true if this predicate list is empty
@ -433,7 +310,7 @@ public:
**/
virtual void toString(String& dest);
private:
protected:
//-- list of predicates
List predicates;
}; //-- PredicateList
@ -444,7 +321,7 @@ public:
// Axis Identifier Types
//-- LF changed from static const short to enum
enum _LocationStepType {
enum LocationStepType {
ANCESTOR_AXIS = 0,
ANCESTOR_OR_SELF_AXIS,
ATTRIBUTE_AXIS,
@ -465,28 +342,24 @@ public:
* @param nodeExpr the NodeExpr to use when matching Nodes
* @param axisIdentifier the Axis Identifier in which to search for nodes
**/
LocationStep(NodeExpr* nodeExpr, short axisIdentifier);
LocationStep(txNodeTest* aNodeTest, LocationStepType aAxisIdentifier);
/**
* Destructor, will delete all predicates and the given NodeExpr
**/
virtual ~LocationStep();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_EXPR;
private:
NodeExpr* nodeExpr;
short axisIdentifier;
txNodeTest* mNodeTest;
LocationStepType mAxisIdentifier;
void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes);
void fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes);
void fromDescendants(Node* node, txIMatchContext* aContext,
NodeSet* nodes);
void fromDescendantsRev(Node* node, txIMatchContext* aContext,
NodeSet* nodes);
}; //-- LocationStep
@ -499,20 +372,14 @@ public:
* Creates a new FilterExpr using the given Expr
* @param expr the Expr to use for evaluation
**/
FilterExpr(Expr* expr);
FilterExpr(Expr* aExpr);
/**
* Destructor, will delete all predicates and the given Expr
**/
virtual ~FilterExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_EXPR;
private:
Expr* expr;
@ -526,11 +393,7 @@ public:
NumberExpr(double dbl);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
@ -546,11 +409,7 @@ public:
StringExpr(const String& value);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
@ -575,11 +434,7 @@ public:
AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op);
~AdditiveExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
short op;
@ -597,11 +452,7 @@ public:
UnaryExpr(Expr* expr);
~UnaryExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
Expr* expr;
@ -621,11 +472,7 @@ public:
BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op);
~BooleanExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
short op;
@ -652,11 +499,7 @@ public:
MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op);
~MultiplicativeExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
short op;
@ -692,11 +535,7 @@ public:
RelationalExpr(Expr* leftExpr, Expr* rightExpr, short op);
~RelationalExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
short op;
@ -714,18 +553,16 @@ class VariableRefExpr : public Expr {
public:
VariableRefExpr(const String& name);
VariableRefExpr(txAtom* aPrefix, txAtom* aLocalName, PRInt32 aNSID);
~VariableRefExpr();
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual void toString(String& str);
TX_DECL_EXPR;
private:
String name;
}; //-- VariableRefExpr
txAtom* mPrefix;
txAtom* mLocalName;
PRInt32 mNamespace;
};
/**
* Represents a PathExpr
@ -755,32 +592,25 @@ public:
**/
void addExpr(Expr* expr, PathOperator pathOp);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_EXPR;
private:
static const String RTF_INVALID_OP;
static const String NODESET_EXPECTED;
struct PathExprItem {
Expr* expr;
PathOperator pathOp;
};
List expressions;
List expressions;
/**
* Selects from the descendants of the context node
* all nodes that match the Expr
* -- this will be moving to a Utility class
**/
void evalDescendants(Expr* expr,
Node* context,
ContextState* cs,
NodeSet* resNodes);
/*
* Selects from the descendants of the context node
* all nodes that match the Expr
*/
void evalDescendants(Expr* aStep, Node* aNode,
txIMatchContext* aContext,
NodeSet* resNodes);
}; //-- PathExpr
@ -797,13 +627,7 @@ public:
*/
RootExpr(MBool aSerialize);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_EXPR;
private:
// When a RootExpr is used in a PathExpr it shouldn't be serialized
@ -834,13 +658,7 @@ public:
**/
void addExpr(Expr* expr);
/**
* Virtual methods from Expr
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
virtual MBool matches(Node* node, Node* context, ContextState* cs);
virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs);
virtual void toString(String& dest);
TX_DECL_EXPR;
private:

Просмотреть файл

@ -41,25 +41,16 @@
#include "ExprParser.h"
#include "FunctionLib.h"
#include "Names.h"
/**
* Creates a new ExprParser
**/
ExprParser::ExprParser() {};
/**
* Default Destructor
**/
ExprParser::~ExprParser() {};
#include "txAtoms.h"
#include "txIXPathContext.h"
/**
* Creates an Attribute Value Template using the given value
* This should move to XSLProcessor class
**/
AttributeValueTemplate* ExprParser::createAttributeValueTemplate
(const String& attValue)
(const String& attValue, txIParseContext* aContext)
{
AttributeValueTemplate* avt = new AttributeValueTemplate();
if (attValue.isEmpty())
@ -116,7 +107,8 @@ AttributeValueTemplate* ExprParser::createAttributeValueTemplate
case '}':
if (inExpr) {
inExpr = MB_FALSE;
Expr* expr = createExpr(buffer);
ExprLexer lexer(buffer);
Expr* expr = createExpr(lexer, aContext);
if (!expr) {
delete avt;
return 0;
@ -154,18 +146,14 @@ AttributeValueTemplate* ExprParser::createAttributeValueTemplate
} //-- createAttributeValueTemplate
Expr* ExprParser::createExpr(const String& aExpression)
Expr* ExprParser::createExpr(const String& aExpression,
txIParseContext* aContext)
{
ExprLexer lexer(aExpression);
return createExpr(lexer);
Expr* expr = createExpr(lexer, aContext);
return expr;
} //-- createExpr
Pattern* ExprParser::createPattern(const String& aPattern)
{
ExprLexer lexer(aPattern);
return createUnionExpr(lexer);
} //-- createPatternExpr
//--------------------/
//- Private Methods -/
//-------------------/
@ -221,8 +209,8 @@ Expr* ExprParser::createBinaryExpr (Expr* left, Expr* right, Token* op) {
} //-- createBinaryExpr
Expr* ExprParser::createExpr(ExprLexer& lexer) {
Expr* ExprParser::createExpr(ExprLexer& lexer, txIParseContext* aContext)
{
MBool done = MB_FALSE;
Expr* expr = 0;
@ -238,7 +226,7 @@ Expr* ExprParser::createExpr(ExprLexer& lexer) {
lexer.nextToken();
}
expr = createUnionExpr(lexer);
expr = createUnionExpr(lexer, aContext);
if (!expr)
break;
@ -299,21 +287,33 @@ Expr* ExprParser::createExpr(ExprLexer& lexer) {
} //-- createExpr
Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
Expr* ExprParser::createFilterExpr(ExprLexer& lexer, txIParseContext* aContext)
{
Token* tok = lexer.nextToken();
Expr* expr = 0;
switch (tok->type) {
case Token::FUNCTION_NAME :
lexer.pushBack();
expr = createFunctionCall(lexer);
expr = createFunctionCall(lexer, aContext);
break;
case Token::VAR_REFERENCE :
expr = new VariableRefExpr(tok->value);
{
txAtom *prefix, *lName;
PRInt32 nspace;
nsresult rv = resolveQName(tok->value, prefix, aContext,
lName, nspace);
if (NS_FAILED(rv)) {
// XXX error report namespace resolve failed
return 0;
}
expr = new VariableRefExpr(prefix, lName, nspace);
TX_IF_RELEASE_ATOM(prefix);
TX_IF_RELEASE_ATOM(lName);
}
break;
case Token::L_PAREN:
expr = createExpr(lexer);
expr = createExpr(lexer, aContext);
if (!expr)
return 0;
@ -347,7 +347,7 @@ Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
FilterExpr* filterExpr = new FilterExpr(expr);
//-- handle predicates
if (!parsePredicates(filterExpr, lexer)) {
if (!parsePredicates(filterExpr, lexer, aContext)) {
delete filterExpr;
return 0;
}
@ -358,8 +358,9 @@ Expr* ExprParser::createFilterExpr(ExprLexer& lexer) {
} //-- createFilterExpr
FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
Expr* ExprParser::createFunctionCall(ExprLexer& lexer,
txIParseContext* aContext)
{
FunctionCall* fnCall = 0;
Token* tok = lexer.nextToken();
@ -368,11 +369,11 @@ FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
return 0;
}
String fnName = tok->value;
//-- compare function names
//-- * we should hash these names for speed
nsresult rv = NS_OK;
if (XPathNames::BOOLEAN_FN.isEqual(tok->value)) {
fnCall = new BooleanFunctionCall(BooleanFunctionCall::TX_BOOLEAN);
}
@ -455,24 +456,44 @@ FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) {
fnCall = new NumberFunctionCall(NumberFunctionCall::FLOOR);
}
else {
//-- Most likely an Extension Function, or error, but it's
//-- not our job to report an invalid function call here
fnCall = new ExtensionFunctionCall(fnName);
txAtom *prefix, *lName;
PRInt32 namespaceID;
rv = resolveQName(tok->value, prefix, aContext, lName, namespaceID);
if (NS_FAILED(rv)) {
// XXX error report namespace resolve failed
return 0;
}
rv = aContext->resolveFunctionCall(lName, namespaceID, fnCall);
TX_IF_RELEASE_ATOM(prefix);
TX_IF_RELEASE_ATOM(lName);
if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
// XXX report error unknown function call
return 0;
}
}
//-- handle parametes
if (!parseParameters(fnCall, lexer)) {
if (!parseParameters(fnCall, lexer, aContext)) {
delete fnCall;
return 0;
}
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
NS_ASSERTION(!fnCall, "Now is it implemented or not?");
String err(tok->value);
err.append(" not implemented.");
return new StringExpr(err);
}
return fnCall;
} //-- createFunctionCall
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
LocationStep* ExprParser::createLocationStep(ExprLexer& lexer,
txIParseContext* aContext)
{
//-- child axis is default
short axisIdentifier = LocationStep::CHILD_AXIS;
NodeExpr* nodeExpr = 0;
LocationStep::LocationStepType axisIdentifier = LocationStep::CHILD_AXIS;
txNodeTest* nodeTest = 0;
//-- get Axis Identifier or AbbreviatedStep, if present
Token* tok = lexer.peek();
@ -536,44 +557,78 @@ LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
//-- eat token
lexer.nextToken();
axisIdentifier = LocationStep::PARENT_AXIS;
nodeExpr = new BasicNodeExpr(NodeExpr::NODE_EXPR);
nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
if (!nodeTest) {
//XXX out of memory
return 0;
}
break;
case Token::SELF_NODE :
//-- eat token
lexer.nextToken();
axisIdentifier = LocationStep::SELF_AXIS;
nodeExpr = new BasicNodeExpr(NodeExpr::NODE_EXPR);
nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
if (!nodeTest) {
//XXX out of memory
return 0;
}
break;
default:
break;
}
//-- get NodeTest unless AbbreviatedStep was found
if (!nodeExpr) {
//-- get NodeTest unless an AbbreviatedStep was found
if (!nodeTest) {
tok = lexer.nextToken();
switch (tok->type) {
case Token::CNAME :
// NameTest
// XXX Namespace: handle namespaces here
if (axisIdentifier == LocationStep::ATTRIBUTE_AXIS)
nodeExpr = new AttributeExpr(tok->value);
else
nodeExpr = new ElementExpr(tok->value);
{
// resolve QName
txAtom *prefix, *lName;
PRInt32 nspace;
nsresult rv = resolveQName(tok->value, prefix, aContext,
lName, nspace);
if (NS_FAILED(rv)) {
// XXX error report namespace resolve failed
return 0;
}
switch (axisIdentifier) {
case LocationStep::ATTRIBUTE_AXIS:
nodeTest = new txNameTest(prefix, lName, nspace,
Node::ATTRIBUTE_NODE);
break;
default:
nodeTest = new txNameTest(prefix, lName, nspace,
Node::ELEMENT_NODE);
break;
}
TX_IF_RELEASE_ATOM(prefix);
TX_IF_RELEASE_ATOM(lName);
}
if (!nodeTest) {
//XXX ErrorReport: out of memory
return 0;
}
break;
default:
lexer.pushBack();
nodeExpr = createNodeExpr(lexer);
if (!nodeExpr) {
nodeTest = createNodeTypeTest(lexer);
if (!nodeTest) {
return 0;
}
}
}
LocationStep* lstep = new LocationStep(nodeExpr, axisIdentifier);
LocationStep* lstep = new LocationStep(nodeTest, axisIdentifier);
if (!lstep) {
//XXX out of memory
delete nodeTest;
return 0;
}
//-- handle predicates
if (!parsePredicates(lstep, lexer)) {
if (!parsePredicates(lstep, lexer, aContext)) {
delete lstep;
return 0;
}
@ -585,59 +640,62 @@ LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) {
* This method only handles comment(), text(), processing-instructing() and node()
*
**/
NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) {
txNodeTypeTest* ExprParser::createNodeTypeTest(ExprLexer& lexer) {
NodeExpr* nodeExpr = 0;
txNodeTypeTest* nodeTest = 0;
Token* nodeTok = lexer.nextToken();
switch (nodeTok->type) {
case Token::COMMENT:
nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR);
nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE);
break;
case Token::NODE :
nodeExpr = new BasicNodeExpr(NodeExpr::NODE_EXPR);
nodeTest = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
break;
case Token::PROC_INST :
nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR);
nodeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE);
break;
case Token::TEXT :
nodeExpr = new TextExpr();
nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE);
break;
default:
lexer.pushBack();
// XXX ErrorReport: unexpected token
return 0;
break;
}
if (!nodeTest) {
//XXX out of memory
return 0;
}
if (lexer.nextToken()->type != Token::L_PAREN) {
lexer.pushBack();
//XXX ErrorReport: left parenthesis expected
delete nodeExpr;
delete nodeTest;
return 0;
}
if (nodeTok->type == Token::PROC_INST &&
lexer.peek()->type == Token::LITERAL) {
Token* tok = lexer.nextToken();
((BasicNodeExpr*)nodeExpr)->setNodeName(tok->value);
nodeTest->setNodeName(tok->value);
}
if (lexer.nextToken()->type != Token::R_PAREN) {
lexer.pushBack();
//XXX ErrorReport: right parenthesis expected (or literal for pi)
delete nodeExpr;
delete nodeTest;
return 0;
}
return nodeExpr;
} //-- createNodeExpr
return nodeTest;
} //-- createNodeTypeTest
/**
* Creates a PathExpr using the given ExprLexer
* @param lexer the ExprLexer for retrieving Tokens
**/
Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
Expr* ExprParser::createPathExpr(ExprLexer& lexer, txIParseContext* aContext)
{
Expr* expr = 0;
Token* tok = lexer.peek();
@ -655,10 +713,10 @@ Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
if (tok->type != Token::PARENT_OP &&
tok->type != Token::ANCESTOR_OP) {
if (isFilterExprToken(tok)) {
expr = createFilterExpr(lexer);
expr = createFilterExpr(lexer, aContext);
}
else
expr = createLocationStep(lexer);
expr = createLocationStep(lexer, aContext);
if (!expr)
return 0;
@ -702,7 +760,7 @@ Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
return pathExpr;
}
expr = createLocationStep(lexer);
expr = createLocationStep(lexer, aContext);
if (!expr) {
delete pathExpr;
return 0;
@ -719,9 +777,9 @@ Expr* ExprParser::createPathExpr(ExprLexer& lexer) {
* XXX temporary use as top of XSLT Pattern
* @param lexer the ExprLexer for retrieving Tokens
**/
Expr* ExprParser::createUnionExpr(ExprLexer& lexer) {
Expr* expr = createPathExpr(lexer);
Expr* ExprParser::createUnionExpr(ExprLexer& lexer, txIParseContext* aContext)
{
Expr* expr = createPathExpr(lexer, aContext);
if (!expr)
return 0;
@ -734,7 +792,7 @@ Expr* ExprParser::createUnionExpr(ExprLexer& lexer) {
while (lexer.peek()->type == Token::UNION_OP) {
lexer.nextToken(); //-- eat token
expr = createPathExpr(lexer);
expr = createPathExpr(lexer, aContext);
if (!expr) {
delete unionExpr;
return 0;
@ -791,13 +849,14 @@ MBool ExprParser::isNodeTypeToken(Token* token) {
* @param lexer the ExprLexer to use for parsing tokens
* @return 0 if successful, or a String pointer to the error message
**/
MBool ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) {
MBool ExprParser::parsePredicates(PredicateList* predicateList,
ExprLexer& lexer, txIParseContext* aContext)
{
while (lexer.peek()->type == Token::L_BRACKET) {
//-- eat Token
lexer.nextToken();
Expr* expr = createExpr(lexer);
Expr* expr = createExpr(lexer, aContext);
if (!expr)
return MB_FALSE;
@ -822,8 +881,9 @@ MBool ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer
* @param lexer the ExprLexer to use for parsing tokens
* @return MB_TRUE if successful, or a MB_FALSE otherwise
**/
MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer) {
MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer,
txIParseContext* aContext)
{
if (lexer.nextToken()->type != Token::L_PAREN) {
lexer.pushBack();
//XXX ErrorReport: left parenthesis expected
@ -836,11 +896,12 @@ MBool ExprParser::parseParameters(FunctionCall* fnCall, ExprLexer& lexer) {
}
while (1) {
Expr* expr = createExpr(lexer);
Expr* expr = createExpr(lexer, aContext);
if (!expr)
return MB_FALSE;
fnCall->addParam(expr);
if (fnCall)
fnCall->addParam(expr);
switch (lexer.nextToken()->type) {
case Token::R_PAREN :
@ -887,5 +948,35 @@ short ExprParser::precedenceLevel(short tokenType) {
break;
}
return 0;
} //-- precedenceLevel
}
nsresult ExprParser::resolveQName(const String& aQName,
txAtom*& aPrefix, txIParseContext* aContext,
txAtom*& aLocalName, PRInt32& aNamespace)
{
aNamespace = kNameSpaceID_None;
String prefix, lName;
int idx = aQName.indexOf(':');
if (idx > 0) {
aQName.subString(0, idx, prefix);
aPrefix = TX_GET_ATOM(prefix);
if (!aPrefix) {
return NS_ERROR_OUT_OF_MEMORY;
}
aQName.subString(idx + 1, lName);
aLocalName = TX_GET_ATOM(lName);
if (!aLocalName) {
TX_RELEASE_ATOM(aPrefix);
aPrefix = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
return aContext->resolveNamespacePrefix(aPrefix, aNamespace);
}
// the lexer dealt with idx == 0
aPrefix = 0;
aLocalName = TX_GET_ATOM(aQName);
if (!aLocalName) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}

Просмотреть файл

@ -36,59 +36,61 @@
#include "ExprLexer.h"
#include "Expr.h"
#include "List.h"
class txIParseContext;
class ExprParser {
class ExprParser
{
public:
/**
* Creates a new ExprParser
**/
ExprParser();
/**
* destroys the ExprParser
**/
~ExprParser();
Expr* createExpr(const String& aExpression);
Pattern* createPattern(const String& aPattern);
static Expr* createExpr(const String& aExpression,
txIParseContext* aContext);
/**
* Creates an Attribute Value Template using the given value
**/
AttributeValueTemplate* createAttributeValueTemplate(const String& attValue);
static AttributeValueTemplate* createAttributeValueTemplate
(const String& attValue, txIParseContext* aContext);
private:
Expr* createBinaryExpr (Expr* left, Expr* right, Token* op);
Expr* createExpr (ExprLexer& lexer);
Expr* createFilterExpr (ExprLexer& lexer);
FunctionCall* createFunctionCall (ExprLexer& lexer);
LocationStep* createLocationStep (ExprLexer& lexer);
NodeExpr* createNodeExpr (ExprLexer& lexer);
Expr* createPathExpr (ExprLexer& lexer);
Expr* createUnionExpr (ExprLexer& lexer);
MBool isFilterExprToken (Token* tok);
MBool isLocationStepToken (Token* tok);
MBool isNodeTypeToken (Token* tok);
static short precedenceLevel (short tokenType);
protected:
static Expr* createBinaryExpr(Expr* left, Expr* right, Token* op);
static Expr* createExpr(ExprLexer& lexer, txIParseContext* aContext);
static Expr* createFilterExpr(ExprLexer& lexer, txIParseContext* aContext);
static Expr* createFunctionCall(ExprLexer& lexer,
txIParseContext* aContext);
static LocationStep* createLocationStep(ExprLexer& lexer,
txIParseContext* aContext);
static txNodeTypeTest* createNodeTypeTest(ExprLexer& lexer);
static Expr* createPathExpr(ExprLexer& lexer, txIParseContext* aContext);
static Expr* createUnionExpr(ExprLexer& lexer, txIParseContext* aContext);
static MBool isFilterExprToken (Token* tok);
static MBool isLocationStepToken(Token* tok);
static MBool isNodeTypeToken (Token* tok);
static short precedenceLevel (short tokenType);
/**
* Using the given lexer, parses the tokens if they represent a predicate list
* If an error occurs a non-zero String pointer will be returned containing the
* error message.
* Resolve a QName, given the mContext parse context.
* Returns prefix and localName as well as namespace ID
**/
static nsresult resolveQName(const String& aQName, txAtom*& aPrefix,
txIParseContext* aContext,
txAtom*& aLocalName, PRInt32& aNamespace);
/**
* Using the given lexer, parses the tokens if they represent a
* predicate list
* If an error occurs a non-zero String pointer will be returned
* containing the error message.
* @param predicateList, the PredicateList to add predicate expressions to
* @param lexer the ExprLexer to use for parsing tokens
* @return 0 if successful, or a String pointer to the error message
**/
MBool parsePredicates(PredicateList* predicateList, ExprLexer& lexer);
MBool parseParameters(FunctionCall* fnCall, ExprLexer& lexer);
static MBool parsePredicates(PredicateList* predicateList,
ExprLexer& lexer, txIParseContext* aContext);
static MBool parseParameters(FunctionCall* fnCall,
ExprLexer& lexer, txIParseContext* aContext);
}; //-- ExprParser

Просмотреть файл

@ -26,6 +26,7 @@
*/
#include "Expr.h"
#include "txIXPathContext.h"
//-- Implementation of FilterExpr --/
@ -56,24 +57,24 @@ FilterExpr::~FilterExpr() {
* @return the result of the evaluation
* @see Expr
**/
ExprResult* FilterExpr::evaluate(Node* context, ContextState* cs) {
if (!context || !expr)
ExprResult* FilterExpr::evaluate(txIEvalContext* aContext)
{
if (!aContext || !expr)
return new NodeSet;
ExprResult* exprResult = expr->evaluate(context, cs);
ExprResult* exprResult = expr->evaluate(aContext);
if (!exprResult)
return 0;
if (exprResult->getResultType() == ExprResult::NODESET) {
// Result is a nodeset, filter it.
evaluatePredicates((NodeSet*)exprResult, cs);
evaluatePredicates((NodeSet*)exprResult, aContext);
}
else if(!isEmpty()) {
// We can't filter a non-nodeset
String err("Expecting nodeset as result of: ");
expr->toString(err);
cs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_EVAL_FAILED);
delete exprResult;
return new NodeSet;
}
@ -81,40 +82,6 @@ ExprResult* FilterExpr::evaluate(Node* context, ContextState* cs) {
return exprResult;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
**/
double FilterExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
NS_ASSERTION(0, "FilterExpr is not allowed in Patterns");
if (isEmpty())
return expr->getDefaultPriority(node, context, cs);
return 0.5;
} //-- getDefaultPriority
/**
* Determines whether this Expr matches the given node within
* the given context
**/
MBool FilterExpr::matches(Node* node, Node* context, ContextState* cs) {
if (!expr)
return MB_FALSE;
ExprResult* exprResult = evaluate(node, cs);
if (!exprResult)
return MB_FALSE;
MBool result = MB_FALSE;
if(exprResult->getResultType() == ExprResult::NODESET)
result = ((NodeSet*)exprResult)->contains(node);
delete exprResult;
return result;
} //-- matches
/**
* Creates a String representation of this Expr
* @param str the destination String to append to

Просмотреть файл

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txForwardContext.h"
Node* txForwardContext::getContextNode()
{
return mContext;
}
PRUint32 txForwardContext::size()
{
return (PRUint32)mContextSet->size();
}
PRUint32 txForwardContext::position()
{
int pos = mContextSet->indexOf(mContext);
NS_ASSERTION(pos >= 0, "Context is not member of context node list.");
return (PRUint32)(pos+1);
}
nsresult txForwardContext::getVariable(PRInt32 aNamespace, txAtom* aLName,
ExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
}
MBool txForwardContext::isStripSpaceAllowed(Node* aNode)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
}
void txForwardContext::receiveError(const String& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");
#ifdef DEBUG
String error("forwarded error: ");
error.append(aMsg);
mInner->receiveError(error, aRes);
#else
mInner->receiveError(aMsg, aRes);
#endif
}

Просмотреть файл

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __TX_XPATH_CONTEXT
#define __TX_XPATH_CONTEXT
#include "txIXPathContext.h"
class txForwardContext : public txIEvalContext
{
public:
txForwardContext(txIMatchContext* aContext, Node* aContextNode,
NodeSet* aContextNodeSet) : mContext(aContextNode),
mContextSet(aContextNodeSet),
mInner(aContext)
{}
~txForwardContext()
{}
TX_DECL_EVAL_CONTEXT;
private:
Node* mContext;
NodeSet* mContextSet;
txIMatchContext* mInner;
};
#endif // __TX_XPATH_CONTEXT

Просмотреть файл

@ -24,6 +24,7 @@
*/
#include "Expr.h"
#include "txIXPathContext.h"
/**
* This class represents a FunctionCall as defined by the XSL Working Draft
@ -77,50 +78,22 @@ FunctionCall::~FunctionCall()
* Adds the given parameter to this FunctionCall's parameter list
* @param expr the Expr to add to this FunctionCall's parameter list
**/
void FunctionCall::addParam(Expr* expr)
nsresult FunctionCall::addParam(Expr* aExpr)
{
if (expr)
params.add(expr);
if (aExpr)
params.add(aExpr);
return NS_OK;
} //-- addParam
/**
* Returns the default priority of this Expr based on the given Node,
* context Node, and ContextState.
**/
double FunctionCall::getDefaultPriority(Node* node,
Node* context,
ContextState* cs)
{
return 0.5;
} //-- getDefaultPriority
/**
* Determines whether this Expr matches the given node within
* the given context
**/
MBool FunctionCall::matches(Node* node, Node* context, ContextState* cs)
{
MBool result = MB_FALSE;
ExprResult* exprResult = evaluate(node, cs);
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* nodes = (NodeSet*)exprResult;
result = (nodes->contains(node));
}
delete exprResult;
return result;
} //-- matches
/*
* Evaluates the given Expression and converts its result to a String.
* The value is appended to the given destination String
*/
void FunctionCall::evaluateToString(Expr* aExpr,
Node* aContext,
ContextState* aCs,
void FunctionCall::evaluateToString(Expr* aExpr, txIEvalContext* aContext,
String& aDest)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext, aCs);
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return;
@ -131,12 +104,10 @@ void FunctionCall::evaluateToString(Expr* aExpr,
/*
* Evaluates the given Expression and converts its result to a number.
*/
double FunctionCall::evaluateToNumber(Expr* aExpr,
Node* aContext,
ContextState* aCs)
double FunctionCall::evaluateToNumber(Expr* aExpr, txIEvalContext* aContext)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext, aCs);
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return Double::NaN;
@ -148,12 +119,10 @@ double FunctionCall::evaluateToNumber(Expr* aExpr,
/*
* Evaluates the given Expression and converts its result to a boolean.
*/
MBool FunctionCall::evaluateToBoolean(Expr* aExpr,
Node* aContext,
ContextState* aCs)
MBool FunctionCall::evaluateToBoolean(Expr* aExpr, txIEvalContext* aContext)
{
NS_ASSERTION(aExpr, "missing expression");
ExprResult* exprResult = aExpr->evaluate(aContext, aCs);
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return MB_FALSE;
@ -166,18 +135,16 @@ MBool FunctionCall::evaluateToBoolean(Expr* aExpr,
* Evaluates the given Expression and converts its result to a NodeSet.
* If the result is not a NodeSet NULL is returned.
*/
NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr,
Node* aContext,
ContextState* aCs)
NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr, txIEvalContext* aContext)
{
NS_ASSERTION(aExpr, "Missing expression to evaluate");
ExprResult* exprResult = aExpr->evaluate(aContext, aCs);
ExprResult* exprResult = aExpr->evaluate(aContext);
if (!exprResult)
return 0;
if (exprResult->getResultType() != ExprResult::NODESET) {
String err("NodeSet expected as argument");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
delete exprResult;
return 0;
}
@ -190,13 +157,13 @@ NodeSet* FunctionCall::evaluateToNodeSet(Expr* aExpr,
**/
MBool FunctionCall::requireParams (int paramCountMin,
int paramCountMax,
ContextState* cs)
txIEvalContext* aContext)
{
int argc = params.getLength();
if ((argc < paramCountMin) || (argc > paramCountMax)) {
String err(INVALID_PARAM_COUNT);
toString(err);
cs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
return MB_FALSE;
}
return MB_TRUE;
@ -205,13 +172,13 @@ MBool FunctionCall::requireParams (int paramCountMin,
/**
* Called to check number of parameters
**/
MBool FunctionCall::requireParams(int paramCountMin, ContextState* cs)
MBool FunctionCall::requireParams(int paramCountMin, txIEvalContext* aContext)
{
int argc = params.getLength();
if (argc < paramCountMin) {
String err(INVALID_PARAM_COUNT);
toString(err);
cs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
return MB_FALSE;
}
return MB_TRUE;

Просмотреть файл

@ -125,14 +125,7 @@ public:
**/
BooleanFunctionCall(BooleanFunctions aType);
/**
* 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
**/
ExprResult* evaluate(Node* aContext, ContextState* aCs);
TX_DECL_EVALUATE;
private:
BooleanFunctions mType;
@ -148,14 +141,7 @@ public:
ErrorFunctionCall();
ErrorFunctionCall(const String& errorMsg);
/**
* 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
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
TX_DECL_EVALUATE;
void setErrorMessage(String& errorMsg);
@ -165,89 +151,6 @@ private:
}; //-- ErrorFunctionCall
/**
* Used for extension functions
**/
class ExtensionFunctionCall : public FunctionCall {
public:
static const String UNDEFINED_FUNCTION;
/**
* Creates a new ExtensionFunctionCall with the given function name
* @param name the name of the extension function
**/
ExtensionFunctionCall(const String& name);
/**
* Destructor for extension function call
**/
virtual ~ExtensionFunctionCall();
/**
* 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
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
private:
String fname;
FunctionCall* fnCall;
};
/**
* This class is used by ExtensionFunctionCall, to prevent deletion
* of the parameter expressions, by the resolved function call. The implementation
* for this class is in ExtensionFunctionCall.cpp
**/
class ExprWrapper : public Expr {
public:
/**
* Creates a new ExprWrapper for the given Expr
**/
ExprWrapper(Expr* expr);
/**
* Destructor for ExprWrapper
**/
virtual ~ExprWrapper();
/**
* 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
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
virtual void toString(String& str);
private:
Expr* expr;
}; //-- ExprWrapper
/*
* A representation of the XPath NodeSet funtions
*/
@ -270,14 +173,7 @@ public:
*/
NodeSetFunctionCall(NodeSetFunctions aType);
/*
* 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
*/
ExprResult* evaluate(Node* aContext, ContextState* aCs);
TX_DECL_EVALUATE;
private:
NodeSetFunctions mType;
@ -309,14 +205,7 @@ public:
**/
StringFunctionCall(StringFunctions aType);
/**
* 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
**/
ExprResult* evaluate(Node* aContext, ContextState* aCs);
TX_DECL_EVALUATE;
private:
StringFunctions mType;
@ -343,14 +232,7 @@ public:
*/
NumberFunctionCall(NumberFunctions aType);
/*
* 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
*/
ExprResult* evaluate(Node* aContext, ContextState* aCs);
TX_DECL_EVALUATE;
private:
NumberFunctions mType;

Просмотреть файл

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __TX_I_XPATH_CONTEXT
#define __TX_I_XPATH_CONTEXT
#include "Expr.h"
#include "txError.h"
/*
* txIParseContext
*
* This interface describes the context needed to create
* XPath Expressions and XSLT Patters.
* (not completely though. key() requires the ProcessorState, which is
* not part of this interface.)
*/
class txIParseContext
{
public:
virtual ~txIParseContext()
{
}
/*
* Return a namespaceID for a given prefix.
*/
virtual nsresult resolveNamespacePrefix(txAtom* aPrefix, PRInt32& aID) = 0;
/*
* Create a FunctionCall, needed for extension function calls and
* XSLT. XPath function calls are resolved by the Parser.
*/
virtual nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID,
FunctionCall*& aFunction) = 0;
/*
* Callback to be used by the Parser if errors are detected.
*/
virtual void receiveError(const String& aMsg, nsresult aRes) = 0;
};
/*
* txIMatchContext
*
* Interface used for matching XSLT Patters.
* This is the part of txIEvalContext (see below), that is independent
* of the context node when evaluating a XPath expression, too.
* When evaluating a XPath expression, |txIMatchContext|s are used
* to transport the information from Step to Step.
*/
class txIMatchContext
{
public:
virtual ~txIMatchContext()
{
}
/*
* Return the ExprResult associated with the variable with the
* given namespace and local name.
*/
virtual nsresult getVariable(PRInt32 aNamespace, txAtom* aLName,
ExprResult*& aResult) = 0;
/*
* Is whitespace stripping allowed for the given node?
* See http://www.w3.org/TR/xslt#strip
*/
virtual MBool isStripSpaceAllowed(Node* aNode) = 0;
/*
* Callback to be used by the expression/pattern if errors are detected.
*/
virtual void receiveError(const String& aMsg, nsresult aRes) = 0;
};
#define TX_DECL_MATCH_CONTEXT \
nsresult getVariable(PRInt32 aNamespace, txAtom* aLName, \
ExprResult*& aResult); \
MBool isStripSpaceAllowed(Node* aNode); \
void receiveError(const String& aMsg, nsresult aRes)
class txIEvalContext : public txIMatchContext
{
public:
virtual ~txIEvalContext()
{
}
/*
* Get the context node.
*/
virtual Node* getContextNode() = 0;
/*
* Get the size of the context node set.
*/
virtual PRUint32 size() = 0;
/*
* Get the position of the context node in the context node set,
* starting with 1.
*/
virtual PRUint32 position() = 0;
};
#define TX_DECL_EVAL_CONTEXT \
TX_DECL_MATCH_CONTEXT; \
Node* getContextNode(); \
PRUint32 size(); \
PRUint32 position()
#endif // __TX_I_XPATH_CONTEXT

Просмотреть файл

@ -28,15 +28,17 @@
*/
#include "Expr.h"
#include "txIXPathContext.h"
/**
* Creates a new LocationStep using the given NodeExpr and Axis Identifier
* @param nodeExpr the NodeExpr to use when matching Nodes
* @param axisIdentifier the Axis Identifier in which to search for nodes
**/
LocationStep::LocationStep(NodeExpr* nodeExpr, short axisIdentifier) : PredicateList() {
this->nodeExpr = nodeExpr;
this->axisIdentifier = axisIdentifier;
LocationStep::LocationStep(txNodeTest* aNodeTest,
LocationStepType aAxisIdentifier)
: mNodeTest(aNodeTest), mAxisIdentifier(aAxisIdentifier)
{
} //-- LocationStep
/**
@ -45,7 +47,7 @@ LocationStep::LocationStep(NodeExpr* nodeExpr, short axisIdentifier) : Predicate
* The NodeExpr will be deleted
**/
LocationStep::~LocationStep() {
delete nodeExpr;
delete mNodeTest;
} //-- ~LocationStep
//-----------------------------/
@ -60,23 +62,25 @@ LocationStep::~LocationStep() {
* @return the result of the evaluation
* @see Expr
**/
ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
ExprResult* LocationStep::evaluate(txIEvalContext* aContext)
{
NS_ASSERTION(aContext, "internal error");
NodeSet* nodes = new NodeSet();
if (!context || !nodeExpr || !nodes)
return nodes;
if (!nodes)
return 0;
MBool reverse = MB_FALSE;
Node* node = context;
switch (axisIdentifier) {
Node* node = aContext->getContextNode();
switch (mAxisIdentifier) {
case ANCESTOR_AXIS :
node = context->getXPathParent();
node = node->getXPathParent();
//-- do not break here
case ANCESTOR_OR_SELF_AXIS :
reverse = MB_TRUE;
while (node) {
if (nodeExpr->matches(node, context, cs)) {
if (mNodeTest->matches(node, aContext)) {
nodes->append(node);
}
node = node->getXPathParent();
@ -84,28 +88,28 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
break;
case ATTRIBUTE_AXIS :
{
NamedNodeMap* atts = context->getAttributes();
NamedNodeMap* atts = node->getAttributes();
if (atts) {
for (PRUint32 i = 0; i < atts->getLength(); i++) {
Node* attr = atts->item(i);
if (nodeExpr->matches(attr, context, cs))
if (mNodeTest->matches(attr, aContext))
nodes->append(attr);
}
}
break;
}
case DESCENDANT_OR_SELF_AXIS :
if (nodeExpr->matches(context, context, cs))
nodes->append(context);
if (mNodeTest->matches(node, aContext))
nodes->append(node);
//-- do not break here
case DESCENDANT_AXIS :
fromDescendants(context, cs, nodes);
fromDescendants(node, aContext, nodes);
break;
case FOLLOWING_AXIS :
{
if ( node->getNodeType() == Node::ATTRIBUTE_NODE) {
node = node->getXPathParent();
fromDescendants(node, cs, nodes);
fromDescendants(node, aContext, nodes);
}
while (node && !node->getNextSibling()) {
node = node->getXPathParent();
@ -113,11 +117,11 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
while (node) {
node = node->getNextSibling();
if (nodeExpr->matches(node, context, cs))
if (mNodeTest->matches(node, aContext))
nodes->append(node);
if (node->hasChildNodes())
fromDescendants(node, cs, nodes);
fromDescendants(node, aContext, nodes);
while (node && !node->getNextSibling()) {
node = node->getParentNode();
@ -126,9 +130,9 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
break;
}
case FOLLOWING_SIBLING_AXIS :
node = context->getNextSibling();
node = node->getNextSibling();
while (node) {
if (nodeExpr->matches(node, context, cs))
if (mNodeTest->matches(node, aContext))
nodes->append(node);
node = node->getNextSibling();
}
@ -141,8 +145,8 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
break;
case PARENT_AXIS :
{
Node* parent = context->getXPathParent();
if ( nodeExpr->matches(parent, context, cs) )
Node* parent = node->getXPathParent();
if (mNodeTest->matches(parent, aContext))
nodes->append(parent);
break;
}
@ -155,9 +159,9 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
node = node->getPreviousSibling();
if (node->hasChildNodes())
fromDescendantsRev(node, cs, nodes);
fromDescendantsRev(node, aContext, nodes);
if (nodeExpr->matches(node, context, cs))
if (mNodeTest->matches(node, aContext))
nodes->append(node);
while (node && !node->getPreviousSibling()) {
@ -167,56 +171,48 @@ ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) {
break;
case PRECEDING_SIBLING_AXIS:
reverse = MB_TRUE;
node = context->getPreviousSibling();
node = node->getPreviousSibling();
while (node) {
if (nodeExpr->matches(node, context, cs))
if (mNodeTest->matches(node, aContext))
nodes->append(node);
node = node->getPreviousSibling();
}
break;
case SELF_AXIS :
if (nodeExpr->matches(context, context, cs))
nodes->append(context);
if (mNodeTest->matches(node, aContext))
nodes->append(node);
break;
default: //-- Children Axis
{
Node* tmpNode = context->getFirstChild();
while (tmpNode) {
if (nodeExpr->matches(tmpNode, context, cs))
nodes->append(tmpNode);
tmpNode = tmpNode->getNextSibling();
node = node->getFirstChild();
while (node) {
if (mNodeTest->matches(node, aContext))
nodes->append(node);
node = node->getNextSibling();
}
break;
}
} //-- switch
//-- apply predicates
evaluatePredicates(nodes, cs);
if (!isEmpty())
evaluatePredicates(nodes, aContext);
if (reverse)
nodes->reverse();
return nodes;
} //-- evaluate
}
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
**/
double LocationStep::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
if (isEmpty())
return nodeExpr->getDefaultPriority(node, context, cs);
return 0.5;
} //-- getDefaultPriority
void LocationStep::fromDescendants(Node* node, txIMatchContext* cs,
NodeSet* nodes)
{
if (!node)
return;
void LocationStep::fromDescendants(Node* context, ContextState* cs, NodeSet* nodes) {
if ( !context || !nodeExpr ) return;
Node* child = context->getFirstChild();
Node* child = node->getFirstChild();
while (child) {
if (nodeExpr->matches(child, context, cs))
if (mNodeTest->matches(child, cs))
nodes->append(child);
//-- check childs descendants
if (child->hasChildNodes())
@ -227,17 +223,19 @@ void LocationStep::fromDescendants(Node* context, ContextState* cs, NodeSet* nod
} //-- fromDescendants
void LocationStep::fromDescendantsRev(Node* context, ContextState* cs, NodeSet* nodes) {
void LocationStep::fromDescendantsRev(Node* node, txIMatchContext* cs,
NodeSet* nodes)
{
if (!node)
return;
if ( !context || !nodeExpr ) return;
Node* child = context->getLastChild();
Node* child = node->getLastChild();
while (child) {
//-- check childs descendants
if (child->hasChildNodes())
fromDescendantsRev(child, cs, nodes);
if (nodeExpr->matches(child, context, cs))
if (mNodeTest->matches(child, cs))
nodes->append(child);
child = child->getPreviousSibling();
@ -245,40 +243,13 @@ void LocationStep::fromDescendantsRev(Node* context, ContextState* cs, NodeSet*
} //-- fromDescendantsRev
/**
* Determines whether this Expr matches the given node within
* the given context
**/
MBool LocationStep::matches(Node* node, Node* context, ContextState* cs) {
if (!nodeExpr || !node)
return MB_FALSE;
if (!nodeExpr->matches(node, context, cs))
return MB_FALSE;
MBool result = MB_TRUE;
if (!isEmpty()) {
NodeSet* nodes = (NodeSet*)evaluate(node->getXPathParent(),cs);
result = nodes->contains(node);
delete nodes;
}
else if (axisIdentifier == CHILD_AXIS ) {
if (!node->getParentNode())
result = MB_FALSE;
}
return result;
} //-- matches
/**
* Creates a String representation of this Expr
* @param str the destination String to append to
* @see Expr
**/
void LocationStep::toString(String& str) {
switch (axisIdentifier) {
switch (mAxisIdentifier) {
case ANCESTOR_AXIS :
str.append("ancestor::");
break;
@ -318,8 +289,9 @@ void LocationStep::toString(String& str) {
default:
break;
}
if ( nodeExpr ) nodeExpr->toString(str);
else str.append("null");
PredicateList::toString(str);
} //-- toString
NS_ASSERTION(mNodeTest, "mNodeTest is null, that's verboten");
mNodeTest->toString(str);
PredicateList::toString(str);
} // toString

Просмотреть файл

@ -59,21 +59,20 @@ MultiplicativeExpr::~MultiplicativeExpr() {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* MultiplicativeExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* MultiplicativeExpr::evaluate(txIEvalContext* aContext)
{
double rightDbl = Double::NaN;
ExprResult* exprRes = 0;
if ( rightExpr ) {
exprRes = rightExpr->evaluate(context, cs);
exprRes = rightExpr->evaluate(aContext);
if ( exprRes ) rightDbl = exprRes->numberValue();
delete exprRes;
}
double leftDbl = Double::NaN;
if ( leftExpr ) {
exprRes = leftExpr->evaluate(context, cs);
exprRes = leftExpr->evaluate(aContext);
if ( exprRes ) leftDbl = exprRes->numberValue();
delete exprRes;
}

Просмотреть файл

@ -0,0 +1,106 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
*/
#include "Expr.h"
#include "txAtoms.h"
#include "txIXPathContext.h"
txNameTest::txNameTest(txAtom* aPrefix, txAtom* aLocalName, PRInt32 aNSID,
Node::NodeType aNodeType)
:mPrefix(aPrefix), mLocalName(aLocalName), mNamespace(aNSID),
mNodeType(aNodeType)
{
if (aPrefix == txXMLAtoms::_empty)
mPrefix = 0;
NS_ASSERTION(aLocalName, "txNameTest without a local name?");
TX_IF_ADDREF_ATOM(mPrefix);
TX_IF_ADDREF_ATOM(mLocalName);
}
txNameTest::~txNameTest()
{
TX_IF_RELEASE_ATOM(mPrefix);
TX_IF_RELEASE_ATOM(mLocalName);
}
/*
* Determines whether this txNodeTest matches the given node
*/
MBool txNameTest::matches(Node* aNode, txIMatchContext* aContext)
{
if (!aNode || aNode->getNodeType() != mNodeType)
return MB_FALSE;
// Totally wild?
if (mLocalName == txXPathAtoms::_asterix && !mPrefix)
return MB_TRUE;
// Compare namespaces
if (aNode->getNamespaceID() != mNamespace)
return MB_FALSE;
// Name wild?
if (mLocalName == txXPathAtoms::_asterix)
return MB_TRUE;
// Compare local-names
txAtom* localName;
aNode->getLocalName(&localName);
MBool result = localName == mLocalName;
TX_IF_RELEASE_ATOM(localName);
return result;
}
/*
* Returns the default priority of this txNodeTest
*/
double txNameTest::getDefaultPriority()
{
if (mLocalName == txXPathAtoms::_asterix) {
if (!mPrefix)
return -0.5;
return -0.25;
}
return 0;
}
/*
* Returns the String representation of this txNodeTest.
* @param aDest the String to use when creating the string representation.
* The string representation will be appended to the string.
*/
void txNameTest::toString(String& aDest)
{
if (mPrefix) {
String prefix;
TX_GET_ATOM_STRING(mPrefix, prefix);
aDest.append(prefix);
aDest.append(':');
}
String localName;
TX_GET_ATOM_STRING(mLocalName, localName);
aDest.append(localName);
}

Просмотреть файл

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txNodeSetContext.h"
Node* txNodeSetContext::getContextNode()
{
return mContextSet->get(mPosition - 1);
}
PRUint32 txNodeSetContext::size()
{
return (PRUint32)mContextSet->size();
}
PRUint32 txNodeSetContext::position()
{
NS_ASSERTION(mPosition, "Should have called next() at least once");
return mPosition;
}
nsresult txNodeSetContext::getVariable(PRInt32 aNamespace, txAtom* aLName,
ExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
}
MBool txNodeSetContext::isStripSpaceAllowed(Node* aNode)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
}
void txNodeSetContext::receiveError(const String& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");
#ifdef DEBUG
String error("forwarded error: ");
error.append(aMsg);
mInner->receiveError(error, aRes);
#else
mInner->receiveError(aMsg, aRes);
#endif
}

Просмотреть файл

@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __TX_XPATH_SET_CONTEXT
#define __TX_XPATH_SET_CONTEXT
#include "txIXPathContext.h"
class txNodeSetContext : public txIEvalContext
{
public:
txNodeSetContext(NodeSet* aContextNodeSet, txIMatchContext* aContext)
: mContextSet(aContextNodeSet), mPosition(0), mInner(aContext)
{
}
~txNodeSetContext()
{
}
// Iteration over the given NodeSet
MBool hasNext()
{
return mPosition < size();
}
void next()
{
NS_ASSERTION(mPosition < size(), "Out of bounds.");
mPosition++;
}
TX_DECL_EVAL_CONTEXT;
private:
NodeSet* mContextSet;
PRUint32 mPosition;
txIMatchContext* mInner;
};
#endif // __TX_XPATH_SET_CONTEXT

Просмотреть файл

@ -36,6 +36,7 @@
#include "XMLDOMUtils.h"
#include "Tokenizer.h"
#include "txAtom.h"
#include "txIXPathContext.h"
/*
* Creates a NodeSetFunctionCall of the given type
@ -75,16 +76,16 @@ NodeSetFunctionCall::NodeSetFunctionCall(NodeSetFunctions aType)
* for evaluation
* @return the result of the evaluation
*/
ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
ExprResult* NodeSetFunctionCall::evaluate(txIEvalContext* aContext) {
ListIterator iter(&params);
switch (mType) {
case COUNT:
{
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext, aCs);
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult("error");
@ -94,11 +95,11 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
}
case ID:
{
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
ExprResult* exprResult;
exprResult = ((Expr*)iter.next())->evaluate(aContext, aCs);
exprResult = ((Expr*)iter.next())->evaluate(aContext);
if (!exprResult)
return new StringResult("error");
@ -108,11 +109,12 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
return 0;
}
Document* contextDoc;
if (aContext->getNodeType() == Node::DOCUMENT_NODE)
contextDoc = (Document*)aContext;
Document* contextDoc = 0;
Node* contextNode = aContext->getContextNode();
if (contextNode->getNodeType() == Node::DOCUMENT_NODE)
contextDoc = (Document*)contextNode;
else
contextDoc = aContext->getOwnerDocument();
contextDoc = contextNode->getOwnerDocument();
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* nodes = (NodeSet*)exprResult;
@ -123,7 +125,9 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
txTokenizer tokenizer(idList);
while (tokenizer.hasMoreTokens()) {
tokenizer.nextToken(id);
resultSet->add(contextDoc->getElementById(id));
Node* idNode = contextDoc->getElementById(id);
if (idNode)
resultSet->add(idNode);
}
}
}
@ -133,7 +137,9 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
txTokenizer tokenizer(idList);
while (tokenizer.hasMoreTokens()) {
tokenizer.nextToken(id);
resultSet->add(contextDoc->getElementById(id));
Node* idNode = contextDoc->getElementById(id);
if (idNode)
resultSet->add(idNode);
}
}
delete exprResult;
@ -142,30 +148,23 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
}
case LAST:
{
if (!requireParams(0, 0, aCs))
if (!requireParams(0, 0, aContext))
return new StringResult("error");
NodeSet* contextNodeSet = (NodeSet*)aCs->getNodeSetStack()->peek();
if (!contextNodeSet) {
String err("Internal error");
aCs->recieveError(err);
return new StringResult("error");
}
return new NumberResult(contextNodeSet->size());
return new NumberResult(aContext->size());
}
case LOCAL_NAME:
case NAME:
case NAMESPACE_URI:
{
if (!requireParams(0, 1, aCs))
if (!requireParams(0, 1, aContext))
return new StringResult("error");
Node* node = 0;
// Check for optional arg
if (iter.hasNext()) {
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext, aCs);
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult("error");
@ -177,7 +176,7 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
delete nodes;
}
else {
node = aContext;
node = aContext->getContextNode();
}
switch (mType) {
@ -219,21 +218,14 @@ ExprResult* NodeSetFunctionCall::evaluate(Node* aContext, ContextState* aCs) {
}
case POSITION:
{
if (!requireParams(0, 0, aCs))
if (!requireParams(0, 0, aContext))
return new StringResult("error");
NodeSet* contextNodeSet = (NodeSet*)aCs->getNodeSetStack()->peek();
if (!contextNodeSet) {
String err("Internal error");
aCs->recieveError(err);
return new StringResult("error");
}
return new NumberResult(contextNodeSet->indexOf(aContext) + 1);
return new NumberResult(aContext->position());
}
}
String err("Internal error");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_UNEXPECTED);
return new StringResult("error");
}

Просмотреть файл

@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
*/
#include "Expr.h"
#include "txAtom.h"
#include "txIXPathContext.h"
/*
* Creates a new txNodeTypeTest of the given type
*/
txNodeTypeTest::txNodeTypeTest(NodeType aNodeType)
: mNodeType(aNodeType), mNodeName(0)
{
}
txNodeTypeTest::~txNodeTypeTest()
{
TX_IF_RELEASE_ATOM(mNodeName);
}
void txNodeTypeTest::setNodeName(const String& aName)
{
mNodeName = TX_GET_ATOM(aName);
}
/*
* Determines whether this txNodeTest matches the given node
*/
MBool txNodeTypeTest::matches(Node* aNode, txIMatchContext* aContext)
{
if (!aNode)
return MB_FALSE;
Node::NodeType type = (Node::NodeType)aNode->getNodeType();
switch (mNodeType) {
case COMMENT_TYPE:
return type == Node::COMMENT_NODE;
case TEXT_TYPE:
return (type == Node::TEXT_NODE ||
type == Node::CDATA_SECTION_NODE) &&
!aContext->isStripSpaceAllowed(aNode);
case PI_TYPE:
if (type == Node::PROCESSING_INSTRUCTION_NODE) {
txAtom* localName = 0;
MBool result;
result = !mNodeName ||
(aNode->getLocalName(&localName) &&
localName == mNodeName);
TX_IF_RELEASE_ATOM(localName);
return result;
}
return MB_FALSE;
case NODE_TYPE:
return ((type != Node::TEXT_NODE &&
type != Node::CDATA_SECTION_NODE) ||
!aContext->isStripSpaceAllowed(aNode));
}
return MB_TRUE;
}
/*
* Returns the default priority of this txNodeTest
*/
double txNodeTypeTest::getDefaultPriority()
{
return mNodeName ? 0 : -0.5;
}
/*
* Returns the String representation of this txNodeTest.
* @param aDest the String to use when creating the string representation.
* The string representation will be appended to the string.
*/
void txNodeTypeTest::toString(String& aDest)
{
switch (mNodeType) {
case COMMENT_TYPE:
aDest.append("comment()");
break;
case TEXT_TYPE:
aDest.append("text()");
break;
case PI_TYPE:
aDest.append("processing-instruction(");
if (mNodeName) {
String str;
TX_GET_ATOM_STRING(mNodeName, str);
aDest.append('\'');
aDest.append(str);
aDest.append('\'');
}
aDest.append(')');
break;
case NODE_TYPE:
aDest.append("node()");
break;
}
}

Просмотреть файл

@ -36,6 +36,7 @@
#include "FunctionLib.h"
#include "XMLDOMUtils.h"
#include <math.h>
#include "txIXPathContext.h"
/*
* Creates a NumberFunctionCall of the given type
@ -68,23 +69,23 @@ NumberFunctionCall::NumberFunctionCall(NumberFunctions aType) {
* for evaluation
* @return the result of the evaluation
*/
ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs)
ExprResult* NumberFunctionCall::evaluate(txIEvalContext* aContext)
{
ListIterator iter(&params);
if (mType == NUMBER) {
if (!requireParams(0, 1, aCs))
if (!requireParams(0, 1, aContext))
return new StringResult("error");
}
else {
if (!requireParams(1, 1, aCs))
if (!requireParams(1, 1, aContext))
return new StringResult("error");
}
switch (mType) {
case CEILING:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs);
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) || Double::isInfinite(dbl))
return new NumberResult(dbl);
@ -95,7 +96,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case FLOOR:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs);
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) ||
Double::isInfinite(dbl) ||
(dbl == 0 && Double::isNeg(dbl)))
@ -105,7 +106,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case ROUND:
{
double dbl = evaluateToNumber((Expr*)iter.next(), aContext, aCs);
double dbl = evaluateToNumber((Expr*)iter.next(), aContext);
if (Double::isNaN(dbl) || Double::isInfinite(dbl))
return new NumberResult(dbl);
@ -117,7 +118,7 @@ ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs)
case SUM:
{
NodeSet* nodes;
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext, aCs);
nodes = evaluateToNodeSet((Expr*)iter.next(), aContext);
if (!nodes)
return new StringResult("error");
@ -137,16 +138,16 @@ ExprResult* NumberFunctionCall::evaluate(Node* aContext, ContextState* aCs)
{
if (iter.hasNext()) {
return new NumberResult(
evaluateToNumber((Expr*)iter.next(), aContext, aCs));
evaluateToNumber((Expr*)iter.next(), aContext));
}
String resultStr;
XMLDOMUtils::getNodeValue(aContext, resultStr);
XMLDOMUtils::getNodeValue(aContext->getContextNode(), resultStr);
return new NumberResult(Double::toDouble(resultStr));
}
}
String err("Internal error");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_UNEXPECTED);
return new StringResult("error");
}

Просмотреть файл

@ -33,11 +33,17 @@
#include "Expr.h"
#include "XMLUtils.h"
#include "txNodeSetContext.h"
#include "txSingleNodeContext.h"
//------------/
//- PathExpr -/
//------------/
const String PathExpr::RTF_INVALID_OP =
"Result tree fragments don't allow location steps";
const String PathExpr::NODESET_EXPECTED =
"Filter expression must evaluate to a NodeSet";
/**
* Creates a new PathExpr
@ -94,12 +100,14 @@ void PathExpr::addExpr(Expr* expr, PathOperator pathOp)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* PathExpr::evaluate(Node* context, ContextState* cs)
ExprResult* PathExpr::evaluate(txIEvalContext* aContext)
{
if (!context || !expressions.getLength())
if (!aContext || (expressions.getLength() == 0)) {
NS_ASSERTION(0, "internal error");
return new StringResult("error");
}
NodeSet* nodes = new NodeSet(context);
NodeSet* nodes = new NodeSet(aContext->getContextNode());
if (!nodes) {
// XXX ErrorReport: out of memory
NS_ASSERTION(0, "out of memory");
@ -111,16 +119,18 @@ ExprResult* PathExpr::evaluate(Node* context, ContextState* cs)
while ((pxi = (PathExprItem*)iter.next())) {
NodeSet* tmpNodes = 0;
for (int i = 0; i < nodes->size(); i++) {
Node* node = nodes->get(i);
txNodeSetContext eContext(nodes, aContext);
while (eContext.hasNext()) {
eContext.next();
Node* node = eContext.getContextNode();
NodeSet* resNodes;
if (pxi->pathOp == DESCENDANT_OP) {
resNodes = new NodeSet;
evalDescendants(pxi->expr, node, cs, resNodes);
evalDescendants(pxi->expr, node, &eContext, resNodes);
}
else {
ExprResult *res = pxi->expr->evaluate(node, cs);
ExprResult *res = pxi->expr->evaluate(&eContext);
if (!res || (res->getResultType() != ExprResult::NODESET)) {
//XXX ErrorReport: report nonnodeset error
delete res;
@ -147,12 +157,13 @@ ExprResult* PathExpr::evaluate(Node* context, ContextState* cs)
/**
* Selects from the descendants of the context node
* all nodes that match the Expr
* -- this will be moving to a Utility class
**/
void PathExpr::evalDescendants (Expr* expr, Node* context,
ContextState* cs, NodeSet* resNodes)
void PathExpr::evalDescendants (Expr* aStep, Node* aNode,
txIMatchContext* aContext,
NodeSet* resNodes)
{
ExprResult *res = expr->evaluate(context, cs);
txSingleNodeContext eContext(aNode, aContext);
ExprResult *res = aStep->evaluate(&eContext);
if (!res || (res->getResultType() != ExprResult::NODESET)) {
//XXX ErrorReport: report nonnodeset error
}
@ -161,107 +172,19 @@ void PathExpr::evalDescendants (Expr* expr, Node* context,
}
delete res;
MBool filterWS = cs->isStripSpaceAllowed(context);
MBool filterWS = aContext->isStripSpaceAllowed(aNode);
Node* child = context->getFirstChild();
Node* child = aNode->getFirstChild();
while (child) {
if (!(filterWS &&
(child->getNodeType() == Node::TEXT_NODE ||
child->getNodeType() == Node::CDATA_SECTION_NODE) &&
XMLUtils::shouldStripTextnode(child->getNodeValue())))
evalDescendants(expr, child, cs, resNodes);
evalDescendants(aStep, child, aContext, resNodes);
child = child->getNextSibling();
}
} //-- evalDescendants
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
**/
double PathExpr::getDefaultPriority(Node* node, Node* context,
ContextState* cs)
{
int size = expressions.getLength();
if (size > 1)
return 0.5;
return ((PathExprItem*)expressions.get(0))->
expr->getDefaultPriority(node, context, cs);
} //-- getDefaultPriority
/**
* Determines whether this Expr matches the given node within
* the given context
**/
MBool PathExpr::matches(Node* node, Node* context, ContextState* cs)
{
/*
* The idea is to split up a path into blocks separated by descendant
* operators. For example "foo/bar//baz/bop//ying/yang" is split up into
* three blocks. The "ying/yang" block is handled by the first while-loop
* and the "foo/bar" and "baz/bop" blocks are handled by the second
* while-loop.
* A block is considered matched when we find a list of ancestors that
* match the block. If there are more than one list of ancestors that
* match a block we only need to find the one furthermost down in the
* tree.
*/
if (!node || (expressions.getLength() == 0))
return MB_FALSE;
ListIterator iter(&expressions);
iter.resetToEnd();
PathExprItem* pxi;
PathOperator pathOp = RELATIVE_OP;
while (pathOp == RELATIVE_OP) {
pxi = (PathExprItem*)iter.previous();
if (!pxi)
return MB_TRUE; // We've stepped through the entire list
if (!node || !pxi->expr->matches(node, 0, cs))
return MB_FALSE;
node = node->getXPathParent();
pathOp = pxi->pathOp;
}
// We have at least one DESCENDANT_OP
Node* blockStart = node;
ListIterator blockIter(iter);
while ((pxi = (PathExprItem*)iter.previous())) {
if (!node)
return MB_FALSE; // There are more steps in the current block
// then ancestors of the tested node
if (!pxi->expr->matches(node, 0, cs)) {
// Didn't match. We restart at beginning of block using a new
// start node
iter = blockIter;
blockStart = blockStart->getXPathParent();
node = blockStart;
}
else {
node = node->getXPathParent();
if (pxi->pathOp == DESCENDANT_OP) {
// We've matched an entire block. Set new start iter and start node
blockIter = iter;
blockStart = node;
}
}
}
return MB_TRUE;
} //-- matches
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String

Просмотреть файл

@ -24,6 +24,7 @@
*/
#include "Expr.h"
#include "txNodeSetContext.h"
/*
* Represents an ordered list of Predicates,
@ -56,38 +57,39 @@ void PredicateList::add(Expr* expr)
predicates.add(expr);
} // add
void PredicateList::evaluatePredicates(NodeSet* nodes, ContextState* cs)
void PredicateList::evaluatePredicates(NodeSet* nodes,
txIMatchContext* aContext)
{
NS_ASSERTION(nodes, "called evaluatePredicates with NULL NodeSet");
if (!nodes)
return;
cs->getNodeSetStack()->push(nodes);
NodeSet newNodes;
txListIterator iter(&predicates);
while (iter.hasNext()) {
while (iter.hasNext() && !nodes->isEmpty()) {
Expr* expr = (Expr*)iter.next();
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
*/
newNodes.clear();
int nIdx;
for (nIdx = 0; nIdx < nodes->size(); nIdx++) {
Node* node = nodes->get(nIdx);
ExprResult* exprResult = expr->evaluate(node, cs);
while (predContext.hasNext()) {
predContext.next();
ExprResult* exprResult = expr->evaluate(&predContext);
if (!exprResult)
break;
switch(exprResult->getResultType()) {
case ExprResult::NUMBER :
// handle default, [position() == numberValue()]
if ((double)(nIdx+1) == exprResult->numberValue())
newNodes.append(node);
if ((double)predContext.position() ==
exprResult->numberValue())
newNodes.append(predContext.getContextNode());
break;
default:
if (exprResult->booleanValue())
newNodes.append(node);
newNodes.append(predContext.getContextNode());
break;
}
delete exprResult;
@ -96,7 +98,6 @@ void PredicateList::evaluatePredicates(NodeSet* nodes, ContextState* cs)
nodes->clear();
nodes->append(&newNodes);
}
cs->getNodeSetStack()->pop();
}
/*

Просмотреть файл

@ -204,16 +204,19 @@ MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* RelationalExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* RelationalExpr::evaluate(txIEvalContext* aContext)
{
//-- get result of left expression
ExprResult* lResult = 0;
if ( leftExpr ) lResult = leftExpr->evaluate(context, cs);
else return new BooleanResult();
if (leftExpr)
lResult = leftExpr->evaluate(aContext);
else
return new BooleanResult();
//-- get result of right expr
ExprResult* rResult = 0;
if ( rightExpr ) rResult = rightExpr->evaluate(context, cs);
if (rightExpr)
rResult = rightExpr->evaluate(aContext);
else {
delete lResult;
return new BooleanResult();

Просмотреть файл

@ -24,6 +24,7 @@
*/
#include "Expr.h"
#include "txIXPathContext.h"
/**
* Creates a new RootExpr
@ -40,32 +41,19 @@ RootExpr::RootExpr(MBool aSerialize) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* RootExpr::evaluate(Node* context, ContextState* cs)
ExprResult* RootExpr::evaluate(txIEvalContext* aContext)
{
if (!context)
return new StringResult("error");
Node* context;
if (!aContext || !(context = aContext->getContextNode())) {
NS_ASSERTION(0, "internal error");
return 0;
}
if (context->getNodeType() != Node::DOCUMENT_NODE)
return new NodeSet(context->getOwnerDocument());
return new NodeSet(context);
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
**/
double RootExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) {
return 0.5;
} //-- getDefaultPriority
/**
* Determines whether this NodeExpr matches the given node within
* the given context
**/
MBool RootExpr::matches(Node* node, Node* context, ContextState* cs) {
return node && (node->getNodeType() == Node::DOCUMENT_NODE);
} //-- matches
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String

Просмотреть файл

@ -0,0 +1,101 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __TX_XPATH_SINGLENODE_CONTEXT
#define __TX_XPATH_SINGLENODE_CONTEXT
#include "txIXPathContext.h"
class txSingleNodeContext : public txIEvalContext
{
public:
txSingleNodeContext(Node* aContextNode, txIMatchContext* aContext)
: mNode(aContextNode), mInner(aContext)
{
NS_ASSERTION(aContextNode, "context node must be given");
NS_ASSERTION(aContext, "txIMatchContext must be given");
}
~txSingleNodeContext()
{}
nsresult getVariable(PRInt32 aNamespace, txAtom* aLName,
ExprResult*& aResult)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->getVariable(aNamespace, aLName, aResult);
}
MBool isStripSpaceAllowed(Node* aNode)
{
NS_ASSERTION(mInner, "mInner is null!!!");
return mInner->isStripSpaceAllowed(aNode);
}
void receiveError(const String& aMsg, nsresult aRes)
{
NS_ASSERTION(mInner, "mInner is null!!!");
#ifdef DEBUG
String error("forwarded error: ");
error.append(aMsg);
mInner->receiveError(error, aRes);
#else
mInner->receiveError(aMsg, aRes);
#endif
}
Node* getContextNode()
{
return mNode;
}
PRUint32 size()
{
return 1;
}
PRUint32 position()
{
return 1;
}
private:
Node* mNode;
txIMatchContext* mInner;
};
#endif // __TX_XPATH_SINGLENODE_CONTEXT

Просмотреть файл

@ -31,6 +31,7 @@
#include "FunctionLib.h"
#include "XMLDOMUtils.h"
#include "txIXPathContext.h"
#include <math.h>
/**
@ -76,41 +77,42 @@ StringFunctionCall::StringFunctionCall(StringFunctions aType) : mType(aType)
* for evaluation
* @return the result of the evaluation
**/
ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
ExprResult* StringFunctionCall::evaluate(txIEvalContext* aContext)
{
ListIterator iter(&params);
switch (mType) {
case CONCAT:
{
if (!requireParams(2, aCs))
if (!requireParams(2, aContext))
return new StringResult("error");
String resultStr;
while (iter.hasNext()) {
evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr);
evaluateToString((Expr*)iter.next(), aContext, resultStr);
}
return new StringResult(resultStr);
}
case CONTAINS:
{
if (!requireParams(2, 2, aCs))
if (!requireParams(2, 2, aContext))
return new StringResult("error");
String arg1, arg2;
evaluateToString((Expr*)iter.next(), aContext, aCs, arg1);
evaluateToString((Expr*)iter.next(), aContext, aCs, arg2);
evaluateToString((Expr*)iter.next(), aContext, arg1);
evaluateToString((Expr*)iter.next(), aContext, arg2);
return new BooleanResult(arg1.indexOf(arg2) >= 0);
}
case NORMALIZE_SPACE:
{
if (!requireParams(0, 1, aCs))
if (!requireParams(0, 1, aContext))
return new StringResult("error");
String resultStr;
if (iter.hasNext())
evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr);
evaluateToString((Expr*)iter.next(), aContext, resultStr);
else
XMLDOMUtils::getNodeValue(aContext, resultStr);
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
MBool addSpace = MB_FALSE;
MBool first = MB_TRUE;
@ -136,35 +138,36 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case STARTS_WITH:
{
if (!requireParams(2, 2, aCs))
if (!requireParams(2, 2, aContext))
return new StringResult("error");
String arg1, arg2;
evaluateToString((Expr*)iter.next(), aContext, aCs, arg1);
evaluateToString((Expr*)iter.next(), aContext, aCs, arg2);
evaluateToString((Expr*)iter.next(), aContext, arg1);
evaluateToString((Expr*)iter.next(), aContext, arg2);
return new BooleanResult(arg1.indexOf(arg2) == 0);
}
case STRING_LENGTH:
{
if (!requireParams(0, 1, aCs))
if (!requireParams(0, 1, aContext))
return new StringResult("error");
String resultStr;
if (iter.hasNext())
evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr);
evaluateToString((Expr*)iter.next(), aContext, resultStr);
else
XMLDOMUtils::getNodeValue(aContext, resultStr);
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
return new NumberResult(resultStr.length());
}
case SUBSTRING:
{
if (!requireParams(2, 3, aCs))
if (!requireParams(2, 3, aContext))
return new StringResult("error");
String src;
double start, end;
evaluateToString((Expr*)iter.next(), aContext, aCs, src);
start = evaluateToNumber((Expr*)iter.next(), aContext, aCs);
evaluateToString((Expr*)iter.next(), aContext, src);
start = evaluateToNumber((Expr*)iter.next(), aContext);
// check for NaN or +/-Inf
if (Double::isNaN(start) ||
@ -175,8 +178,7 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
start = floor(start + 0.5) - 1;
if (iter.hasNext()) {
end = start + evaluateToNumber((Expr*)iter.next(),
aContext,
aCs);
aContext);
if (Double::isNaN(end) || end < 0)
return new StringResult();
@ -201,12 +203,12 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case SUBSTRING_AFTER:
{
if (!requireParams(2, 2, aCs))
if (!requireParams(2, 2, aContext))
return new StringResult("error");
String arg1, arg2;
evaluateToString((Expr*)iter.next(), aContext, aCs, arg1);
evaluateToString((Expr*)iter.next(), aContext, aCs, arg2);
evaluateToString((Expr*)iter.next(), aContext, arg1);
evaluateToString((Expr*)iter.next(), aContext, arg2);
PRInt32 idx = arg1.indexOf(arg2);
if (idx >= 0) {
PRInt32 len = arg2.length();
@ -217,12 +219,12 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case SUBSTRING_BEFORE:
{
if (!requireParams(2, 2, aCs))
if (!requireParams(2, 2, aContext))
return new StringResult("error");
String arg1, arg2;
evaluateToString((Expr*)iter.next(), aContext, aCs, arg1);
evaluateToString((Expr*)iter.next(), aContext, aCs, arg2);
evaluateToString((Expr*)iter.next(), aContext, arg1);
evaluateToString((Expr*)iter.next(), aContext, arg2);
PRInt32 idx = arg1.indexOf(arg2);
if (idx >= 0) {
arg2.clear();
@ -233,17 +235,17 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case TRANSLATE:
{
if (!requireParams(3, 3, aCs))
if (!requireParams(3, 3, aContext))
return new StringResult("error");
String src;
evaluateToString((Expr*)iter.next(), aContext, aCs, src);
evaluateToString((Expr*)iter.next(), aContext, src);
if (src.isEmpty())
return new StringResult();
String oldChars, newChars, dest;
evaluateToString((Expr*)iter.next(), aContext, aCs, oldChars);
evaluateToString((Expr*)iter.next(), aContext, aCs, newChars);
evaluateToString((Expr*)iter.next(), aContext, oldChars);
evaluateToString((Expr*)iter.next(), aContext, newChars);
PRInt32 i;
for (i = 0; i < src.length(); i++) {
PRInt32 idx = oldChars.indexOf(src.charAt(i));
@ -259,19 +261,20 @@ ExprResult* StringFunctionCall::evaluate(Node* aContext, ContextState* aCs)
}
case STRING:
{
if (!requireParams(0, 1, aCs))
if (!requireParams(0, 1, aContext))
return new StringResult("error");
String resultStr;
if (iter.hasNext())
evaluateToString((Expr*)iter.next(), aContext, aCs, resultStr);
evaluateToString((Expr*)iter.next(), aContext, resultStr);
else
XMLDOMUtils::getNodeValue(aContext, resultStr);
XMLDOMUtils::getNodeValue(aContext->getContextNode(),
resultStr);
return new StringResult(resultStr);
}
}
String err("Internal error");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_UNEXPECTED);
return new StringResult("error");
}

Просмотреть файл

@ -42,9 +42,9 @@ UnaryExpr::~UnaryExpr()
* for evaluation.
* @return the result of the evaluation.
*/
ExprResult* UnaryExpr::evaluate(Node* context, ContextState* cs)
ExprResult* UnaryExpr::evaluate(txIEvalContext* aContext)
{
ExprResult* exprRes = expr->evaluate(context, cs);
ExprResult* exprRes = expr->evaluate(aContext);
double value = exprRes->numberValue();
delete exprRes;
#ifdef HPUX

Просмотреть файл

@ -69,21 +69,22 @@ void UnionExpr::addExpr(Expr* expr) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs)
ExprResult* UnionExpr::evaluate(txIEvalContext* aContext)
{
NodeSet* nodes = new NodeSet();
if (!context || expressions.getLength() == 0 || !nodes)
if (!aContext || (expressions.getLength() == 0) || !nodes)
return nodes;
txListIterator iter(&expressions);
while (iter.hasNext()) {
Expr* expr = (Expr*)iter.next();
ExprResult* exprResult = expr->evaluate(context, cs);
ExprResult* exprResult = expr->evaluate(aContext);
if (!exprResult ||
exprResult->getResultType() != ExprResult::NODESET) {
delete exprResult;
delete nodes;
return new StringResult("error");
}
nodes->add((NodeSet*)exprResult);
@ -93,45 +94,6 @@ ExprResult* UnionExpr::evaluate(Node* context, ContextState* cs)
return nodes;
} //-- evaluate
/**
* Returns the default priority of this Pattern based on the given Node,
* context Node, and ContextState.
**/
double UnionExpr::getDefaultPriority(Node* node, Node* context,
ContextState* cs)
{
//-- find highest priority
double priority = Double::NEGATIVE_INFINITY;
ListIterator iter(&expressions);
while (iter.hasNext()) {
Expr* expr = (Expr*)iter.next();
double tmpPriority = expr->getDefaultPriority(node, context, cs);
if (tmpPriority > priority && expr->matches(node, context, cs))
priority = tmpPriority;
}
return priority;
} //-- getDefaultPriority
/**
* Determines whether this UnionExpr matches the given node within
* the given context
**/
MBool UnionExpr::matches(Node* node, Node* context, ContextState* cs) {
ListIterator* iter = expressions.iterator();
while (iter->hasNext()) {
Expr* expr = (Expr*)iter->next();
if (expr->matches(node, context, cs)) {
delete iter;
return MB_TRUE;
}
}
delete iter;
return MB_FALSE;
} //-- matches
/**
* Returns the String representation of this Expr.
* @param dest the String to use when creating the String

Просмотреть файл

@ -24,6 +24,8 @@
*/
#include "Expr.h"
#include "txAtoms.h"
#include "txIXPathContext.h"
//-------------------/
//- VariableRefExpr -/
@ -32,9 +34,25 @@
/**
* Creates a VariableRefExpr with the given variable name
**/
VariableRefExpr::VariableRefExpr(const String& name) {
this->name = name;
} //-- VariableRefExpr
VariableRefExpr::VariableRefExpr(txAtom* aPrefix, txAtom* aLocalName,
PRInt32 aNSID)
: mPrefix(aPrefix), mLocalName(aLocalName), mNamespace(aNSID)
{
NS_ASSERTION(mLocalName, "VariableRefExpr without local name?");
if (mPrefix == txXMLAtoms::_empty)
mPrefix = 0;
TX_IF_ADDREF_ATOM(mPrefix);
TX_IF_ADDREF_ATOM(mLocalName);
}
/*
* Release the local name atom
*/
VariableRefExpr::~VariableRefExpr()
{
TX_IF_RELEASE_ATOM(mPrefix);
TX_IF_RELEASE_ATOM(mLocalName);
}
/**
* Evaluates this Expr based on the given context node and processor state
@ -43,9 +61,14 @@ VariableRefExpr::VariableRefExpr(const String& name) {
* for evaluation
* @return the result of the evaluation
**/
ExprResult* VariableRefExpr::evaluate(Node* context, ContextState* cs) {
ExprResult* exprResult = cs->getVariable(name);
ExprResult* VariableRefExpr::evaluate(txIEvalContext* aContext)
{
ExprResult* exprResult = 0;
nsresult rv = aContext->getVariable(mNamespace, mLocalName, exprResult);
if (NS_FAILED(rv)) {
// XXX report error, undefined variable
return 0;
}
//-- make copy to prevent deletetion
//-- I know, I should add a #copy method to ExprResult, I will
ExprResult* copyOfResult = 0;
@ -88,7 +111,16 @@ ExprResult* VariableRefExpr::evaluate(Node* context, ContextState* cs) {
* other #toString() methods for Expressions.
* @return the String representation of this Expr.
**/
void VariableRefExpr::toString(String& str) {
str.append('$');
str.append(name);
void VariableRefExpr::toString(String& aDest)
{
aDest.append('$');
if (mPrefix) {
String prefix;
TX_GET_ATOM_STRING(mPrefix, prefix);
aDest.append(prefix);
aDest.append(':');
}
String lname;
TX_GET_ATOM_STRING(mLocalName, lname);
aDest.append(lname);
} //-- toString

Просмотреть файл

@ -54,6 +54,8 @@ CPPSRCS = Names.cpp \
txRtfHandler.cpp \
txTextHandler.cpp \
VariableBinding.cpp \
txXSLTPatterns.cpp \
txPatternParser.cpp \
XSLTProcessor.cpp
ifdef TX_EXE

Просмотреть файл

@ -8,22 +8,19 @@
/**
* Creates a new current function call
**/
CurrentFunctionCall::CurrentFunctionCall(ProcessorState* ps) :
FunctionCall(CURRENT_FN)
CurrentFunctionCall::CurrentFunctionCall(ProcessorState* aPs)
: FunctionCall(CURRENT_FN), mPs(aPs)
{
this->processorState = ps;
}
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param cs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* CurrentFunctionCall::evaluate(Node* context, ContextState* cs)
/*
* Evaluates this Expr
*
* @return NodeSet containing the context node used for the complete
* Expr or Pattern.
*/
ExprResult* CurrentFunctionCall::evaluate(txIEvalContext* aContext)
{
return new NodeSet(processorState->getCurrentNode());
return new NodeSet(mPs->getEvalContext()->getContextNode());
}

Просмотреть файл

@ -39,6 +39,7 @@
#include "XSLTFunctions.h"
#include "XMLDOMUtils.h"
#include "Names.h"
#include "txIXPathContext.h"
/*
* Creates a new DocumentFunctionCall.
@ -56,19 +57,17 @@ DocumentFunctionCall::DocumentFunctionCall(ProcessorState* aPs,
* NOTE: the implementation is incomplete since it does not make use of the
* second argument (base URI)
* @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
*/
ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs)
ExprResult* DocumentFunctionCall::evaluate(txIEvalContext* aContext)
{
NodeSet* nodeSet = new NodeSet();
// document(object, node-set?)
if (requireParams(1, 2, cs)) {
if (requireParams(1, 2, aContext)) {
ListIterator* iter = params.iterator();
Expr* param1 = (Expr*) iter->next();
ExprResult* exprResult1 = param1->evaluate(context, cs);
ExprResult* exprResult1 = param1->evaluate(aContext);
String baseURI;
MBool baseURISet = MB_FALSE;
@ -76,11 +75,12 @@ ExprResult* DocumentFunctionCall::evaluate(Node* context, ContextState* cs)
// We have 2 arguments, get baseURI from the first node
// in the resulting nodeset
Expr* param2 = (Expr*) iter->next();
ExprResult* exprResult2 = param2->evaluate(context, cs);
ExprResult* exprResult2 = param2->evaluate(aContext);
if (exprResult2->getResultType() != ExprResult::NODESET) {
String err("node-set expected as second argument to document(): ");
toString(err);
cs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
delete exprResult1;
delete exprResult2;
return nodeSet;
}

Просмотреть файл

@ -40,6 +40,7 @@
#include "XSLTFunctions.h"
#include "XMLUtils.h"
#include "Names.h"
#include "txIXPathContext.h"
/*
Implementation of XSLT 1.0 extension function: element-available
@ -47,9 +48,11 @@
/**
* Creates a new element-available function call
* aNode is the Element in the stylesheet containing the
* Expr and is used for namespaceID resolution
**/
ElementAvailableFunctionCall::ElementAvailableFunctionCall() :
FunctionCall(ELEMENT_AVAILABLE_FN)
ElementAvailableFunctionCall::ElementAvailableFunctionCall(Element* aNode) :
mStylesheetNode(aNode), FunctionCall(ELEMENT_AVAILABLE_FN)
{
}
@ -61,24 +64,28 @@ ElementAvailableFunctionCall::ElementAvailableFunctionCall() :
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* ElementAvailableFunctionCall::evaluate(Node* context, ContextState* cs) {
ExprResult* ElementAvailableFunctionCall::evaluate(txIEvalContext* aContext)
{
ExprResult* result = NULL;
if ( requireParams(1,1,cs) ) {
if (requireParams(1, 1, aContext)) {
ListIterator iter(&params);
Expr* param = (Expr*) iter.next();
ExprResult* exprResult = param->evaluate(context, cs);
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult &&
exprResult->getResultType() == ExprResult::STRING) {
String property;
exprResult->stringValue(property);
if (XMLUtils::isValidQName(property)) {
String prefix, propertyNsURI;
String prefix;
PRInt32 aNSID = kNameSpaceID_None;
XMLUtils::getPrefix(property, prefix);
if (!prefix.isEmpty()) {
cs->getNameSpaceURIFromPrefix(property, propertyNsURI);
txAtom* prefixAtom = TX_GET_ATOM(prefix);
aNSID = mStylesheetNode->lookupNamespaceID(prefixAtom);
TX_IF_RELEASE_ATOM(prefixAtom);
}
if (propertyNsURI.isEqual(XSLT_NS)) {
if (aNSID == kNameSpaceID_XSLT) {
String localName;
XMLUtils::getLocalPart(property, localName);
if ( localName.isEqual(APPLY_IMPORTS) ||
@ -119,7 +126,7 @@ ExprResult* ElementAvailableFunctionCall::evaluate(Node* context, ContextState*
}
else {
String err("Invalid argument passed to element-available(), expecting String");
delete result;
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
delete exprResult;

Просмотреть файл

@ -39,6 +39,7 @@
#include "XSLTFunctions.h"
#include "primitives.h"
#include "Names.h"
#include "txIXPathContext.h"
#include <math.h>
#ifndef TX_EXE
@ -70,10 +71,9 @@ txFormatNumberFunctionCall::txFormatNumberFunctionCall(ProcessorState* aPs) :
* for evaluation
* @return the result of the evaluation
*/
ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext,
ContextState* aCs)
ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext)
{
if (!requireParams(2, 3, aCs))
if (!requireParams(2, 3, aContext))
return new StringResult();
// Get number and format
@ -83,16 +83,16 @@ ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext,
String formatStr;
String formatName;
value = evaluateToNumber((Expr*)iter.next(), aContext, aCs);
evaluateToString((Expr*)iter.next(), aContext, aCs, formatStr);
value = evaluateToNumber((Expr*)iter.next(), aContext);
evaluateToString((Expr*)iter.next(), aContext, formatStr);
if (iter.hasNext())
evaluateToString((Expr*)iter.next(), aContext, aCs, formatName);
evaluateToString((Expr*)iter.next(), aContext, formatName);
txDecimalFormat* format = mPs->getDecimalFormat(formatName);
if (!format) {
String err("unknown decimal format for: ");
toString(err);
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
return new StringResult(err);
}
@ -161,7 +161,8 @@ ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext,
else {
String err(INVALID_PARAM_VALUE);
toString(err);
aCs->recieveError(err);
aContext->receiveError(err,
NS_ERROR_XPATH_EVAL_FAILED);
return new StringResult(err);
}
}
@ -171,7 +172,8 @@ ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext,
else {
String err(INVALID_PARAM_VALUE);
toString(err);
aCs->recieveError(err);
aContext->receiveError(err,
NS_ERROR_XPATH_EVAL_FAILED);
return new StringResult(err);
}
}
@ -256,7 +258,8 @@ ExprResult* txFormatNumberFunctionCall::evaluate(Node* aContext,
groupSize == 0) {
String err(INVALID_PARAM_VALUE);
toString(err);
aCs->recieveError(err);
aContext->receiveError(err,
NS_ERROR_XPATH_EVAL_FAILED);
return new StringResult(err);
}

Просмотреть файл

@ -41,6 +41,7 @@
#include "FunctionLib.h"
#include "XMLUtils.h"
#include "Names.h"
#include "txIXPathContext.h"
/*
Implementation of XSLT 1.0 extension function: function-available
@ -62,13 +63,14 @@ FunctionAvailableFunctionCall::FunctionAvailableFunctionCall() :
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* FunctionAvailableFunctionCall::evaluate(Node* context, ContextState* cs) {
ExprResult* FunctionAvailableFunctionCall::evaluate(txIEvalContext* aContext)
{
ExprResult* result = NULL;
if ( requireParams(1,1,cs) ) {
if (requireParams(1, 1, aContext)) {
ListIterator iter(&params);
Expr* param = (Expr*)iter.next();
ExprResult* exprResult = param->evaluate(context, cs);
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult &&
exprResult->getResultType() == ExprResult::STRING) {
String property;
@ -119,7 +121,7 @@ ExprResult* FunctionAvailableFunctionCall::evaluate(Node* context, ContextState*
}
else {
String err("Invalid argument passed to function-available, expecting String");
delete result;
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
delete exprResult;

Просмотреть файл

@ -24,6 +24,7 @@
#include "XSLTFunctions.h"
#include "Names.h"
#include "txIXPathContext.h"
#ifdef TX_EXE
#include <stdio.h>
#else
@ -55,10 +56,9 @@ GenerateIdFunctionCall::GenerateIdFunctionCall()
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* GenerateIdFunctionCall::evaluate(Node* aContext,
ContextState* aCs) {
if (!requireParams(0, 1, aCs))
ExprResult* GenerateIdFunctionCall::evaluate(txIEvalContext* aContext)
{
if (!requireParams(0, 1, aContext))
return new StringResult();
Node* node = 0;
@ -68,14 +68,14 @@ ExprResult* GenerateIdFunctionCall::evaluate(Node* aContext,
txListIterator iter(&params);
Expr* param = (Expr*)iter.next();
ExprResult* exprResult = param->evaluate(aContext, aCs);
ExprResult* exprResult = param->evaluate(aContext);
if (!exprResult)
return 0;
if (exprResult->getResultType() != ExprResult::NODESET) {
String err("Invalid argument passed to generate-id(), "
"expecting NodeSet");
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
delete exprResult;
return new StringResult(err);
}
@ -89,7 +89,7 @@ ExprResult* GenerateIdFunctionCall::evaluate(Node* aContext,
delete exprResult;
}
else {
node = aContext;
node = aContext->getContextNode();
}
// generate id for selected node

Просмотреть файл

@ -21,6 +21,7 @@
#include "XSLTFunctions.h"
#include "Names.h"
#include "XMLDOMUtils.h"
#include "txSingleNodeContext.h"
/*
* txKeyFunctionCall
@ -44,9 +45,9 @@ txKeyFunctionCall::txKeyFunctionCall(ProcessorState* aPs) :
* for evaluation
* @return the result of the evaluation
*/
ExprResult* txKeyFunctionCall::evaluate(Node* aContext, ContextState* aCs)
ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext)
{
if (!aContext || !requireParams(2, 2, aCs))
if (!aContext || !requireParams(2, 2, aContext))
return new StringResult("error");
NodeSet* res = new NodeSet;
@ -57,26 +58,27 @@ ExprResult* txKeyFunctionCall::evaluate(Node* aContext, ContextState* aCs)
ListIterator iter(&params);
String keyName;
evaluateToString((Expr*)iter.next(), aContext, aCs, keyName);
evaluateToString((Expr*)iter.next(), aContext, keyName);
Expr* param = (Expr*) iter.next();
txXSLKey* key = mProcessorState->getKey(keyName);
if (!key) {
String err("No key with that name in: ");
toString(err);
aCs->recieveError(err);
aContext->receiveError(err, NS_ERROR_INVALID_ARG);
return res;
}
ExprResult* exprResult = param->evaluate(aContext, aCs);
ExprResult* exprResult = param->evaluate(aContext);
if (!exprResult)
return res;
Document* contextDoc;
if (aContext->getNodeType() == Node::DOCUMENT_NODE)
contextDoc = (Document*)aContext;
Node* contextNode = aContext->getContextNode();
if (contextNode->getNodeType() == Node::DOCUMENT_NODE)
contextDoc = (Document*)contextNode;
else
contextDoc = aContext->getOwnerDocument();
contextDoc = contextNode->getOwnerDocument();
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* nodeSet = (NodeSet*) exprResult;
@ -155,7 +157,7 @@ const NodeSet* txXSLKey::getNodes(String& aKeyValue, Document* aDoc)
* @param aUse use-expression
* @return MB_FALSE if an error occured, MB_TRUE otherwise
*/
MBool txXSLKey::addKey(Pattern* aMatch, Expr* aUse)
MBool txXSLKey::addKey(txPattern* aMatch, Expr* aUse)
{
if (!aMatch || !aUse)
return MB_FALSE;
@ -226,13 +228,12 @@ void txXSLKey::testNode(Node* aNode, NamedMap* aMap)
while (iter.hasNext())
{
Key* key=(Key*)iter.next();
if (key->matchPattern->matches(aNode, 0, mProcessorState)) {
NodeSet contextNodeSet(aNode);
mProcessorState->getNodeSetStack()->push(&contextNodeSet);
mProcessorState->pushCurrentNode(aNode);
ExprResult* exprResult = key->useExpr->evaluate(aNode, mProcessorState);
mProcessorState->popCurrentNode();
mProcessorState->getNodeSetStack()->pop();
if (key->matchPattern->matches(aNode, mProcessorState)) {
txSingleNodeContext evalContext(aNode, mProcessorState);
txIEvalContext* prevCon =
mProcessorState->setEvalContext(&evalContext);
ExprResult* exprResult = key->useExpr->evaluate(&evalContext);
mProcessorState->setEvalContext(prevCon);
if (exprResult->getResultType() == ExprResult::NODESET) {
NodeSet* res = (NodeSet*)exprResult;
for (int i=0; i<res->size(); i++) {

Просмотреть файл

@ -43,6 +43,7 @@
#include "ProcessorState.h"
#include "txXPathResultComparator.h"
#include "txAtoms.h"
#include "txForwardContext.h"
/*
* Sorts Nodes as specified by the W3C XSLT 1.0 Recommendation
@ -84,9 +85,8 @@ MBool txNodeSorter::addSortElement(Element* aSortElement,
key->mExpr = mPs->getExpr(aSortElement, ProcessorState::SelectAttr);
else {
if (!mDefaultExpr) {
String expr(".");
ExprParser parser;
mDefaultExpr = parser.createExpr(expr);
txNodeTest* test = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
mDefaultExpr = new LocationStep(test, LocationStep::SELF_AXIS);
}
key->mExpr = mDefaultExpr;
}
@ -188,7 +188,7 @@ MBool txNodeSorter::sortNodeSet(NodeSet* aNodes)
}
iter.reset();
SortableNode* compNode = (SortableNode*)iter.next();
while (compNode && (compareNodes(currNode, compNode) > 0)) {
while (compNode && (compareNodes(currNode, compNode, aNodes) > 0)) {
compNode = (SortableNode*)iter.next();
}
// ... and insert in sorted list
@ -211,7 +211,8 @@ MBool txNodeSorter::sortNodeSet(NodeSet* aNodes)
}
int txNodeSorter::compareNodes(SortableNode* aSNode1,
SortableNode* aSNode2)
SortableNode* aSNode2,
NodeSet* aNodes)
{
txListIterator iter(&mSortKeys);
int i;
@ -221,9 +222,10 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1,
SortKey* key = (SortKey*)iter.next();
// Lazy create sort values
if (!aSNode1->mSortValues[i]) {
mPs->pushCurrentNode(aSNode1->mNode);
ExprResult* res = key->mExpr->evaluate(aSNode1->mNode, mPs);
mPs->popCurrentNode();
txForwardContext evalContext(mPs, aSNode1->mNode, aNodes);
txIEvalContext* priorEC = mPs->setEvalContext(&evalContext);
ExprResult* res = key->mExpr->evaluate(&evalContext);
mPs->setEvalContext(priorEC);
if (!res) {
// XXX ErrorReport
return -1;
@ -236,9 +238,10 @@ int txNodeSorter::compareNodes(SortableNode* aSNode1,
delete res;
}
if (!aSNode2->mSortValues[i]) {
mPs->pushCurrentNode(aSNode2->mNode);
ExprResult* res = key->mExpr->evaluate(aSNode2->mNode, mPs);
mPs->popCurrentNode();
txForwardContext evalContext(mPs, aSNode2->mNode, aNodes);
txIEvalContext* priorEC = mPs->setEvalContext(&evalContext);
ExprResult* res = key->mExpr->evaluate(&evalContext);
mPs->setEvalContext(priorEC);
if (!res) {
// XXX ErrorReport
return -1;
@ -272,7 +275,7 @@ MBool txNodeSorter::getAttrAsAVT(Element* aSortElement,
if (!aSortElement->getAttr(aAttrName, kNameSpaceID_None, attValue))
return MB_FALSE;
mPs->processAttrValueTemplate(attValue, aContext, aResult);
mPs->processAttrValueTemplate(attValue, aSortElement, aResult);
return MB_TRUE;
}

Просмотреть файл

@ -83,7 +83,8 @@ private:
};
int compareNodes(SortableNode* sNode1,
SortableNode* sNode2);
SortableNode* sNode2,
NodeSet* aNodes);
MBool getAttrAsAVT(Element* aSortElement,
txAtom* aAttrName,

Просмотреть файл

@ -0,0 +1,339 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txXSLTPatterns.h"
#include "txPatternParser.h"
#include "Names.h"
#include "txAtoms.h"
txPattern* txPatternParser::createPattern(const String& aPattern,
txIParseContext* aContext,
ProcessorState* aPs)
{
txPattern* pattern = 0;
ExprLexer lexer(aPattern);
nsresult rv = createUnionPattern(lexer, aContext, aPs, pattern);
if (NS_FAILED(rv)) {
// XXX error report parsing error
return 0;
}
return pattern;
}
nsresult txPatternParser::createUnionPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern)
{
nsresult rv = NS_OK;
txPattern* locPath = 0;
rv = createLocPathPattern(aLexer, aContext, aPs, locPath);
if (NS_FAILED(rv))
return rv;
short type = aLexer.peek()->type;
if (type == Token::END) {
aPattern = locPath;
return NS_OK;
}
if (type != Token::UNION_OP) {
delete locPath;
return NS_ERROR_XPATH_PARSE_FAILED;
}
txUnionPattern* unionPattern = new txUnionPattern();
if (!unionPattern) {
delete locPath;
return NS_ERROR_OUT_OF_MEMORY;
}
rv = unionPattern->addPattern(locPath);
#if 0 // XXX addPattern can't fail yet, it doesn't check for mem
if (NS_FAILED(rv)) {
delete unionPattern;
delete locPath;
return rv;
}
#endif
aLexer.nextToken();
do {
rv = createLocPathPattern(aLexer, aContext, aPs, locPath);
if (NS_FAILED(rv)) {
delete unionPattern;
return rv;
}
rv = unionPattern->addPattern(locPath);
#if 0 // XXX addPattern can't fail yet, it doesn't check for mem
if (NS_FAILED(rv)) {
delete unionPattern;
delete locPath;
return rv;
}
#endif
type = aLexer.nextToken()->type;
} while (type == Token::UNION_OP);
if (type != Token::END) {
delete unionPattern;
return NS_ERROR_XPATH_PARSE_FAILED;
}
aPattern = unionPattern;
return NS_OK;
}
nsresult txPatternParser::createLocPathPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern)
{
nsresult rv = NS_OK;
MBool isChild = MB_TRUE;
MBool isAbsolute = MB_FALSE;
txPattern* stepPattern = 0;
txLocPathPattern* pathPattern = 0;
short type = aLexer.peek()->type;
switch (type) {
case Token::ANCESTOR_OP:
isChild = MB_FALSE;
isAbsolute = MB_TRUE;
aLexer.nextToken();
break;
case Token::PARENT_OP:
aLexer.nextToken();
isAbsolute = MB_TRUE;
if (aLexer.peek()->type == Token::END ||
aLexer.peek()->type == Token::UNION_OP) {
aPattern = new txRootPattern(MB_TRUE);
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
break;
case Token::FUNCTION_NAME:
// id(Literal) or key(Literal, Literal)
{
String& name = aLexer.nextToken()->value;
txAtom* nameAtom = TX_GET_ATOM(name);
if (nameAtom == txXPathAtoms::id) {
rv = createIdPattern(aLexer, stepPattern);
}
else if (nameAtom == txXSLTAtoms::key) {
rv = createKeyPattern(aLexer, aContext, aPs, stepPattern);
}
TX_IF_RELEASE_ATOM(nameAtom);
if (NS_FAILED(rv))
return rv;
}
break;
default:
break;
}
if (!stepPattern) {
rv = createStepPattern(aLexer, aContext, stepPattern);
if (NS_FAILED(rv))
return rv;
}
type = aLexer.peek()->type;
if (!isAbsolute && type != Token::PARENT_OP
&& type != Token::ANCESTOR_OP) {
aPattern = stepPattern;
return NS_OK;
}
pathPattern = new txLocPathPattern();
if (!pathPattern) {
delete stepPattern;
return NS_ERROR_OUT_OF_MEMORY;
}
if (isAbsolute) {
txRootPattern* root = new txRootPattern(MB_FALSE);
if (!root) {
delete stepPattern;
delete pathPattern;
return NS_ERROR_OUT_OF_MEMORY;
}
rv = pathPattern->addStep(root, isChild);
if (NS_FAILED(rv)) {
delete stepPattern;
delete pathPattern;
delete root;
return NS_ERROR_OUT_OF_MEMORY;
}
}
rv = pathPattern->addStep(stepPattern, isChild);
if (NS_FAILED(rv)) {
delete stepPattern;
delete pathPattern;
return NS_ERROR_OUT_OF_MEMORY;
}
stepPattern = 0; // stepPattern is part of pathPattern now
while (type == Token::PARENT_OP || type == Token::ANCESTOR_OP) {
isChild = type == Token::PARENT_OP;
aLexer.nextToken();
rv = createStepPattern(aLexer, aContext, stepPattern);
if (NS_FAILED(rv)) {
delete pathPattern;
return rv;
}
rv = pathPattern->addStep(stepPattern, isChild);
if (NS_FAILED(rv)) {
delete stepPattern;
delete pathPattern;
return NS_ERROR_OUT_OF_MEMORY;
}
stepPattern = 0; // stepPattern is part of pathPattern now
type = aLexer.peek()->type;
}
aPattern = pathPattern;
return rv;
}
nsresult txPatternParser::createIdPattern(ExprLexer& aLexer,
txPattern*& aPattern)
{
nsresult rv = NS_OK;
// check for '(' Literal ')'
if (aLexer.nextToken()->type != Token::L_PAREN &&
aLexer.peek()->type != Token::LITERAL)
return NS_ERROR_XPATH_PARSE_FAILED;
const String& value = aLexer.nextToken()->value;
if (aLexer.nextToken()->type != Token::R_PAREN)
return NS_ERROR_XPATH_PARSE_FAILED;
aPattern = new txIdPattern(value);
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern)
{
nsresult rv = NS_OK;
// check for '(' Literal, Literal ')'
if (aLexer.nextToken()->type != Token::L_PAREN &&
aLexer.peek()->type != Token::LITERAL)
return NS_ERROR_XPATH_PARSE_FAILED;
const String& key = aLexer.nextToken()->value;
if (aLexer.nextToken()->type != Token::COMMA &&
aLexer.peek()->type != Token::LITERAL)
return NS_ERROR_XPATH_PARSE_FAILED;
const String& value = aLexer.nextToken()->value;
if (aLexer.nextToken()->type != Token::R_PAREN)
return NS_ERROR_XPATH_PARSE_FAILED;
aPattern = new txKeyPattern(aPs, key, value);
return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
nsresult txPatternParser::createStepPattern(ExprLexer& aLexer,
txIParseContext* aContext,
txPattern*& aPattern)
{
nsresult rv = NS_OK;
MBool isAttr = MB_FALSE;
Token* tok = aLexer.peek();
if (tok->type == Token::AXIS_IDENTIFIER) {
if (ATTRIBUTE_AXIS.isEqual(tok->value)) {
isAttr = MB_TRUE;
}
else if (!CHILD_AXIS.isEqual(tok->value)) {
// all done already for CHILD_AXIS, for all others
// XXX report unexpected axis error
return NS_ERROR_XPATH_PARSE_FAILED;
}
aLexer.nextToken();
}
else if (tok->type == Token::AT_SIGN) {
aLexer.nextToken();
isAttr = MB_TRUE;
}
tok = aLexer.nextToken();
txNodeTest* nodeTest = 0;
if (tok->type == Token::CNAME) {
// resolve QName
txAtom *prefix, *lName;
PRInt32 nspace;
rv = resolveQName(tok->value, prefix, aContext, lName, nspace);
if (NS_FAILED(rv)) {
// XXX error report namespace resolve failed
return rv;
}
if (isAttr) {
nodeTest = new txNameTest(prefix, lName, nspace,
Node::ATTRIBUTE_NODE);
}
else {
nodeTest = new txNameTest(prefix, lName, nspace,
Node::ELEMENT_NODE);
}
TX_IF_RELEASE_ATOM(prefix);
TX_IF_RELEASE_ATOM(lName);
if (!nodeTest) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
else {
aLexer.pushBack();
nodeTest = createNodeTypeTest(aLexer);
if (!nodeTest) {
// XXX error report NodeTest expected
return NS_ERROR_XPATH_PARSE_FAILED;
}
}
txStepPattern* step = new txStepPattern(nodeTest, isAttr);
if (!step) {
delete nodeTest;
return NS_ERROR_OUT_OF_MEMORY;
}
nodeTest = 0;
if (!parsePredicates(step, aLexer, aContext)) {
delete step;
return NS_ERROR_XPATH_PARSE_FAILED;
}
aPattern = step;
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef TX_PATTERNPARSER_H
#define TX_PATTERNPARSER_H
#include "txXSLTPatterns.h"
#include "ExprParser.h"
class txPatternParser : public ExprParser
{
public:
static txPattern* createPattern(const String& aPattern,
txIParseContext* aContext,
ProcessorState* aPs);
protected:
static nsresult createUnionPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern);
static nsresult createLocPathPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern);
static nsresult createIdPattern(ExprLexer& aLexer,
txPattern*& aPattern);
static nsresult createKeyPattern(ExprLexer& aLexer,
txIParseContext* aContext,
ProcessorState* aPs,
txPattern*& aPattern);
static nsresult createStepPattern(ExprLexer& aLexer,
txIParseContext* aContext,
txPattern*& aPattern);
};
#endif // TX_PATTERNPARSER_H

Просмотреть файл

@ -1,6 +1,7 @@
#include "XSLTFunctions.h"
#include "XMLUtils.h"
#include "Names.h"
#include "txIXPathContext.h"
const String XSL_VERSION_PROPERTY = "version";
const String XSL_VENDOR_PROPERTY = "vendor";
@ -12,9 +13,11 @@ const String XSL_VENDOR_URL_PROPERTY = "vendor-url";
/**
* Creates a new system-property function call
* aNode is the Element in the stylesheet containing the
* Expr and is used for namespaceID resolution
**/
SystemPropertyFunctionCall::SystemPropertyFunctionCall() :
FunctionCall(SYSTEM_PROPERTY_FN)
SystemPropertyFunctionCall::SystemPropertyFunctionCall(Element* aNode) :
mStylesheetNode(aNode), FunctionCall(SYSTEM_PROPERTY_FN)
{
}
@ -26,22 +29,29 @@ SystemPropertyFunctionCall::SystemPropertyFunctionCall() :
* @return the result of the evaluation
* @see FunctionCall.h
**/
ExprResult* SystemPropertyFunctionCall::evaluate(Node* context, ContextState* cs) {
ExprResult* SystemPropertyFunctionCall::evaluate(txIEvalContext* aContext)
{
ExprResult* result = NULL;
if ( requireParams(1,1,cs) ) {
if (requireParams(1, 1, aContext)) {
ListIterator* iter = params.iterator();
Expr* param = (Expr*) iter->next();
delete iter;
ExprResult* exprResult = param->evaluate(context, cs);
ExprResult* exprResult = param->evaluate(aContext);
if (exprResult->getResultType() == ExprResult::STRING) {
String property;
exprResult->stringValue(property);
if (XMLUtils::isValidQName(property)) {
String propertyNsURI, prefix;
String prefix;
PRInt32 namespaceID = kNameSpaceID_None;
XMLUtils::getPrefix(property, prefix);
cs->getNameSpaceURIFromPrefix(prefix, propertyNsURI);
if (propertyNsURI.isEqual(XSLT_NS)) {
if (!prefix.isEmpty()) {
txAtom* prefixAtom = TX_GET_ATOM(prefix);
namespaceID =
mStylesheetNode->lookupNamespaceID(prefixAtom);
TX_IF_RELEASE_ATOM(prefixAtom);
}
if (namespaceID == kNameSpaceID_XSLT) {
String localName;
XMLUtils::getLocalPart(property, localName);
if (localName.isEqual(XSL_VERSION_PROPERTY))
@ -55,6 +65,7 @@ ExprResult* SystemPropertyFunctionCall::evaluate(Node* context, ContextState* cs
}
else {
String err("Invalid argument passed to system-property(), expecting String");
aContext->receiveError(err, NS_ERROR_XPATH_INVALID_ARG);
result = new StringResult(err);
}
}

Просмотреть файл

@ -51,14 +51,9 @@ public:
DocumentFunctionCall(ProcessorState* aPs, Node* aDefResolveNode);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param cs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see FunctionCall.h
* Virtual methods from FunctionCall
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
ProcessorState* mProcessorState;
@ -80,12 +75,10 @@ public:
/*
* Evaluates a key() xslt-functioncall. First argument is name of key
* to use, second argument is value to look up.
* @param aContext the context node for evaluation of this Expr
* @param aCs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
*
* Virtual function from FunctionCall
*/
virtual ExprResult* evaluate(Node* aContext, ContextState* aCs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
ProcessorState* mProcessorState;
@ -120,7 +113,7 @@ public:
* @param aUse use-expression
* @return MB_FALSE if an error occured, MB_TRUE otherwise
*/
MBool addKey(Pattern* aMatch, Expr* aUse);
MBool addKey(txPattern* aMatch, Expr* aUse);
private:
/*
@ -150,7 +143,7 @@ private:
* represents one match/use pair
*/
struct Key {
Pattern* matchPattern;
txPattern* matchPattern;
Expr* useExpr;
};
@ -191,14 +184,9 @@ public:
txFormatNumberFunctionCall(ProcessorState* aPs);
/**
* Evaluates this Expr based on the given context node and processor state
* @param aContext the context node for evaluation of this Expr
* @param aCs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see FunctionCall.h
* Virtual function from FunctionCall
**/
virtual ExprResult* evaluate(Node* aContext, ContextState* aCs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
static const UNICODE_CHAR FORMAT_QUOTE;
@ -255,17 +243,12 @@ public:
CurrentFunctionCall(ProcessorState* ps);
/**
* Evaluates this Expr based on the given context node and processor state
* @param context the context node for evaluation of this Expr
* @param cs the ContextState containing the stack information needed
* for evaluation
* @return the result of the evaluation
* @see FunctionCall.h
* Virtual function from FunctionCall
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
ProcessorState* processorState;
ProcessorState* mPs;
};
/**
@ -288,7 +271,7 @@ public:
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
};
@ -313,7 +296,7 @@ public:
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
static const char printfFmt[];
@ -328,8 +311,10 @@ public:
/**
* Creates a new system-property() function call
* aNode is the Element in the stylesheet containing the
* Expr and is used for namespaceID resolution
**/
SystemPropertyFunctionCall();
SystemPropertyFunctionCall(Element* aNode);
/**
* Evaluates this Expr based on the given context node and processor state
@ -339,9 +324,13 @@ public:
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
/*
* resolve namespaceIDs with this node
*/
Element* mStylesheetNode;
};
/**
@ -353,8 +342,10 @@ public:
/**
* Creates a new element-available() function call
* aNode is the Element in the stylesheet containing the
* Expr and is used for namespaceID resolution
**/
ElementAvailableFunctionCall();
ElementAvailableFunctionCall(Element* aNode);
/**
* Evaluates this Expr based on the given context node and processor state
@ -364,9 +355,13 @@ public:
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
/*
* resolve namespaceIDs with this node
*/
Element* mStylesheetNode;
};
/**
@ -389,7 +384,7 @@ public:
* @return the result of the evaluation
* @see FunctionCall.h
**/
virtual ExprResult* evaluate(Node* context, ContextState* cs);
ExprResult* evaluate(txIEvalContext* aContext);
private:
};

Просмотреть файл

@ -0,0 +1,614 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "txXSLTPatterns.h"
#include "txNodeSetContext.h"
#include "txForwardContext.h"
#include "XSLTFunctions.h"
#ifndef TX_EXE
#include "nsReadableUtils.h"
#include "nsIContent.h"
#include "nsINodeInfo.h"
#endif
/*
* txPattern
*
* Base class of all patterns
* Implements only a default getSimplePatterns
*/
nsresult txPattern::getSimplePatterns(txList& aList)
{
aList.add(this);
return NS_OK;
}
txPattern::~txPattern()
{
}
/*
* txUnionPattern
*
* This pattern is returned by the parser for "foo | bar" constructs.
* |xsl:template|s should use the simple patterns
*/
/*
* Destructor, deletes all LocationPathPatterns
*/
txUnionPattern::~txUnionPattern()
{
ListIterator iter(&mLocPathPatterns);
while (iter.hasNext()) {
delete (txPattern*)iter.next();
}
}
nsresult txUnionPattern::addPattern(txPattern* aPattern)
{
if (!aPattern)
return NS_ERROR_NULL_POINTER;
mLocPathPatterns.add(aPattern);
return NS_OK;
}
/*
* Returns the default priority of this Pattern.
* UnionPatterns don't like this.
* This should be called on the simple patterns.
*/
double txUnionPattern::getDefaultPriority()
{
NS_ASSERTION(0, "Don't call getDefaultPriority on txUnionPattern");
return Double::NaN;
}
/*
* Determines whether this Pattern matches the given node within
* the given context
* This should be called on the simple patterns for xsl:template,
* but is fine for xsl:key and xsl:number
*/
MBool txUnionPattern::matches(Node* aNode, txIMatchContext* aContext)
{
ListIterator iter(&mLocPathPatterns);
while (iter.hasNext()) {
txPattern* p = (txPattern*)iter.next();
if (p->matches(aNode, aContext)) {
return MB_TRUE;
}
}
return MB_FALSE;
}
nsresult txUnionPattern::getSimplePatterns(txList& aList)
{
ListIterator iter(&mLocPathPatterns);
while (iter.hasNext()) {
aList.add(iter.next());
iter.remove();
}
return NS_OK;
}
/*
* The String representation will be appended to any data in the
* destination String, to allow cascading calls to other
* toString() methods for mLocPathPatterns.
*/
void txUnionPattern::toString(String& aDest)
{
#ifdef DEBUG
aDest.append("txUnionPattern{");
#endif
txListIterator iter(&mLocPathPatterns);
if (iter.hasNext())
((txPattern*)iter.next())->toString(aDest);
while (iter.hasNext()) {
aDest.append(" | ");
((txPattern*)iter.next())->toString(aDest);
}
#ifdef DEBUG
aDest.append("}");
#endif
} // toString
/*
* LocationPathPattern
*
* a list of step patterns, can start with id or key
* (dealt with by the parser)
*/
/*
* Destructor, deletes all PathPatterns
*/
txLocPathPattern::~txLocPathPattern()
{
ListIterator iter(&mSteps);
while (iter.hasNext()) {
delete (Step*)iter.next();
}
}
nsresult txLocPathPattern::addStep(txPattern* aPattern, MBool isChild)
{
if (!aPattern)
return NS_ERROR_NULL_POINTER;
Step* step = new Step(aPattern, isChild);
if (!step)
return NS_ERROR_OUT_OF_MEMORY;
mSteps.add(step);
return NS_OK;
}
MBool txLocPathPattern::matches(Node* aNode, txIMatchContext* aContext)
{
NS_ASSERTION(aNode && mSteps.getLength(), "Internal error");
/*
* The idea is to split up a path into blocks separated by descendant
* operators. For example "foo/bar//baz/bop//ying/yang" is split up into
* three blocks. The "ying/yang" block is handled by the first while-loop
* and the "foo/bar" and "baz/bop" blocks are handled by the second
* while-loop.
* A block is considered matched when we find a list of ancestors that
* match the block. If there are more than one list of ancestors that
* match a block we only need to find the one furthermost down in the
* tree.
*/
ListIterator iter(&mSteps);
iter.resetToEnd();
Step* step;
step = (Step*)iter.previous();
if (!step->pattern->matches(aNode, aContext))
return MB_FALSE;
Node* node = aNode->getXPathParent();
while (step->isChild) {
step = (Step*)iter.previous();
if (!step)
return MB_TRUE; // all steps matched
if (!node || !step->pattern->matches(node, aContext))
return MB_FALSE; // no more ancestors or no match
node = node->getXPathParent();
}
// We have at least one // path separator
Node *blockStart = node;
txListIterator blockIter(iter);
while ((step = (Step*)iter.previous())) {
if (!node)
return MB_FALSE; // There are more steps in the current block
// than ancestors of the tested node
if (!step->pattern->matches(node, aContext)) {
// Didn't match. We restart at beginning of block using a new
// start node
iter = blockIter;
blockStart = blockStart->getXPathParent();
node = blockStart;
}
else {
node = node->getXPathParent();
if (!step->isChild) {
// We've matched an entire block. Set new start iter and start node
blockIter = iter;
blockStart = node;
}
}
}
return MB_TRUE;
} // txLocPathPattern::matches
double txLocPathPattern::getDefaultPriority()
{
if (mSteps.getLength() > 1) {
return 0.5;
}
return ((Step*)mSteps.get(0))->pattern->getDefaultPriority();
}
void txLocPathPattern::toString(String& aDest)
{
ListIterator iter(&mSteps);
#ifdef DEBUG
aDest.append("txLocPathPattern{");
#endif
Step* step;
step = (Step*)iter.next();
if (step) {
step->pattern->toString(aDest);
}
while ((step = (Step*)iter.next())) {
if (step->isChild)
aDest.append("/");
else
aDest.append("//");
step->pattern->toString(aDest);
}
#ifdef DEBUG
aDest.append("}");
#endif
} // txLocPathPattern::toString
/*
* txRootPattern
*
* a txPattern matching the document node, or '/'
*/
txRootPattern::~txRootPattern()
{
}
MBool txRootPattern::matches(Node* aNode, txIMatchContext* aContext)
{
return aNode && (aNode->getNodeType() == Node::DOCUMENT_NODE);
}
double txRootPattern::getDefaultPriority()
{
return 0.5;
}
void txRootPattern::toString(String& aDest)
{
#ifdef DEBUG
aDest.append("txRootPattern{");
#endif
if (mSerialize)
aDest.append("/");
#ifdef DEBUG
aDest.append("}");
#endif
}
/*
* txIdPattern
*
* txIdPattern matches if the given node has a ID attribute with one
* of the space delimited values.
* This looks like the id() function, but may only have LITERALs as
* argument.
*/
#define TX_IS_WHITE(c) (c == ' ' || c == '\r' || c == '\n'|| c == '\t')
txIdPattern::txIdPattern(const String aString)
{
#ifdef TX_EXE
mIds = aString;
#else
const nsString& ids = aString.getConstNSString();
nsAString::const_iterator pos, begin, end;
ids.BeginReading(begin);
ids.EndReading(end);
pos = begin;
while (pos != end) {
while (pos != end && TX_IS_WHITE(*pos))
++pos;
begin = pos;
if (!mIds.IsEmpty())
mIds += PRUnichar(' ');
while (pos != end && !TX_IS_WHITE(*pos))
++pos;
mIds += Substring(begin, pos);
}
#endif
}
txIdPattern::~txIdPattern()
{
}
MBool txIdPattern::matches(Node* aNode, txIMatchContext* aContext)
{
#ifdef TX_EXE
return MB_FALSE; // not implemented
#else
if (aNode->getNodeType() != Node::ELEMENT_NODE) {
return MB_FALSE;
}
// Get a ID attribute, if there is
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode->getNSObj());
NS_ASSERTION(content, "a Element without nsIContent");
if (!content) {
return MB_FALSE;
}
nsCOMPtr<nsINodeInfo> ni;
content->GetNodeInfo(*getter_AddRefs(ni));
if (!ni) {
return MB_FALSE;
}
nsCOMPtr<nsIAtom> idAttr;
ni->GetIDAttributeAtom(getter_AddRefs(idAttr));
if (!idAttr) {
return MB_FALSE; // no ID for this element defined, can't match
}
nsAutoString value;
nsresult rv = content->GetAttr(kNameSpaceID_None, idAttr, value);
if (rv != NS_CONTENT_ATTR_HAS_VALUE) {
return MB_FALSE; // no ID attribute given
}
nsAString::const_iterator pos, begin, end;
mIds.BeginReading(begin);
mIds.EndReading(end);
pos = begin;
const PRUnichar space = PRUnichar(' ');
PRBool found = FindCharInReadable(space, pos, end);
while (found) {
if (value.Equals(Substring(begin, pos))) {
return MB_TRUE;
}
++pos; // skip ' '
begin = pos;
found = FindCharInReadable(PRUnichar(' '), pos, end);
}
if (value.Equals(Substring(begin, pos))) {
return MB_TRUE;
}
return MB_FALSE;
#endif // TX_EXE
}
double txIdPattern::getDefaultPriority()
{
return 0.5;
}
void txIdPattern::toString(String& aDest)
{
#ifdef DEBUG
aDest.append("txIdPattern{");
#endif
aDest.append("id('");
#ifdef TX_EXE
aDest.append(mIds);
#else
aDest.append(mIds.get());
#endif
aDest.append("')");
#ifdef DEBUG
aDest.append("}");
#endif
}
/*
* txKeyPattern
*
* txKeyPattern matches if the given node is in the evalation of
* the key() function
* This resembles the key() function, but may only have LITERALs as
* argument.
*/
txKeyPattern::~txKeyPattern()
{
}
MBool txKeyPattern::matches(Node* aNode, txIMatchContext* aContext)
{
Document* contextDoc;
if (aNode->getNodeType() == Node::DOCUMENT_NODE)
contextDoc = (Document*)aNode;
else
contextDoc = aNode->getOwnerDocument();
txXSLKey* key = mProcessorState->getKey(mName);
const NodeSet* nodes = key->getNodes(mValue, contextDoc);
if (!nodes || nodes->isEmpty())
return MB_FALSE;
MBool isTrue = nodes->contains(aNode);
return isTrue;
}
double txKeyPattern::getDefaultPriority()
{
return 0.5;
}
void txKeyPattern::toString(String& aDest)
{
#ifdef DEBUG
aDest.append("txKeyPattern{");
#endif
aDest.append("key('");
aDest.append(mName);
aDest.append(", ");
aDest.append(mValue);
aDest.append("')");
#ifdef DEBUG
aDest.append("}");
#endif
}
/*
* txStepPattern
*
* a txPattern to hold the NodeTest and the Predicates of a StepPattern
*/
txStepPattern::~txStepPattern()
{
delete mNodeTest;
}
MBool txStepPattern::matches(Node* aNode, txIMatchContext* aContext)
{
NS_ASSERTION(mNodeTest && aNode, "Internal error");
if (!aNode)
return MB_FALSE;
if (!mNodeTest->matches(aNode, aContext))
return MB_FALSE;
if (!mIsAttr && !aNode->getParentNode())
return MB_FALSE;
if (isEmpty()) {
return MB_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 MB_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
NodeSet nodes;
Node* parent = aNode->getXPathParent();
if (mIsAttr) {
NamedNodeMap* atts = parent->getAttributes();
if (atts) {
PRUint32 i;
for (i = 0; i < atts->getLength(); i++) {
Node* attr = atts->item(i);
if (mNodeTest->matches(attr, aContext))
nodes.append(attr);
}
}
}
else {
Node* tmpNode = parent->getFirstChild();
while (tmpNode) {
if (mNodeTest->matches(tmpNode, aContext))
nodes.append(tmpNode);
tmpNode = tmpNode->getNextSibling();
}
}
txListIterator iter(&predicates);
Expr* predicate = (Expr*)iter.next();
NodeSet newNodes;
while (iter.hasNext()) {
newNodes.clear();
MBool contextIsInPredicate = MB_FALSE;
txNodeSetContext predContext(&nodes, aContext);
while (predContext.hasNext()) {
predContext.next();
ExprResult* exprResult = predicate->evaluate(&predContext);
if (!exprResult)
break;
switch(exprResult->getResultType()) {
case ExprResult::NUMBER :
// handle default, [position() == numberValue()]
if ((double)predContext.position() ==
exprResult->numberValue()) {
Node* tmp = predContext.getContextNode();
if (tmp == aNode)
contextIsInPredicate = MB_TRUE;
newNodes.append(tmp);
}
break;
default:
if (exprResult->booleanValue()) {
Node* tmp = predContext.getContextNode();
if (tmp == aNode)
contextIsInPredicate = MB_TRUE;
newNodes.append(tmp);
}
break;
}
delete exprResult;
}
// Move new NodeSet to the current one
nodes.clear();
nodes.append(&newNodes);
if (!contextIsInPredicate) {
return MB_FALSE;
}
predicate = (Expr*)iter.next();
}
txForwardContext evalContext(aContext, aNode, &nodes);
ExprResult* exprResult = predicate->evaluate(&evalContext);
if (!exprResult)
return MB_FALSE;
if (exprResult->getResultType() == ExprResult::NUMBER)
// handle default, [position() == numberValue()]
return ((double)evalContext.position() == exprResult->numberValue());
return exprResult->booleanValue();
} // matches
double txStepPattern::getDefaultPriority()
{
if (isEmpty())
return mNodeTest->getDefaultPriority();
return 0.5;
}
void txStepPattern::toString(String& aDest)
{
#ifdef DEBUG
aDest.append("txStepPattern{");
#endif
if (mIsAttr)
aDest.append("@");
if (mNodeTest)
mNodeTest->toString(aDest);
PredicateList::toString(aDest);
#ifdef DEBUG
aDest.append("}");
#endif
}

Просмотреть файл

@ -0,0 +1,210 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TransforMiiX XSLT Processor.
*
* The Initial Developer of the Original Code is
* Axel Hecht.
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef TX_XSLT_PATTERNS_H
#define TX_XSLT_PATTERNS_H
#include "Expr.h"
class ProcessorState;
class txPattern : public TxObject
{
public:
virtual ~txPattern();
/*
* Determines whether this Pattern matches the given node.
*/
virtual MBool matches(Node* aNode, txIMatchContext* aContext) = 0;
/*
* Returns the default priority of this Pattern.
*
* Simple Patterns return the values as specified in XPath 5.5.
* Returns -Inf for union patterns, as it shouldn't be called on them.
*/
virtual double getDefaultPriority() = 0;
/*
* Returns the String representation of this Pattern.
* @param dest the String to use when creating the String
* representation. The String representation will be appended to
* any data in the destination String, to allow cascading calls to
* other #toString() methods for Patterns.
* @return the String representation of this Pattern.
*/
virtual void toString(String& aDest) = 0;
/*
* Adds the simple Patterns to the List.
* For union patterns, add all sub patterns,
* all other (simple) patterns just add themselves.
* This cuts the ownership of the union pattern and it's
* simple patterns, leaving union patterns empty after a call
* to this function.
*/
virtual nsresult getSimplePatterns(txList &aList);
};
#define TX_DECL_PATTERN \
MBool matches(Node* aNode, txIMatchContext* aContext); \
double getDefaultPriority(); \
void toString(String& aDest)
#define TX_DECL_PATTERN2 \
TX_DECL_PATTERN; \
nsresult getSimplePatterns(txList &aList)
class txUnionPattern : public txPattern
{
public:
txUnionPattern()
{
}
~txUnionPattern();
nsresult addPattern(txPattern* aPattern);
TX_DECL_PATTERN2;
private:
txList mLocPathPatterns;
};
class txLocPathPattern : public txPattern
{
public:
txLocPathPattern()
{
}
~txLocPathPattern();
nsresult addStep(txPattern* aPattern, MBool isChild);
TX_DECL_PATTERN;
private:
class Step {
public:
Step(txPattern* aPattern, MBool aIsChild)
: pattern(aPattern), isChild(aIsChild)
{
}
~Step()
{
delete pattern;
}
txPattern* pattern;
MBool isChild;
};
txList mSteps;
};
class txRootPattern : public txPattern
{
public:
txRootPattern(MBool aSerialize) : mSerialize(aSerialize)
{
}
~txRootPattern();
TX_DECL_PATTERN;
private:
// Don't serialize txRootPattern if it's used in a txLocPathPattern
MBool mSerialize;
};
class txIdPattern : public txPattern
{
public:
txIdPattern(const String aString);
~txIdPattern();
TX_DECL_PATTERN;
private:
#ifdef TX_EXE
String mIds;
#else
nsAutoString mIds;
#endif
};
class txKeyPattern : public txPattern
{
public:
txKeyPattern(ProcessorState* aPs, const String& aName,
const String& aValue)
: mProcessorState(aPs), mName(aName), mValue(aValue)
{
}
~txKeyPattern();
TX_DECL_PATTERN;
private:
ProcessorState* mProcessorState;
String mName, mValue;
};
class txStepPattern : public PredicateList, public txPattern
{
public:
txStepPattern(txNodeTest* aNodeTest, MBool isAttr)
:mNodeTest(aNodeTest), mIsAttr(isAttr)
{
}
~txStepPattern();
TX_DECL_PATTERN;
private:
txNodeTest* mNodeTest;
MBool mIsAttr;
};
#endif // TX_XSLT_PATTERNS_H