diff --git a/mozilla/extensions/transformiix/build/Makefile.in b/mozilla/extensions/transformiix/build/Makefile.in index 36d930ea9c2..405b772ce96 100644 --- a/mozilla/extensions/transformiix/build/Makefile.in +++ b/mozilla/extensions/transformiix/build/Makefile.in @@ -88,19 +88,13 @@ LOBJS =../source/base/ArrayList.$(OBJ_SUFFIX) \ ../source/xml/dom/mozImpl/MozillaProcInstruction.$(OBJ_SUFFIX) \ ../source/xml/dom/mozImpl/MozillaText.$(OBJ_SUFFIX) \ ../source/xpath/AdditiveExpr.$(OBJ_SUFFIX) \ - ../source/xpath/AttributeExpr.$(OBJ_SUFFIX) \ ../source/xpath/AttributeValueTemplate.$(OBJ_SUFFIX) \ - ../source/xpath/BasicNodeExpr.$(OBJ_SUFFIX) \ ../source/xpath/BooleanExpr.$(OBJ_SUFFIX) \ ../source/xpath/BooleanFunctionCall.$(OBJ_SUFFIX) \ ../source/xpath/BooleanResult.$(OBJ_SUFFIX) \ - ../source/xpath/ElementExpr.$(OBJ_SUFFIX) \ - ../source/xpath/ErrorFunctionCall.$(OBJ_SUFFIX) \ - ../source/xpath/Expr.$(OBJ_SUFFIX) \ ../source/xpath/ExprLexer.$(OBJ_SUFFIX) \ ../source/xpath/ExprLexerChars.$(OBJ_SUFFIX) \ ../source/xpath/ExprParser.$(OBJ_SUFFIX) \ - ../source/xpath/ExtensionFunctionCall.$(OBJ_SUFFIX) \ ../source/xpath/FilterExpr.$(OBJ_SUFFIX) \ ../source/xpath/FunctionCall.$(OBJ_SUFFIX) \ ../source/xpath/LocationStep.$(OBJ_SUFFIX) \ @@ -122,7 +116,10 @@ LOBJS =../source/base/ArrayList.$(OBJ_SUFFIX) \ ../source/xpath/StringExpr.$(OBJ_SUFFIX) \ ../source/xpath/StringFunctionCall.$(OBJ_SUFFIX) \ ../source/xpath/StringResult.$(OBJ_SUFFIX) \ - ../source/xpath/TextExpr.$(OBJ_SUFFIX) \ + ../source/xpath/txNameTest.$(OBJ_SUFFIX) \ + ../source/xpath/txNodeTypeTest.$(OBJ_SUFFIX) \ + ../source/xpath/txForwardContext.$(OBJ_SUFFIX) \ + ../source/xpath/txNodeSetContext.$(OBJ_SUFFIX) \ ../source/xpath/UnionExpr.$(OBJ_SUFFIX) \ ../source/xpath/UnaryExpr.$(OBJ_SUFFIX) \ ../source/xpath/VariableRefExpr.$(OBJ_SUFFIX) \ @@ -140,6 +137,8 @@ LOBJS =../source/base/ArrayList.$(OBJ_SUFFIX) \ ../source/xslt/txRtfHandler.$(OBJ_SUFFIX) \ ../source/xslt/txTextHandler.$(OBJ_SUFFIX) \ ../source/xslt/VariableBinding.$(OBJ_SUFFIX) \ + ../source/xslt/txXSLTPatterns.$(OBJ_SUFFIX) \ + ../source/xslt/txPatternParser.$(OBJ_SUFFIX) \ ../source/xslt/XSLTProcessor.$(OBJ_SUFFIX) \ ../source/xslt/functions/CurrentFunctionCall.$(OBJ_SUFFIX) \ ../source/xslt/functions/DocumentFunctionCall.$(OBJ_SUFFIX) \ diff --git a/mozilla/extensions/transformiix/build/makefile.win b/mozilla/extensions/transformiix/build/makefile.win index 1ae96b03e8b..3c1772e6bd3 100644 --- a/mozilla/extensions/transformiix/build/makefile.win +++ b/mozilla/extensions/transformiix/build/makefile.win @@ -73,19 +73,13 @@ CPP_OBJS= \ ..\source\xml\dom\mozImpl\$(OBJDIR)\MozillaProcInstruction.obj \ ..\source\xml\dom\mozImpl\$(OBJDIR)\MozillaText.obj \ ..\source\xpath\$(OBJDIR)\AdditiveExpr.obj \ - ..\source\xpath\$(OBJDIR)\AttributeExpr.obj \ ..\source\xpath\$(OBJDIR)\AttributeValueTemplate.obj \ - ..\source\xpath\$(OBJDIR)\BasicNodeExpr.obj \ ..\source\xpath\$(OBJDIR)\BooleanExpr.obj \ ..\source\xpath\$(OBJDIR)\BooleanFunctionCall.obj \ ..\source\xpath\$(OBJDIR)\BooleanResult.obj \ - ..\source\xpath\$(OBJDIR)\ElementExpr.obj \ - ..\source\xpath\$(OBJDIR)\ErrorFunctionCall.obj \ - ..\source\xpath\$(OBJDIR)\Expr.obj \ ..\source\xpath\$(OBJDIR)\ExprLexer.obj \ ..\source\xpath\$(OBJDIR)\ExprLexerChars.obj \ ..\source\xpath\$(OBJDIR)\ExprParser.obj \ - ..\source\xpath\$(OBJDIR)\ExtensionFunctionCall.obj \ ..\source\xpath\$(OBJDIR)\FilterExpr.obj \ ..\source\xpath\$(OBJDIR)\FunctionCall.obj \ ..\source\xpath\$(OBJDIR)\LocationStep.obj \ @@ -107,7 +101,10 @@ CPP_OBJS= \ ..\source\xpath\$(OBJDIR)\StringExpr.obj \ ..\source\xpath\$(OBJDIR)\StringFunctionCall.obj \ ..\source\xpath\$(OBJDIR)\StringResult.obj \ - ..\source\xpath\$(OBJDIR)\TextExpr.obj \ + ..\source\xpath\$(OBJDIR)\txNameTest.obj \ + ..\source\xpath\$(OBJDIR)\txNodeTypeTest.obj \ + ..\source\xpath\$(OBJDIR)\txForwardContext.obj \ + ..\source\xpath\$(OBJDIR)\txNodeSetContext.obj \ ..\source\xpath\$(OBJDIR)\UnionExpr.obj \ ..\source\xpath\$(OBJDIR)\UnaryExpr.obj \ ..\source\xpath\$(OBJDIR)\VariableRefExpr.obj \ @@ -125,6 +122,8 @@ CPP_OBJS= \ ..\source\xslt\$(OBJDIR)\txRtfHandler.obj \ ..\source\xslt\$(OBJDIR)\txTextHandler.obj \ ..\source\xslt\$(OBJDIR)\VariableBinding.obj \ + ..\source\xslt\$(OBJDIR)\txXSLTPatterns.obj \ + ..\source\xslt\$(OBJDIR)\txPatternParser.obj \ ..\source\xslt\$(OBJDIR)\XSLTProcessor.obj \ ..\source\xslt\functions\$(OBJDIR)\CurrentFunctionCall.obj \ ..\source\xslt\functions\$(OBJDIR)\DocumentFunctionCall.obj \ diff --git a/mozilla/extensions/transformiix/macbuild/transformiix.xml b/mozilla/extensions/transformiix/macbuild/transformiix.xml index 18b77d421e1..926b76838ac 100644 --- a/mozilla/extensions/transformiix/macbuild/transformiix.xml +++ b/mozilla/extensions/transformiix/macbuild/transformiix.xml @@ -1009,6 +1009,34 @@ Library + + Name + txNameTest.cpp + MacOS + Text + + + + Name + txNodeTypeTest.cpp + MacOS + Text + + + + Name + txForwardContext.cpp + MacOS + Text + + + + Name + txNodeSetContext.cpp + MacOS + Text + + Name MozillaNode.cpp @@ -1121,34 +1149,6 @@ Text - - Name - BasicNodeExpr.cpp - MacOS - Text - - - - Name - AttributeExpr.cpp - MacOS - Text - - - - Name - ElementExpr.cpp - MacOS - Text - - - - Name - ErrorFunctionCall.cpp - MacOS - Text - - Name FilterExpr.cpp @@ -1436,13 +1436,6 @@ Text - - Name - TextExpr.cpp - MacOS - Text - - Name ArrayList.cpp @@ -1478,13 +1471,6 @@ Text - - Name - ExtensionFunctionCall.cpp - MacOS - Text - - Name GenerateIdFunctionCall.cpp @@ -1569,13 +1555,6 @@ Text - - Name - Expr.cpp - MacOS - Text - - Name ExprLexerChars.cpp @@ -1702,6 +1681,20 @@ Text Debug + + Name + txPatternParser.cpp + MacOS + Text + Debug + + + Name + txXSLTPatterns.cpp + MacOS + Text + Debug + @@ -1739,6 +1732,26 @@ UnicharUtilsStaticDebug.o MacOS + + Name + txNameTest.cpp + MacOS + + + Name + txNodeTypeTest.cpp + MacOS + + + Name + txForwardContext.cpp + MacOS + + + Name + txNodeSetContext.cpp + MacOS + Name List.cpp @@ -1799,26 +1812,6 @@ VariableBinding.cpp MacOS - - Name - BasicNodeExpr.cpp - MacOS - - - Name - AttributeExpr.cpp - MacOS - - - Name - ElementExpr.cpp - MacOS - - - Name - ErrorFunctionCall.cpp - MacOS - Name FilterExpr.cpp @@ -1959,11 +1952,6 @@ RootExpr.cpp MacOS - - Name - TextExpr.cpp - MacOS - Name ArrayList.cpp @@ -2074,11 +2062,6 @@ XMLParser.cpp MacOS - - Name - ExtensionFunctionCall.cpp - MacOS - Name GenerateIdFunctionCall.cpp @@ -2139,11 +2122,6 @@ txKeyFunctionCall.cpp MacOS - - Name - Expr.cpp - MacOS - Name ExprLexerChars.cpp @@ -2229,6 +2207,16 @@ txExpandedNameMap.cpp MacOS + + Name + txPatternParser.cpp + MacOS + + + Name + txXSLTPatterns.cpp + MacOS + @@ -3271,34 +3259,6 @@ Text - - Name - BasicNodeExpr.cpp - MacOS - Text - - - - Name - AttributeExpr.cpp - MacOS - Text - - - - Name - ElementExpr.cpp - MacOS - Text - - - - Name - ErrorFunctionCall.cpp - MacOS - Text - - Name FilterExpr.cpp @@ -3586,13 +3546,6 @@ Text - - Name - TextExpr.cpp - MacOS - Text - - Name ArrayList.cpp @@ -3656,13 +3609,6 @@ Text - - Name - ExtensionFunctionCall.cpp - MacOS - Text - - Name GenerateIdFunctionCall.cpp @@ -3747,13 +3693,6 @@ Text - - Name - Expr.cpp - MacOS - Text - - Name ExprLexerChars.cpp @@ -3880,6 +3819,48 @@ Text Debug + + Name + txForwardContext.cpp + MacOS + Text + Debug + + + Name + txNameTest.cpp + MacOS + Text + Debug + + + Name + txNodeSetContext.cpp + MacOS + Text + Debug + + + Name + txNodeTypeTest.cpp + MacOS + Text + Debug + + + Name + txPatternParser.cpp + MacOS + Text + Debug + + + Name + txXSLTPatterns.cpp + MacOS + Text + Debug + @@ -3957,26 +3938,6 @@ VariableBinding.cpp MacOS - - Name - BasicNodeExpr.cpp - MacOS - - - Name - AttributeExpr.cpp - MacOS - - - Name - ElementExpr.cpp - MacOS - - - Name - ErrorFunctionCall.cpp - MacOS - Name FilterExpr.cpp @@ -4117,11 +4078,6 @@ RootExpr.cpp MacOS - - Name - TextExpr.cpp - MacOS - Name ArrayList.cpp @@ -4252,11 +4208,6 @@ XMLParser.cpp MacOS - - Name - ExtensionFunctionCall.cpp - MacOS - Name GenerateIdFunctionCall.cpp @@ -4317,11 +4268,6 @@ txKeyFunctionCall.cpp MacOS - - Name - Expr.cpp - MacOS - Name ExprLexerChars.cpp @@ -4407,6 +4353,36 @@ txExpandedNameMap.cpp MacOS + + Name + txForwardContext.cpp + MacOS + + + Name + txNameTest.cpp + MacOS + + + Name + txNodeSetContext.cpp + MacOS + + + Name + txNodeTypeTest.cpp + MacOS + + + Name + txPatternParser.cpp + MacOS + + + Name + txXSLTPatterns.cpp + MacOS + @@ -4645,24 +4621,12 @@ AdditiveExpr.cpp MacOS - - transformiixDebug.shlb - Name - AttributeExpr.cpp - MacOS - transformiixDebug.shlb Name AttributeValueTemplate.cpp MacOS - - transformiixDebug.shlb - Name - BasicNodeExpr.cpp - MacOS - transformiixDebug.shlb Name @@ -4681,24 +4645,6 @@ BooleanResult.cpp MacOS - - transformiixDebug.shlb - Name - ElementExpr.cpp - MacOS - - - transformiixDebug.shlb - Name - ErrorFunctionCall.cpp - MacOS - - - transformiixDebug.shlb - Name - Expr.cpp - MacOS - transformiixDebug.shlb Name @@ -4717,12 +4663,6 @@ ExprParser.cpp MacOS - - transformiixDebug.shlb - Name - ExtensionFunctionCall.cpp - MacOS - transformiixDebug.shlb Name @@ -4852,7 +4792,25 @@ transformiixDebug.shlb Name - TextExpr.cpp + txForwardContext.cpp + MacOS + + + transformiixDebug.shlb + Name + txNameTest.cpp + MacOS + + + transformiixDebug.shlb + Name + txNodeSetContext.cpp + MacOS + + + transformiixDebug.shlb + Name + txNodeTypeTest.cpp MacOS @@ -4917,6 +4875,12 @@ txOutputFormat.cpp MacOS + + transformiixDebug.shlb + Name + txPatternParser.cpp + MacOS + transformiixDebug.shlb Name @@ -4929,6 +4893,12 @@ txTextHandler.cpp MacOS + + transformiixDebug.shlb + Name + txXSLTPatterns.cpp + MacOS + transformiixDebug.shlb Name diff --git a/mozilla/extensions/transformiix/source/base/ErrorObserver.h b/mozilla/extensions/transformiix/source/base/ErrorObserver.h index 826dac4414a..ceb95dae458 100644 --- a/mozilla/extensions/transformiix/source/base/ErrorObserver.h +++ b/mozilla/extensions/transformiix/source/base/ErrorObserver.h @@ -28,6 +28,7 @@ #include "baseutils.h" #include "TxString.h" +#include "txError.h" #include /** @@ -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); diff --git a/mozilla/extensions/transformiix/source/base/SimpleErrorObserver.cpp b/mozilla/extensions/transformiix/source/base/SimpleErrorObserver.cpp index debfef44ccb..f9d4716ca4e 100644 --- a/mozilla/extensions/transformiix/source/base/SimpleErrorObserver.cpp +++ b/mozilla/extensions/transformiix/source/base/SimpleErrorObserver.cpp @@ -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; diff --git a/mozilla/extensions/transformiix/source/base/txError.h b/mozilla/extensions/transformiix/source/base/txError.h index 9fe0349753a..e45914b939a 100644 --- a/mozilla/extensions/transformiix/source/base/txError.h +++ b/mozilla/extensions/transformiix/source/base/txError.h @@ -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 diff --git a/mozilla/extensions/transformiix/source/main/Makefile.in b/mozilla/extensions/transformiix/source/main/Makefile.in index 7fa3b20586e..13780723a9f 100644 --- a/mozilla/extensions/transformiix/source/main/Makefile.in +++ b/mozilla/extensions/transformiix/source/main/Makefile.in @@ -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) \ diff --git a/mozilla/extensions/transformiix/source/main/makefile.win b/mozilla/extensions/transformiix/source/main/makefile.win index b44e4a386a8..21700e0b1e9 100644 --- a/mozilla/extensions/transformiix/source/main/makefile.win +++ b/mozilla/extensions/transformiix/source/main/makefile.win @@ -59,19 +59,13 @@ CPP_OBJS= \ ../xml/dom/standalone/$(OBJDIR)/ProcessingInstruction.obj \ ../xml/dom/standalone/$(OBJDIR)/Text.obj \ ../xpath/$(OBJDIR)/AdditiveExpr.obj \ - ../xpath/$(OBJDIR)/AttributeExpr.obj \ ../xpath/$(OBJDIR)/AttributeValueTemplate.obj \ - ../xpath/$(OBJDIR)/BasicNodeExpr.obj \ ../xpath/$(OBJDIR)/BooleanExpr.obj \ ../xpath/$(OBJDIR)/BooleanFunctionCall.obj \ ../xpath/$(OBJDIR)/BooleanResult.obj \ - ../xpath/$(OBJDIR)/ElementExpr.obj \ - ../xpath/$(OBJDIR)/ErrorFunctionCall.obj \ - ../xpath/$(OBJDIR)/Expr.obj \ ../xpath/$(OBJDIR)/ExprLexer.obj \ ../xpath/$(OBJDIR)/ExprLexerChars.obj \ ../xpath/$(OBJDIR)/ExprParser.obj \ - ../xpath/$(OBJDIR)/ExtensionFunctionCall.obj \ ../xpath/$(OBJDIR)/FilterExpr.obj \ ../xpath/$(OBJDIR)/FunctionCall.obj \ ../xpath/$(OBJDIR)/LocationStep.obj \ @@ -88,7 +82,10 @@ CPP_OBJS= \ ../xpath/$(OBJDIR)/StringExpr.obj \ ../xpath/$(OBJDIR)/StringFunctionCall.obj \ ../xpath/$(OBJDIR)/StringResult.obj \ - ../xpath/$(OBJDIR)/TextExpr.obj \ + ../xpath/$(OBJDIR)/txNameTest.obj \ + ../xpath/$(OBJDIR)/txNodeTypeTest.obj \ + ../xpath/$(OBJDIR)/txForwardContext.obj \ + ../xpath/$(OBJDIR)/txNodeSetContext.obj \ ../xpath/$(OBJDIR)/UnionExpr.obj \ ../xpath/$(OBJDIR)/UnaryExpr.obj \ ../xpath/$(OBJDIR)/VariableRefExpr.obj \ @@ -105,6 +102,8 @@ CPP_OBJS= \ ../xslt/$(OBJDIR)/txTextHandler.obj \ ../xslt/$(OBJDIR)/txTextOutput.obj \ ../xslt/$(OBJDIR)/txXMLOutput.obj \ + ../xslt/$(OBJDIR)/txXSLTPatterns.obj \ + ../xslt/$(OBJDIR)/txPatternParser.obj \ ../xslt/$(OBJDIR)/VariableBinding.obj \ ../xslt/$(OBJDIR)/XSLTProcessor.obj \ ../xslt/functions/$(OBJDIR)/CurrentFunctionCall.obj \ diff --git a/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp b/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp index cd440e7a503..1088c38aa3b 100644 --- a/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp deleted file mode 100644 index b9b26725945..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/*-*- 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 "XMLDOMUtils.h" - -/* - This class represents a Attribute Expression as defined by the XPath - 1.0 Recommendation -*/ - -const String AttributeExpr::WILD_CARD = "*"; - -//- Constructors -/ - -AttributeExpr::AttributeExpr(String& name) -{ - if (name.isEqual(WILD_CARD)) { - isNameWild = MB_TRUE; - isNamespaceWild = MB_TRUE; - return; - } - - int idx = name.indexOf(':'); - if (idx >= 0) - name.subString(0, idx, prefix); - else - idx = -1; - - name.subString(idx+1, this->name); - - //-- set flags - isNamespaceWild = MB_FALSE; - isNameWild = this->name.isEqual(WILD_CARD); -} //-- AttributeExpr - - //------------------/ - //- Public Methods -/ -//------------------/ - -/** - * 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* AttributeExpr::evaluate(Node* context, ContextState* cs) { - NS_ASSERTION(0, "AttributeExpr::evaluate called"); - return 0; -} //-- evaluate - -/** - * Returns the default priority of this Pattern based on the given Node, - * context Node, and ContextState. -**/ -double AttributeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { - if (!isNameWild) - return 0; - if (!isNamespaceWild) - return -0.25; - return -0.5; -} //-- getDefaultPriority - - //-----------------------------/ - //- Methods from NodeExpr.cpp -/ -//-----------------------------/ - -/** - * Determines whether this NodeExpr matches the given node within - * the given context -**/ -MBool AttributeExpr::matches(Node* node, Node* context, ContextState* cs) { - - //XXX need to filter out namespace-declaration attributes! - - if ( (!node) || (node->getNodeType() != Node::ATTRIBUTE_NODE) ) - return MB_FALSE; - - if ( isNameWild && isNamespaceWild ) return MB_TRUE; - - const String nodeName = ((Attr*)node)->getName(); - int idx = nodeName.indexOf(':'); - if (idx >= 0) { - String prefixForNode; - nodeName.subString(0,idx,prefixForNode); - String localName; - nodeName.subString(idx+1, localName); - if (isNamespaceWild) return localName.isEqual(this->name); - String nsForNode; - Node* parent = node->getXPathParent(); - if (parent) - XMLDOMUtils::getNamespaceURI(prefixForNode, (Element*)parent, - nsForNode); - String nsForTest; - if (!prefix.isEmpty()) - cs->getNameSpaceURIFromPrefix(prefix, nsForTest); - if (!nsForTest.isEqual(nsForNode)) return MB_FALSE; - return localName.isEqual(this->name); - } - else { - if (isNamespaceWild) return nodeName.isEqual(this->name); - String nsForTest; - if (!prefix.isEmpty()) - cs->getNameSpaceURIFromPrefix(prefix, nsForTest); - if (!nsForTest.isEmpty()) - return MB_FALSE; - return nodeName.isEqual(this->name); - } - return MB_FALSE; -} //-- matches - - -/** - * Returns the String representation of this NodeExpr. - * @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 NodeExpr. -**/ -void AttributeExpr::toString(String& dest) { - if (isNameWild && isNamespaceWild) dest.append('*'); - else { - dest.append(this->prefix); - dest.append(':'); - dest.append(this->name); - } -} //-- toString - diff --git a/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp b/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp index 2ea5341c0f2..16d78c60ef5 100644 --- a/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp +++ b/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp deleted file mode 100644 index 6dabc4a5d3d..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- 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" - -//- Constructors -/ - -/** - * Creates a new BasicNodeExpr of the given type -**/ -BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType) { - this->type = nodeExprType; - nodeNameSet = MB_FALSE; -} //-- BasicNodeExpr - - //------------------/ - //- Public Methods -/ -//------------------/ - -void BasicNodeExpr::setNodeName(const String& name) { - this->nodeName = name; - nodeNameSet = MB_TRUE; -} - - //-----------------------------/ - //- Methods from NodeExpr.cpp -/ -//-----------------------------/ - -/** - * 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* BasicNodeExpr::evaluate(Node* context, ContextState* cs) { - NS_ASSERTION(0, "BasicNodeExpr::evaluate called"); - return 0; -} //-- evaluate - -/** - * Returns the default priority of this Expr based on the given Node, - * context Node, and ContextState. -**/ -double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, - ContextState* cs) { - if (nodeNameSet) - return 0; - return -0.5; -} //-- getDefaultPriority - -/** - * Determines whether this NodeExpr matches the given node within - * the given context -**/ -MBool BasicNodeExpr::matches(Node* node, Node* context, ContextState* cs) { - if (!node) - return MB_FALSE; - switch (type) { - case NodeExpr::COMMENT_EXPR: - return (MBool)(node->getNodeType() == Node::COMMENT_NODE); - case NodeExpr::PI_EXPR : - return (MBool)(node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE && - !nodeNameSet || nodeName.isEqual(node->getNodeName())); - default: //-- node() - if (node->getNodeType() == Node::TEXT_NODE || - node->getNodeType() == Node::CDATA_SECTION_NODE) - return !cs->isStripSpaceAllowed(node); - return MB_TRUE; - } - return MB_TRUE; -} //-- matches - - -/** - * Returns the String representation of this NodeExpr. - * @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 NodeExpr. -**/ -void BasicNodeExpr::toString(String& dest) { - switch (type) { - case NodeExpr::COMMENT_EXPR: - dest.append("comment()"); - break; - case NodeExpr::PI_EXPR : - dest.append("processing-instruction("); - if (nodeNameSet) { - dest.append('\''); - dest.append(nodeName); - dest.append('\''); - } - dest.append(')'); - break; - default: //-- node() - dest.append("node()"); - break; - } -} //-- toString - diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp index 526c287ce70..acc91961dc6 100644 --- a/mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp index 8ad9a3484bf..761ffa31b13 100644 --- a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp @@ -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(¶ms); 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"); } diff --git a/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp b/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp deleted file mode 100644 index c09a6fb9af7..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* -*- 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 "XMLDOMUtils.h" - -/* - This class represents a ElementExpr as defined by XPath 1.0 - proposed recommendation -*/ - - -const String ElementExpr::WILD_CARD = "*"; - - -//- Constructors -/ -ElementExpr::ElementExpr(String& name) -{ - int idx = name.indexOf(':'); - if (idx >= 0) - name.subString(0, idx, prefix); - else - idx = -1; - - name.subString(idx+1, this->name); - - //-- set flags - isNameWild = this->name.isEqual(WILD_CARD); - isNamespaceWild = (isNameWild && prefix.isEmpty()); -} //-- ElementExpr - - //------------------/ - //- Public Methods -/ -//------------------/ - -/** - * 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* ElementExpr::evaluate(Node* context, ContextState* cs) { - NS_ASSERTION(0, "ElementExpr::evaluate called"); - return 0; -} //-- evaluate - -/** - * Returns the default priority of this Pattern based on the given Node, - * context Node, and ContextState. -**/ -double ElementExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { - if (!isNameWild) - return 0; - if (!isNamespaceWild) - return -0.25; - return -0.5; -} //-- getDefaultPriority - - //-----------------------------/ - //- Methods from NodeExpr.cpp -/ -//-----------------------------/ - -/** - * Determines whether this NodeExpr matches the given node within - * the given context -**/ -MBool ElementExpr::matches(Node* node, Node* context, ContextState* cs) { - - if ((!node) || (node->getNodeType() != Node::ELEMENT_NODE )) - return MB_FALSE; - - if (isNamespaceWild && isNameWild) return MB_TRUE; - - const String nodeName = node->getNodeName(); - - int idx = nodeName.indexOf(':'); - - if (!isNamespaceWild) { - //-- compare namespaces - String nsURI; - // use context to get namespace for testing against - if (!prefix.isEmpty()) - cs->getNameSpaceURIFromPrefix(prefix, nsURI); - - String nsURI2; - String prefix2; - if (idx > 0) nodeName.subString(0, idx, prefix2); - // use source tree to aquire namespace for node - XMLDOMUtils::getNamespaceURI(prefix2, (Element*) node, nsURI2); - - if (!nsURI.isEqual(nsURI2)) return MB_FALSE; - } - - if (this->isNameWild) return MB_TRUE; - //-- compare local names - if (idx < 0) return nodeName.isEqual(this->name); - else { - String local; - nodeName.subString(idx+1, local); - return local.isEqual(this->name); - } -} //-- matches - - -/** - * Returns the String representation of this NodeExpr. - * @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 NodeExpr. -**/ -void ElementExpr::toString(String& dest) { - dest.append(this->name); -} //-- toString - diff --git a/mozilla/extensions/transformiix/source/xpath/ErrorFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/ErrorFunctionCall.cpp deleted file mode 100644 index b06ab5e9042..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/ErrorFunctionCall.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 "FunctionLib.h" - -/** - * Creates an Error FunctionCall with no error message -**/ -ErrorFunctionCall::ErrorFunctionCall() : FunctionCall(XPathNames::ERROR_FN) {}; - -/** - * Creates an Error FunctionCall with the given error message -**/ -ErrorFunctionCall::ErrorFunctionCall - (const String& errorMsg) : FunctionCall(XPathNames::ERROR_FN) -{ - //-- copy errorMsg - this->errorMessage = errorMsg; -} //-- ErrorFunctionCall - -/** - * 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* ErrorFunctionCall::evaluate(Node* context, ContextState* cs) { - return new StringResult( errorMessage); -} //-- evaluate - -void ErrorFunctionCall::setErrorMessage(String& errorMsg) { - //-- copy errorMsg - this->errorMessage = errorMsg; -} //-- setError - diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.cpp b/mozilla/extensions/transformiix/source/xpath/Expr.cpp deleted file mode 100644 index 380e4c3c9eb..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/Expr.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- 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 Initial Developer of the Original Code is Jonas Sicking. - * Portions created by Jonas Sicking are Copyright (C) 2001, Jonas Sicking. - * All rights reserved. - * - * Contributor(s): - * Jonas Sicking, sicking@bigfoot.com - * -- original author. - */ - -#include "Expr.h" - -Expr::~Expr() { -} - -/* - * Determines whether this Expr matches the given node within - * the given context. - */ -MBool Expr::matches(Node* node, Node* context, ContextState* cs) -{ - NS_ASSERTION(0, "Expr::matches() called"); - return MB_FALSE; -} - -/* - * Returns the default priority of this Expr based on the given Node, - * context Node, and ContextState. - */ -double Expr::getDefaultPriority(Node* node, Node* context, ContextState* cs) -{ - NS_ASSERTION(0, "Expr::matches() called"); - return 0; -} diff --git a/mozilla/extensions/transformiix/source/xpath/Expr.h b/mozilla/extensions/transformiix/source/xpath/Expr.h index f46a3e0d06e..456591d7eb8 100644 --- a/mozilla/extensions/transformiix/source/xpath/Expr.h +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -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: diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp index 3631e3fe215..a3949738d6d 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp @@ -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; +} diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.h b/mozilla/extensions/transformiix/source/xpath/ExprParser.h index 432a8193a14..a0187df216c 100644 --- a/mozilla/extensions/transformiix/source/xpath/ExprParser.h +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.h @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/ExtensionFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/ExtensionFunctionCall.cpp deleted file mode 100644 index d0f2288f1e6..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/ExtensionFunctionCall.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 XSL:P XSLT processor. - * - * The Initial Developer of the Original Code is Keith Visco. - * Portions created by Keith Visco are Copyright (C) 1999, 2000 Keith Visco. - * All Rights Reserved. - * - * Contributor(s): - * Keith Visco, kvisco@ziplink.net - * -- original author. - * - */ - -#include "FunctionLib.h" - - -const String ExtensionFunctionCall::UNDEFINED_FUNCTION = "Undefined Function: "; - -/** - * Creates an ExtensionFunctionCall with the given function name. - * @param name the name of the extension function which to invoke -**/ -ExtensionFunctionCall::ExtensionFunctionCall(const String& name) : FunctionCall(name) -{ - this->fname = name; - this->fnCall = 0; - -} //-- ExtensionFunctionCall - -/** - * Deletes an instance of ExtensionFunctioncall -**/ -ExtensionFunctionCall::~ExtensionFunctionCall() { - delete fnCall; -} //-- ~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 -**/ -ExprResult* ExtensionFunctionCall::evaluate(Node* context, ContextState* cs) { - - //-- check for existing function call resolution - - if (!fnCall) { - fnCall = cs->resolveFunctionCall(fname); - - if (!fnCall) { - String err(UNDEFINED_FUNCTION); - err.append(fname); - return new StringResult(err); - } - - //copy parameters - ListIterator* iter = params.iterator(); - while (iter->hasNext()) { - fnCall->addParam( new ExprWrapper( (Expr*) iter->next() ) ); - } - delete iter; - } - - //-- delegate - return fnCall->evaluate(context, cs); - -} //-- evaluate - -//---------------------------------/ -//- Implementation of ExprWrapper -/ -//---------------------------------/ - -/** - * Creates a new ExprWrapper for the given Expr -**/ -ExprWrapper::ExprWrapper(Expr* expr) { - this->expr = expr; -} - -/** - * Destructor for ExprWrapper -**/ -ExprWrapper::~ExprWrapper() { - //-- DO NOTHING! -} - -/** - * 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* ExprWrapper::evaluate(Node* context, ContextState* cs) { - //-- just delegate - if (!expr) return 0; // <-- hopefully this will never happen - return expr->evaluate(context, cs); -} //-- evaluate - -/** - * 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. -**/ -void ExprWrapper::toString(String& str) { - //-- just delegate - if (expr) expr->toString(str); -} //-- toString - diff --git a/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp index 0be6684cd21..3c56737e472 100644 --- a/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp index 5decbc12b88..e6c9f0a8b68 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp @@ -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; diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionLib.h b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h index 64611b82d45..580863ee0ec 100644 --- a/mozilla/extensions/transformiix/source/xpath/FunctionLib.h +++ b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h @@ -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; diff --git a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp index 0e5511b1d95..8f9afd09cce 100644 --- a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp +++ b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/Makefile.in b/mozilla/extensions/transformiix/source/xpath/Makefile.in index 5a6e5ccbd3e..31ea4815074 100644 --- a/mozilla/extensions/transformiix/source/xpath/Makefile.in +++ b/mozilla/extensions/transformiix/source/xpath/Makefile.in @@ -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) diff --git a/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp index 4fcfd90c11b..e5605f26cb5 100644 --- a/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp index d786e76c498..33d55660e32 100644 --- a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp @@ -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(¶ms); 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"); } diff --git a/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp b/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp index f582910c5b7..14abfb02d85 100644 --- a/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp @@ -41,7 +41,8 @@ NumberExpr::NumberExpr(double dbl) { * for evaluation * @return the result of the evaluation **/ -ExprResult* NumberExpr::evaluate(Node* context, ContextState* cs) { +ExprResult* NumberExpr::evaluate(txIEvalContext* aContext) +{ return new NumberResult(_value); } //-- evaluate diff --git a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp index 34274f74cf8..23ad0a8d3d7 100644 --- a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp @@ -36,6 +36,7 @@ #include "FunctionLib.h" #include "XMLDOMUtils.h" #include +#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(¶ms); 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"); } diff --git a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp index 02ad5dbdac2..350fc6805e0 100644 --- a/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PathExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp index 689dd3c3a6a..8fcfdb73147 100644 --- a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp +++ b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp @@ -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(); } /* diff --git a/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp index aac3473fb27..f3fdd5a8fcb 100644 --- a/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp @@ -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(); diff --git a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp index a7562f6c280..948b0c65eac 100644 --- a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp b/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp index 9f04b2c873c..522c13c147e 100644 --- a/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp @@ -44,7 +44,8 @@ StringExpr::StringExpr(const String& value) { * for evaluation * @return the result of the evaluation **/ -ExprResult* StringExpr::evaluate(Node* context, ContextState* cs) { +ExprResult* StringExpr::evaluate(txIEvalContext* aContext) +{ return new StringResult(value); } //-- evaluate diff --git a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp index c68da321f8a..190eaabe171 100644 --- a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp @@ -31,6 +31,7 @@ #include "FunctionLib.h" #include "XMLDOMUtils.h" +#include "txIXPathContext.h" #include /** @@ -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(¶ms); 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"); } diff --git a/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp b/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp deleted file mode 100644 index 7cdc8b3580c..00000000000 --- a/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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" - -/** - * 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* TextExpr::evaluate(Node* context, ContextState* cs) { - NS_ASSERTION(0, "TextExpr::evaluate called"); - return 0; -} //-- evaluate - -/** - * Returns the default priority of this Pattern based on the given Node, - * context Node, and ContextState. -**/ -double TextExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { - return -0.5; -} //-- getDefaultPriority - -/** - * Determines whether this NodeExpr matches the given node within - * the given context -**/ -MBool TextExpr::matches(Node* node, Node* context, ContextState* cs) { - if (node) { - if (node->getNodeType() == Node::TEXT_NODE || - node->getNodeType() == Node::CDATA_SECTION_NODE) - return !cs->isStripSpaceAllowed(node); - } - return MB_FALSE; -} //-- matches - - -/** - * Returns the String representation of this NodeExpr. - * @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 NodeExpr. -**/ -void TextExpr::toString(String& dest) { - dest.append("text()"); -} //-- toString - diff --git a/mozilla/extensions/transformiix/source/xpath/UnaryExpr.cpp b/mozilla/extensions/transformiix/source/xpath/UnaryExpr.cpp index 4a9f3789515..fbc5ea92825 100644 --- a/mozilla/extensions/transformiix/source/xpath/UnaryExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/UnaryExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp index eae7a2849c1..2b13a8b4131 100644 --- a/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp index b48da2807b6..292d5b1d126 100644 --- a/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp +++ b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/makefile.win b/mozilla/extensions/transformiix/source/xpath/makefile.win index 3172b74cbde..94f22d0810f 100644 --- a/mozilla/extensions/transformiix/source/xpath/makefile.win +++ b/mozilla/extensions/transformiix/source/xpath/makefile.win @@ -37,19 +37,13 @@ DEFINES=$(DEFINES) -DTX_EXE CPP_OBJS= \ .\$(OBJDIR)\AdditiveExpr.obj \ - .\$(OBJDIR)\AttributeExpr.obj \ .\$(OBJDIR)\AttributeValueTemplate.obj \ - .\$(OBJDIR)\BasicNodeExpr.obj \ .\$(OBJDIR)\BooleanExpr.obj \ .\$(OBJDIR)\BooleanFunctionCall.obj \ .\$(OBJDIR)\BooleanResult.obj \ - .\$(OBJDIR)\ElementExpr.obj \ - .\$(OBJDIR)\ErrorFunctionCall.obj \ - .\$(OBJDIR)\Expr.obj \ .\$(OBJDIR)\ExprLexer.obj \ .\$(OBJDIR)\ExprLexerChars.obj \ .\$(OBJDIR)\ExprParser.obj \ - .\$(OBJDIR)\ExtensionFunctionCall.obj \ .\$(OBJDIR)\FilterExpr.obj \ .\$(OBJDIR)\FunctionCall.obj \ .\$(OBJDIR)\LocationStep.obj \ @@ -66,7 +60,10 @@ CPP_OBJS= \ .\$(OBJDIR)\StringExpr.obj \ .\$(OBJDIR)\StringFunctionCall.obj \ .\$(OBJDIR)\StringResult.obj \ - .\$(OBJDIR)\TextExpr.obj \ + .\$(OBJDIR)\txNameTest.obj \ + .\$(OBJDIR)\txNodeTypeTest.obj \ + .\$(OBJDIR)\txForwardContext.obj \ + .\$(OBJDIR)\txNodeSetContext.obj \ .\$(OBJDIR)\UnionExpr.obj \ .\$(OBJDIR)\UnaryExpr.obj \ .\$(OBJDIR)\VariableRefExpr.obj \ diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp index 72c33acec4a..7b34b1f4885 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp @@ -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? +} diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h index f6e8e44e72e..4e310f3ba41 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathEvaluator.h @@ -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 mNSMan; + }; }; /* d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc */ diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp index 2cca6bd2192..735b210d2c1 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.cpp @@ -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; +} diff --git a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h index 4f52676d5f7..00faa19f2cc 100644 --- a/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h +++ b/mozilla/extensions/transformiix/source/xpath/nsXPathExpression.h @@ -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 diff --git a/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp new file mode 100644 index 00000000000..ac0131ab5f9 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txForwardContext.cpp @@ -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 + * + * 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 +} diff --git a/mozilla/extensions/transformiix/source/xpath/txForwardContext.h b/mozilla/extensions/transformiix/source/xpath/txForwardContext.h new file mode 100644 index 00000000000..41ecb67b0c3 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txForwardContext.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h new file mode 100644 index 00000000000..09f0a833b10 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txIXPathContext.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp b/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp new file mode 100644 index 00000000000..e3d01f3d52f --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txNameTest.cpp @@ -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); +} diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp new file mode 100644 index 00000000000..50569e4fdd1 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.cpp @@ -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 + * + * 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 +} diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h new file mode 100644 index 00000000000..d9c6212e0be --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txNodeSetContext.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp b/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp new file mode 100644 index 00000000000..64da786916b --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txNodeTypeTest.cpp @@ -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; + } +} diff --git a/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h new file mode 100644 index 00000000000..bc6cab10c4b --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/txSingleNodeContext.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xslt/Makefile.in b/mozilla/extensions/transformiix/source/xslt/Makefile.in index 8dfec90a812..8694f050c51 100644 --- a/mozilla/extensions/transformiix/source/xslt/Makefile.in +++ b/mozilla/extensions/transformiix/source/xslt/Makefile.in @@ -54,6 +54,8 @@ CPPSRCS = Names.cpp \ txRtfHandler.cpp \ txTextHandler.cpp \ VariableBinding.cpp \ + txXSLTPatterns.cpp \ + txPatternParser.cpp \ XSLTProcessor.cpp ifdef TX_EXE diff --git a/mozilla/extensions/transformiix/source/xslt/Numbering.cpp b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp index 6b215e7be82..0cef799015a 100644 --- a/mozilla/extensions/transformiix/source/xslt/Numbering.cpp +++ b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp @@ -31,8 +31,9 @@ #include "Numbering.h" #include "Names.h" #include "txAtoms.h" +#include "XMLUtils.h" -void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context, +void Numbering::doNumbering(Element* xslNumber, String& dest, ProcessorState* ps) { if (!xslNumber) @@ -41,30 +42,31 @@ void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context, int* counts = 0; int nbrOfCounts = 0; - String valueAttr; - xslNumber->getAttr(txXSLTAtoms::value, kNameSpaceID_None, - valueAttr); //-- check for expr - if (!valueAttr.isEmpty()) { + if (xslNumber->hasAttr(txXSLTAtoms::value, kNameSpaceID_None)) { Expr* expr = ps->getExpr(xslNumber, ProcessorState::ValueAttr); - if (!expr) + if (!expr) { + // XXX error reporting, parse failed return; + } + ExprResult* result = expr->evaluate(ps->getEvalContext()); + double dbl = Double::NaN; + if (result) + dbl = result->numberValue(); + delete result; nbrOfCounts = 1; counts = new int[1]; - ExprResult* result = expr->evaluate(context, ps); - double dbl = result->numberValue(); - delete result; counts[0] = (int)dbl; } - else if (context) { - - //-- create count expression + else { + Node* context = ps->getEvalContext()->getContextNode(); + // create count pattern String countAttr; xslNumber->getAttr(txXSLTAtoms::count, kNameSpaceID_None, countAttr); - Pattern* countPattern; + txPattern* countPattern = 0; MBool ownsPattern; if (!countAttr.isEmpty()) { @@ -73,31 +75,52 @@ void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context, ownsPattern = MB_FALSE; } else { - // Actually, this code should probobly use NodeTests instead + MBool isAttr = MB_FALSE; + Node::NodeType type = Node::ELEMENT_NODE; + txNodeTypeTest::NodeType nodetype; switch(context->getNodeType()) { case Node::ATTRIBUTE_NODE: - countAttr.append('@'); - countAttr.append(context->getNodeName()); - break; + isAttr = MB_TRUE; + type = Node::ATTRIBUTE_NODE; case Node::ELEMENT_NODE: - countAttr.append(context->getNodeName()); + { + const String& name = context->getNodeName(); + String prefix, lname; + XMLUtils::getPrefix(name, prefix); + XMLUtils::getLocalPart(name, lname); + txAtom* prefixAtom = 0; + if (!prefix.isEmpty()) { + prefixAtom = TX_GET_ATOM(prefix); + } + txAtom* lNameAtom = TX_GET_ATOM(lname); + PRInt32 NSid = context->getNamespaceID(); + txNameTest* nt = new txNameTest(prefixAtom, lNameAtom, + NSid, type); + TX_IF_RELEASE_ATOM(prefixAtom); + TX_IF_RELEASE_ATOM(lNameAtom); + countPattern = new txStepPattern(nt, isAttr); + } break; case Node::CDATA_SECTION_NODE : case Node::TEXT_NODE : - countAttr.append("text()"); + nodetype = txNodeTypeTest::TEXT_TYPE; break; case Node::COMMENT_NODE : - countAttr.append("comment()"); + nodetype = txNodeTypeTest::COMMENT_TYPE; break; case Node::PROCESSING_INSTRUCTION_NODE : - countAttr.append("processing-instruction()"); + nodetype = txNodeTypeTest::PI_TYPE; break; default: - countAttr.append("node()[false()]"); //-- for now - break; + NS_ASSERTION(0, "Unexpected Node type"); + delete counts; + return; + } + if (!countPattern) { + // not a nametest + txNodeTypeTest* nt = new txNodeTypeTest(nodetype); + countPattern = new txStepPattern(nt, MB_FALSE); } - ExprParser parser; - countPattern = parser.createPattern(countAttr); ownsPattern = MB_TRUE; } if (!countPattern) { @@ -114,7 +137,7 @@ void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context, String fromAttr; xslNumber->getAttr(txXSLTAtoms::from, kNameSpaceID_None, fromAttr); - PatternExpr* from = 0; + txPattern* from = 0; if (MULTIPLE_VALUE.isEqual(level)) nodes = getAncestorsOrSelf(countPattern, @@ -150,7 +173,7 @@ void Numbering::doNumbering(Element* xslNumber, String& dest, Node* context, } //-- doNumbering int Numbering::countPreceedingSiblings - (PatternExpr* patternExpr, Node* context, ProcessorState* ps) + (txPattern* patternExpr, Node* context, ProcessorState* ps) { int count = 1; @@ -158,26 +181,27 @@ int Numbering::countPreceedingSiblings Node* sibling = context; while ((sibling = sibling->getPreviousSibling())) { - if (patternExpr->matches(sibling, sibling, ps)) + if (patternExpr->matches(sibling, ps)) ++count; } return count; } //-- countPreceedingSiblings NodeSet* Numbering::getAncestorsOrSelf - ( PatternExpr* countExpr, - PatternExpr* from, - Node* context, - ProcessorState* ps, - MBool findNearest) + (txPattern* countExpr, + txPattern* from, + Node* context, + ProcessorState* ps, + MBool findNearest) { NodeSet* nodeSet = new NodeSet(); Node* parent = context; while ((parent) && (parent->getNodeType() == Node::ELEMENT_NODE)) { - if ((from) && from->matches(parent, parent->getParentNode(), ps)) break; + if (from && from->matches(parent, ps)) + break; - if (countExpr->matches(parent, parent->getParentNode(), ps)) { + if (countExpr->matches(parent, ps)) { nodeSet->append(parent); if (findNearest) break; } diff --git a/mozilla/extensions/transformiix/source/xslt/Numbering.h b/mozilla/extensions/transformiix/source/xslt/Numbering.h index c0398c36200..17d8fcb2dce 100644 --- a/mozilla/extensions/transformiix/source/xslt/Numbering.h +++ b/mozilla/extensions/transformiix/source/xslt/Numbering.h @@ -33,7 +33,7 @@ #include "baseutils.h" #include "TxString.h" #include "ProcessorState.h" -#include "Expr.h" +#include "txXSLTPatterns.h" #include "primitives.h" #include "ExprResult.h" @@ -41,19 +41,19 @@ class Numbering { public: - static void doNumbering - (Element* xslNumber, String& dest, Node* context, ProcessorState* ps); + static void doNumbering(Element* xslNumber, String& dest, + ProcessorState* ps); private: static int countPreceedingSiblings - (PatternExpr* patternExpr, Node* context, ProcessorState* ps); + (txPattern* patternExpr, Node* context, ProcessorState* ps); static NodeSet* getAncestorsOrSelf - ( PatternExpr* countExpr, - PatternExpr* from, - Node* context, - ProcessorState* ps, - MBool findNearest ); + (txPattern* countExpr, + txPattern* from, + Node* context, + ProcessorState* ps, + MBool findNearest ); }; #endif diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp index 66bd35ea7bd..75159d62d38 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -49,8 +49,7 @@ /** * Creates a new ProcessorState **/ -ProcessorState::ProcessorState() : mXPathParseContext(0), - mSourceDocument(0), +ProcessorState::ProcessorState() : mEvalContext(0), mSourceDocument(0), xslDocument(0), resultDocument(0) { @@ -64,8 +63,7 @@ ProcessorState::ProcessorState() : mXPathParseContext(0), ProcessorState::ProcessorState(Document* aSourceDocument, Document* aXslDocument, Document* aResultDocument) - : mXPathParseContext(0), - mSourceDocument(aSourceDocument), + : mEvalContext(0), mSourceDocument(aSourceDocument), xslDocument(aXslDocument), resultDocument(aResultDocument) { @@ -112,7 +110,7 @@ void ProcessorState::addAttributeSet(Element* aAttributeSet, if (!aAttributeSet->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name)) { String err("missing required name attribute for xsl:attribute-set"); - recieveError(err); + receiveError(err); return; } // Get attribute set, if already exists, then merge @@ -165,45 +163,89 @@ void ProcessorState::addTemplate(Element* aXslTemplate, if (tmp) { String err("Duplicate template name: "); err.append(name); - recieveError(err); + receiveError(err); return; } aImportFrame->mNamedTemplates.put(name, aXslTemplate); } String match; - if (aXslTemplate->getAttr(txXSLTAtoms::match, - kNameSpaceID_None, match)) { - // get the txList for the right mode - String mode; - aXslTemplate->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, mode); - txList* templates = - (txList*)aImportFrame->mMatchableTemplates.get(mode); + if (!aXslTemplate->getAttr(txXSLTAtoms::match, kNameSpaceID_None, match)) { + // This is no error, see section 6 Named Templates + return; + } + // get the txList for the right mode + String mode; + aXslTemplate->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, mode); + txList* templates = + (txList*)aImportFrame->mMatchableTemplates.get(mode); + if (!templates) { + templates = new txList; if (!templates) { - templates = new txList; - if (!templates) { - NS_ASSERTION(0, "out of memory"); - return; - } - aImportFrame->mMatchableTemplates.put(mode, templates); - } - - // Add the template to the list of templates - MatchableTemplate* templ = new MatchableTemplate; - if (!templ) { NS_ASSERTION(0, "out of memory"); return; } - templ->mTemplate = aXslTemplate; - Element* oldContext = mXPathParseContext; - mXPathParseContext = aXslTemplate; - templ->mMatch = exprParser.createPattern(match); - mXPathParseContext = oldContext; - if (templ->mMatch) - templates->add(templ); - else - delete templ; + aImportFrame->mMatchableTemplates.put(mode, templates); + } + + // Check for explicit default priority + MBool hasPriority; + double priority; + String prio; + if ((hasPriority = + aXslTemplate->getAttr(txXSLTAtoms::priority, kNameSpaceID_None, + prio))) { + priority = Double::toDouble(prio); + } + + // Get the pattern + txPSParseContext context(this, aXslTemplate); + txPattern* pattern = txPatternParser::createPattern(match, &context, this); +#ifdef TX_PATTERN_DEBUG + String foo; + pattern->toString(foo); +#endif + + if (!pattern) { + return; + } + + // Add the simple patterns to the list of matchable templates, according + // to default priority + txList simpleMatches; + pattern->getSimplePatterns(simpleMatches); + txListIterator simples(&simpleMatches); + while (simples.hasNext()) { + txPattern* simple = (txPattern*)simples.next(); + if (simple != pattern && pattern) { + // txUnionPattern, it doesn't own the txLocPathPatterns no more, + // so delete it. (only once, of course) + delete pattern; + pattern = 0; + } + if (!hasPriority) { + priority = simple->getDefaultPriority(); + } + MatchableTemplate* nt = new MatchableTemplate(aXslTemplate, + simple, + priority); + if (!nt) { + NS_ASSERTION(0, "out of mem"); + return; + } + txListIterator templ(templates); + MBool isLast = MB_TRUE; + while (templ.hasNext() && isLast) { + MatchableTemplate* mt = (MatchableTemplate*)templ.next(); + if (priority < mt->mPriority) { + continue; + } + templ.addBefore(nt); + isLast = MB_FALSE; + } + if (isLast) + templates->add(nt); } } @@ -231,19 +273,27 @@ void ProcessorState::addLREStylesheet(Document* aStylesheet, } // Add the template to the list of templates - MatchableTemplate* templ = new MatchableTemplate; - if (!templ) { + txPattern* root = new txRootPattern(MB_TRUE); + MatchableTemplate* nt = 0; + if (root) + nt = new MatchableTemplate(aStylesheet, root, Double::NaN); + if (!nt) { + delete root; // XXX ErrorReport: out of memory return; } - - templ->mTemplate = aStylesheet; - String match("/"); - templ->mMatch = exprParser.createPattern(match); - if (templ->mMatch) - templates->add(templ); - else - delete templ; + txListIterator templ(templates); + MBool isLast = MB_TRUE; + while (templ.hasNext() && isLast) { + MatchableTemplate* mt = (MatchableTemplate*)templ.next(); + if (0.5 < mt->mPriority) { + continue; + } + templ.addBefore(nt); + isLast = MB_FALSE; + } + if (isLast) + templates->add(nt); } /* @@ -279,7 +329,7 @@ Node* ProcessorState::retrieveDocument(const String& uri, const String& baseUri) err.append(docUrl); err.append("': "); err.append(errMsg); - recieveError(err, ErrorObserver::WARNING); + receiveError(err, NS_ERROR_XSLT_INVALID_URL); return NULL; } // add to list of documents @@ -373,31 +423,15 @@ Node* ProcessorState::findTemplate(Node* aNode, // Find template with highest priority MatchableTemplate* templ; - while ((templ = (MatchableTemplate*)templateIter.next())) { - String priorityAttr; - - if (templ->mTemplate->getNodeType() == Node::ELEMENT_NODE) { - Element* elem = (Element*)templ->mTemplate; - elem->getAttr(txXSLTAtoms::priority, kNameSpaceID_None, - priorityAttr); - } - - double tmpPriority; - if (!priorityAttr.isEmpty()) { - tmpPriority = Double::toDouble(priorityAttr); - } - else { - tmpPriority = templ->mMatch->getDefaultPriority(aNode, - 0, - this); - } - - if (tmpPriority >= currentPriority && - templ->mMatch->matches(aNode, 0, this)) { - + while (!matchTemplate && + (templ = (MatchableTemplate*)templateIter.next())) { +#ifdef TX_PATTERN_DEBUG + String foo; + templ->mMatch->toString(foo); +#endif + if (templ->mMatch->matches(aNode, this)) { matchTemplate = templ->mTemplate; *aImportFrame = frame; - currentPriority = tmpPriority; } } } @@ -467,91 +501,83 @@ NodeSet* ProcessorState::getAttributeSet(const String& aName) return attset; } -/** - * Returns the source node currently being processed -**/ -Node* ProcessorState::getCurrentNode() { - return currentNodeStack.peek(); -} //-- setCurrentNode - Expr* ProcessorState::getExpr(Element* aElem, ExprAttr aAttr) { NS_ASSERTION(aElem, "missing element while getting expression"); - // This is how we'll have to do it for now - mXPathParseContext = aElem; - Expr* expr = (Expr*)mExprHashes[aAttr].get(aElem); + if (expr) { + return expr; + } + String attr; + MBool hasAttr; + switch (aAttr) { + case SelectAttr: + hasAttr = aElem->getAttr(txXSLTAtoms::select, kNameSpaceID_None, + attr); + break; + case TestAttr: + hasAttr = aElem->getAttr(txXSLTAtoms::test, kNameSpaceID_None, + attr); + break; + case ValueAttr: + hasAttr = aElem->getAttr(txXSLTAtoms::value, kNameSpaceID_None, + attr); + break; + } + + if (!hasAttr) + return 0; + + txPSParseContext pContext(this, aElem); + expr = ExprParser::createExpr(attr, &pContext); + if (!expr) { - String attr; - switch (aAttr) { - case SelectAttr: - aElem->getAttr(txXSLTAtoms::select, kNameSpaceID_None, - attr); - break; - case TestAttr: - aElem->getAttr(txXSLTAtoms::test, kNameSpaceID_None, - attr); - break; - case ValueAttr: - aElem->getAttr(txXSLTAtoms::value, kNameSpaceID_None, - attr); - break; - } - - // This is how we should do it once we namespaceresolve during parsing - //Element* oldContext = mXPathParseContext; - //mXPathParseContext = aElem; - expr = exprParser.createExpr(attr); - //mXPathParseContext = oldContext; - - if (!expr) { - String err = "Error in parsing XPath expression: "; - err.append(attr); - recieveError(err); - } - else { - mExprHashes[aAttr].put(aElem, expr); - } + String err = "Error in parsing XPath expression: "; + err.append(attr); + receiveError(err, NS_ERROR_XPATH_PARSE_FAILED); + } + else { + mExprHashes[aAttr].put(aElem, expr); } return expr; } -PatternExpr* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr) +txPattern* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr) { NS_ASSERTION(aElem, "missing element while getting pattern"); - // This is how we'll have to do it for now - mXPathParseContext = aElem; + txPattern* pattern = (txPattern*)mPatternHashes[aAttr].get(aElem); + if (pattern) { + return pattern; + } + String attr; + MBool hasAttr; + switch (aAttr) { + case CountAttr: + hasAttr = aElem->getAttr(txXSLTAtoms::count, kNameSpaceID_None, + attr); + break; + case FromAttr: + hasAttr = aElem->getAttr(txXSLTAtoms::from, kNameSpaceID_None, + attr); + break; + } + + if (!hasAttr) + return 0; + + + txPSParseContext pContext(this, aElem); + pattern = txPatternParser::createPattern(attr, &pContext, this); - Pattern* pattern = (Pattern*)mExprHashes[aAttr].get(aElem); if (!pattern) { - String attr; - switch (aAttr) { - case CountAttr: - aElem->getAttr(txXSLTAtoms::count, kNameSpaceID_None, - attr); - break; - case FromAttr: - aElem->getAttr(txXSLTAtoms::from, kNameSpaceID_None, - attr); - break; - } - - // This is how we should do it once we namespaceresolve during parsing - //Element* oldContext = mXPathParseContext; - //mXPathParseContext = aElem; - pattern = exprParser.createPattern(attr); - //mXPathParseContext = oldContext; - - if (!pattern) { - String err = "Error in parsing pattern: "; - err.append(attr); - recieveError(err); - } - else { - mPatternHashes[aAttr].put(aElem, pattern); - } + String err = "Error in parsing pattern: "; + err.append(attr); + receiveError(err, NS_ERROR_XPATH_PARSE_FAILED); + } + else { + mPatternHashes[aAttr].put(aElem, pattern); } return pattern; } @@ -573,14 +599,6 @@ Element* ProcessorState::getNamedTemplate(String& aName) return 0; } -void ProcessorState::getNameSpaceURIFromPrefix(const String& aPrefix, - String& aNamespaceURI) -{ - if (mXPathParseContext) - XMLDOMUtils::getNamespaceURI(aPrefix, mXPathParseContext, - aNamespaceURI); -} - txOutputFormat* ProcessorState::getOutputFormat() { return &mOutputFormat; @@ -607,27 +625,22 @@ MBool ProcessorState::isXSLStripSpaceAllowed(Node* node) { } -/** - * Removes and returns the current source node being processed, from the stack - * @return the current source node -**/ -Node* ProcessorState::popCurrentNode() { - return currentNodeStack.pop(); -} //-- popCurrentNode - void ProcessorState::processAttrValueTemplate(const String& aAttValue, - Node* aContext, + Element* aContext, String& aResult) { aResult.clear(); + txPSParseContext pContext(this, aContext); AttributeValueTemplate* avt = - exprParser.createAttributeValueTemplate(aAttValue); + ExprParser::createAttributeValueTemplate(aAttValue, &pContext); + if (!avt) { - // XXX ErrorReport: out of memory + // fallback, just copy the attribute + aResult.append(aAttValue); return; } - ExprResult* exprResult = avt->evaluate(aContext, this); + ExprResult* exprResult = avt->evaluate(this->getEvalContext()); delete avt; if (!exprResult) { // XXX ErrorReport: out of memory @@ -638,20 +651,12 @@ void ProcessorState::processAttrValueTemplate(const String& aAttValue, delete exprResult; } -/** - * Sets the source node currently being processed - * @param node the source node to set as the "current" node -**/ -void ProcessorState::pushCurrentNode(Node* node) { - currentNodeStack.push(node); -} //-- setCurrentNode - /** * Adds the set of names to the Whitespace handling list. * xsl:strip-space calls this with MB_TRUE, xsl:preserve-space * with MB_FALSE */ -void ProcessorState::shouldStripSpace(String& aNames, +void ProcessorState::shouldStripSpace(String& aNames, Element* aElement, MBool aShouldStrip, ImportFrame* aImportFrame) { @@ -660,7 +665,20 @@ void ProcessorState::shouldStripSpace(String& aNames, String name; while (tokenizer.hasMoreTokens()) { tokenizer.nextToken(name); - txNameTestItem* nti = new txNameTestItem(name, aShouldStrip); + String prefix, lname; + PRInt32 aNSID = kNameSpaceID_None; + txAtom* prefixAtom = 0; + XMLUtils::getPrefix(name, prefix); + if (!prefix.isEmpty()) { + prefixAtom = TX_GET_ATOM(prefix); + aNSID = aElement->lookupNamespaceID(prefixAtom); + } + XMLUtils::getLocalPart(name, lname); + txAtom* lNameAtom = TX_GET_ATOM(lname); + txNameTestItem* nti = new txNameTestItem(prefixAtom, lNameAtom, + aNSID, aShouldStrip); + TX_IF_RELEASE_ATOM(prefixAtom); + TX_IF_RELEASE_ATOM(lNameAtom); if (!nti) { // XXX error report, parsing error or out of mem break; @@ -694,15 +712,17 @@ MBool ProcessorState::addKey(Element* aKeyElem) return MB_FALSE; xslKeys.put(keyName, xslKey); } - Element* oldContext = mXPathParseContext; - mXPathParseContext = aKeyElem; - Pattern* match; - String matchAttr, useAttr; - aKeyElem->getAttr(txXSLTAtoms::match, kNameSpaceID_None, matchAttr); - aKeyElem->getAttr(txXSLTAtoms::use, kNameSpaceID_None, useAttr); - match = exprParser.createPattern(matchAttr); - Expr* use = exprParser.createExpr(useAttr); - mXPathParseContext = oldContext; + txPattern* match = 0; + txPSParseContext pContext(this, aKeyElem); + String attrVal; + if (aKeyElem->getAttr(txXSLTAtoms::match, kNameSpaceID_None, attrVal)) { + match = txPatternParser::createPattern(attrVal, &pContext, this); + } + Expr* use = 0; + attrVal.clear(); + if (aKeyElem->getAttr(txXSLTAtoms::use, kNameSpaceID_None, attrVal)) { + use = ExprParser::createExpr(attrVal, &pContext); + } if (!match || !use || !xslKey->addKey(match, use)) { delete match; delete use; @@ -845,27 +865,18 @@ txDecimalFormat* ProcessorState::getDecimalFormat(String& name) return (txDecimalFormat*)decimalFormats.get(name); } - //--------------------------------------------------/ - //- Virtual Methods from derived from ContextState -/ -//--------------------------------------------------/ - - -/** - * Returns the Stack of context NodeSets - * @return the Stack of context NodeSets -**/ -Stack* ProcessorState::getNodeSetStack() { - return &nodeSetStack; -} //-- getNodeSetStack - /** * 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 **/ -ExprResult* ProcessorState::getVariable(String& name) { - +nsresult ProcessorState::getVariable(PRInt32 aNamespace, txAtom* aLName, + ExprResult*& aResult) +{ + String name; + // XXX TODO, bug 117658 + TX_GET_ATOM_STRING(aLName, name); StackIterator* iter = variableSets.iterator(); ExprResult* exprResult = 0; while (iter->hasNext()) { @@ -876,7 +887,8 @@ ExprResult* ProcessorState::getVariable(String& name) { } } delete iter; - return exprResult; + aResult = exprResult; + return aResult ? NS_OK : NS_ERROR_INVALID_ARG; } //-- getVariable /** @@ -929,69 +941,71 @@ MBool ProcessorState::isStripSpaceAllowed(Node* node) return (MBool)(STRIP == mode); } -/** - * Notifies this Error observer of a new error, with default - * level of NORMAL -**/ -void ProcessorState::recieveError(String& errorMessage) { - recieveError(errorMessage, ErrorObserver::NORMAL); -} //-- recieveError - /** * Notifies this Error observer of a new error using the given error level **/ -void ProcessorState::recieveError(String& errorMessage, ErrorLevel level) { - ListIterator* iter = errorObservers.iterator(); - while (iter->hasNext()) { - ErrorObserver* observer = (ErrorObserver*)iter->next(); - observer->recieveError(errorMessage, level); +void ProcessorState::receiveError(const String& errorMessage, nsresult aRes) +{ + ListIterator iter(&errorObservers); + while (iter.hasNext()) { + ErrorObserver* observer = (ErrorObserver*)iter.next(); + observer->receiveError(errorMessage, aRes); } - delete iter; -} //-- recieveError +} /** * 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. **/ -FunctionCall* ProcessorState::resolveFunctionCall(const String& name) { - String err; +#define CHECK_FN(_name) aName == txXSLTAtoms::##_name - if (DOCUMENT_FN.isEqual(name)) { - return new DocumentFunctionCall(this, mXPathParseContext); +nsresult ProcessorState::resolveFunctionCall(txAtom* aName, PRInt32 aID, + Element* aElem, + FunctionCall*& aFunction) +{ + aFunction = 0; + + if (aID != kNameSpaceID_None) { + return NS_ERROR_XPATH_PARSE_FAILED; } - else if (KEY_FN.isEqual(name)) { - return new txKeyFunctionCall(this); + if (CHECK_FN(document)) { + aFunction = new DocumentFunctionCall(this, aElem); + return NS_OK; } - else if (FORMAT_NUMBER_FN.isEqual(name)) { - return new txFormatNumberFunctionCall(this); + if (CHECK_FN(key)) { + aFunction = new txKeyFunctionCall(this); + return NS_OK; } - else if (CURRENT_FN.isEqual(name)) { - return new CurrentFunctionCall(this); + if (CHECK_FN(formatNumber)) { + aFunction = new txFormatNumberFunctionCall(this); + return NS_OK; } - else if (UNPARSED_ENTITY_URI_FN.isEqual(name)) { - err = "function not yet implemented: "; - err.append(name); + if (CHECK_FN(current)) { + aFunction = new CurrentFunctionCall(this); + return NS_OK; } - else if (GENERATE_ID_FN.isEqual(name)) { - return new GenerateIdFunctionCall(); + if (CHECK_FN(unparsedEntityUri)) { + return NS_ERROR_NOT_IMPLEMENTED; } - else if (SYSTEM_PROPERTY_FN.isEqual(name)) { - return new SystemPropertyFunctionCall(); + if (CHECK_FN(generateId)) { + aFunction = new GenerateIdFunctionCall(); + return NS_OK; } - else if (ELEMENT_AVAILABLE_FN.isEqual(name)) { - return new ElementAvailableFunctionCall(); + if (CHECK_FN(systemProperty)) { + aFunction = new SystemPropertyFunctionCall(aElem); + return NS_OK; } - else if (FUNCTION_AVAILABLE_FN.isEqual(name)) { - return new FunctionAvailableFunctionCall(); + if (CHECK_FN(elementAvailable)) { + aFunction = new ElementAvailableFunctionCall(aElem); + return NS_OK; } - else { - err = "invalid function call: "; - err.append(name); + if (CHECK_FN(functionAvailable)) { + aFunction = new FunctionAvailableFunctionCall(); + return NS_OK; } - return new ErrorFunctionCall(err); - + return NS_ERROR_XPATH_PARSE_FAILED; } //-- resolveFunctionCall //-------------------/ @@ -1057,9 +1071,6 @@ void ProcessorState::initialize() } if (xslDocument) { loadedDocuments.put(xslDocument->getBaseURI(), xslDocument); - // XXX hackarond to get namespacehandling in a little better shape - // we won't need to do this once we resolve namespaces during parsing - mXPathParseContext = xslDocument->getDocumentElement(); } // make sure all keys are deleted @@ -1105,3 +1116,34 @@ ProcessorState::ImportFrame::~ImportFrame() } delete templKeys; } + +/* + * txPSParseContext + * txIParseContext used by ProcessorState internally + */ + +nsresult txPSParseContext::resolveNamespacePrefix(txAtom* aPrefix, + PRInt32& aID) +{ +#ifdef DEBUG + if (!aPrefix || aPrefix == txXMLAtoms::_empty) { + // default namespace is not forwarded to xpath + NS_ASSERTION(0, "caller should handle default namespace ''"); + aID = kNameSpaceID_None; + return NS_OK; + } +#endif + aID = mStyle->lookupNamespaceID(aPrefix); + return (aID != kNameSpaceID_Unknown) ? NS_OK : NS_ERROR_FAILURE; +} + +nsresult txPSParseContext::resolveFunctionCall(txAtom* aName, PRInt32 aID, + FunctionCall*& aFunction) +{ + return mPS->resolveFunctionCall(aName, aID, mStyle, aFunction); +} + +void txPSParseContext::receiveError(const String& aMsg, nsresult aRes) +{ + mPS->receiveError(aMsg, aRes); +} diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h index bc9f64ee24c..f2a12e2969c 100644 --- a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h @@ -33,11 +33,12 @@ #include "Stack.h" #include "ErrorObserver.h" #include "NamedMap.h" -#include "ExprParser.h" +#include "txPatternParser.h" #include "Expr.h" #include "StringList.h" #include "txOutputFormat.h" #include "Map.h" +#include "txIXPathContext.h" class txXSLKey; class txDecimalFormat; @@ -45,7 +46,7 @@ class txDecimalFormat; /** * Class used for keeping the current state of the XSL Processor **/ -class ProcessorState : public ContextState { +class ProcessorState : public txIMatchContext { public: /** @@ -145,14 +146,6 @@ public: */ Element* getNamedTemplate(String& aName); - /** - * Returns the NodeStack which keeps track of where we are in the - * result tree - * @return the NodeStack which keeps track of where we are in the - * result tree - **/ - NodeStack* getNodeStack(); - /** * Returns the OutputFormat which contains information on how * to serialize the output. I will be removing this soon, when @@ -176,7 +169,7 @@ public: }; Expr* getExpr(Element* aElem, ExprAttr aAttr); - Pattern* getPattern(Element* aElem, PatternAttr aAttr); + txPattern* getPattern(Element* aElem, PatternAttr aAttr); /** * Returns a pointer to the result document @@ -263,28 +256,17 @@ public: **/ void preserveSpace(String& names); - /** - * Removes and returns the current node being processed from the stack - * @return the current node - **/ - Node* popCurrentNode(); - void processAttrValueTemplate(const String& aAttValue, - Node* aContext, + Element* aContext, String& aResult); - /** - * Sets the given source node as the "current node" being processed - * @param node the source node currently being processed - **/ - void pushCurrentNode(Node* node); - /** * Adds the set of names to the Whitespace stripping handling list. * xsl:strip-space calls this with MB_TRUE, xsl:preserve-space * with MB_FALSE + * aElement is used to resolve QNames */ - void shouldStripSpace(String& aNames, + void shouldStripSpace(String& aNames, Element* aElement, MBool aShouldStrip, ImportFrame* aImportFrame); @@ -310,65 +292,62 @@ public: **/ txDecimalFormat* getDecimalFormat(String& name); - //-------------------------------------/ - //- Virtual Methods from ContextState -/ - //-------------------------------------/ + /* + * Virtual methods from txIEvalContext + */ + + TX_DECL_MATCH_CONTEXT; + + /* + * Set the current txIEvalContext and get the prior one + */ + txIEvalContext* setEvalContext(txIEvalContext* aEContext) + { + txIEvalContext* tmp = mEvalContext; + mEvalContext = aEContext; + return tmp; + } + + /* + * Get the current txIEvalContext + */ + txIEvalContext* getEvalContext() + { + return mEvalContext; + } + + + /* + * More other functions + */ + void receiveError(String& errorMessage) + { + receiveError(errorMessage, NS_ERROR_FAILURE); + } /** - * 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); - - /** - * Returns the Stack of context NodeSets - * @return the Stack of context NodeSets - **/ - virtual Stack* getNodeSetStack(); - - /** - * Determines if the given XML node allows Whitespace stripping - **/ - virtual MBool isStripSpaceAllowed(Node* node); - - /** - * Notifies this Error observer of a new error, with default - * level of NORMAL - **/ - 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); - - /** - * Returns a call to the function that has the given name. - * This method is used for XPath Extension Functions. + * Returns a FunctionCall which has the given name. * @return the FunctionCall for the function with the given name. **/ - virtual FunctionCall* resolveFunctionCall(const String& name); - - /** - * Returns the namespace URI for the given namespace prefix. This method - * should only be called to get a namespace declared within the - * context (ie. the stylesheet). - **/ - void getNameSpaceURIFromPrefix(const String& aPrefix, String& aNamespaceURI); + nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID, + Element* aElem, FunctionCall*& aFunction); private: enum XMLSpaceMode {STRIP = 0, DEFAULT, PRESERVE}; - struct MatchableTemplate { + class MatchableTemplate { + public: + MatchableTemplate(Node* aTemplate, txPattern* aPattern, + double aPriority) + : mTemplate(aTemplate), mMatch(aPattern), mPriority(aPriority) + { + } Node* mTemplate; - Pattern* mMatch; + txPattern* mMatch; + double mPriority; }; - NodeStack currentNodeStack; - /** * The list of ErrorObservers registered with this ProcessorState **/ @@ -423,18 +402,20 @@ private: */ Map mPatternHashes[2]; + /* + * Current txIEvalContext* + */ + txIEvalContext* mEvalContext; + /* * Current template rule */ TemplateRule* mCurrentTemplateRule; - Element* mXPathParseContext; - Stack nodeSetStack; Document* mSourceDocument; Document* xslDocument; Document* resultDocument; Stack variableSets; - ExprParser exprParser; /** * Returns the closest xml:space value for the given node @@ -454,11 +435,15 @@ private: **/ class txNameTestItem { public: - txNameTestItem(String& aName, MBool stripSpace): - mNameTest(aName),mStrips(stripSpace) {} + txNameTestItem(txAtom* aPrefix, txAtom* aLocalName, PRUint32 aNSID, + MBool stripSpace) + : mNameTest(aPrefix, aLocalName, aNSID, Node::ELEMENT_NODE), + mStrips(stripSpace) + { + } - MBool matches(Node* aNode, ContextState* aCS) { - return mNameTest.matches(aNode, 0, aCS); + MBool matches(Node* aNode, txIMatchContext* aContext) { + return mNameTest.matches(aNode, aContext); } MBool stripsSpace() { @@ -466,13 +451,39 @@ public: } double getDefaultPriority() { - return mNameTest.getDefaultPriority(0, 0, 0); + return mNameTest.getDefaultPriority(); } protected: - ElementExpr mNameTest; + txNameTest mNameTest; MBool mStrips; }; +/* + * txPSParseContext + * a txIParseContext forwarding all but resolveNamespacePrefix + * to a ProcessorState + */ +class txPSParseContext : public txIParseContext { +public: + txPSParseContext(ProcessorState* aPS, Element* aStyleNode) + : mPS(aPS), mStyle(aStyleNode) + { + } + + ~txPSParseContext() + { + } + + nsresult resolveNamespacePrefix(txAtom* aPrefix, PRInt32& aID); + nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID, + FunctionCall*& aFunction); + void receiveError(const String& aMsg, nsresult aRes); + +protected: + ProcessorState* mPS; + Element* mStyle; +}; + #endif diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp index 99c06c402ae..a2dedb5c422 100644 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -54,6 +54,8 @@ #include "txAtoms.h" #include "TxLog.h" #include "txRtfHandler.h" +#include "txNodeSetContext.h" +#include "txSingleNodeContext.h" #ifndef TX_EXE #include "nsIDocShell.h" #include "nsIObserverService.h" @@ -144,9 +146,10 @@ XSLTProcessor::XSLTProcessor() : mOutputHandler(0), xslTypes.put(WITH_PARAM, new XSLType(XSLType::WITH_PARAM)); // Create default expressions - ExprParser parser; - String node("node()"); - mNodeExpr = parser.createExpr(node); + + // "node()" + txNodeTest* nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE); + mNodeExpr = new LocationStep(nt, LocationStep::CHILD_AXIS); } //-- XSLTProcessor @@ -351,7 +354,7 @@ Document* XSLTProcessor::process if (!xmlDoc) { String err("error reading XML document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; return 0; } //-- Read in XSL document @@ -359,7 +362,7 @@ Document* XSLTProcessor::process if (!xslDoc) { String err("error reading XSL stylesheet document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; delete xmlDoc; return 0; } @@ -386,7 +389,7 @@ Document* XSLTProcessor::process(istream& xmlInput, String& xmlFilename) { if (!xmlDoc) { String err("error reading XML document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; return 0; } //-- Read in XSL document @@ -402,7 +405,7 @@ Document* XSLTProcessor::process(istream& xmlInput, String& xmlFilename) { if (!xslDoc) { String err("error reading XSL stylesheet document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; delete xmlDoc; return 0; } @@ -542,7 +545,7 @@ void XSLTProcessor::processTopLevel(Document* aSource, err.append("\""); } err.append(" decimal format for xsl:decimal-format"); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); } break; } @@ -552,7 +555,8 @@ void XSLTProcessor::processTopLevel(Document* aSource, element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name); if (name.isEmpty()) { - notifyError("missing required name attribute for xsl:param"); + String err("missing required name attribute for xsl:param"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } @@ -563,7 +567,8 @@ void XSLTProcessor::processTopLevel(Document* aSource, } case XSLType::IMPORT : { - notifyError("xsl:import only allowed at top of stylesheet"); + String err("xsl:import only allowed at top of stylesheet"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } case XSLType::INCLUDE : @@ -586,7 +591,7 @@ void XSLTProcessor::processTopLevel(Document* aSource, String err("error adding key '"); err.append(name); err.append("'"); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); } break; @@ -679,7 +684,8 @@ void XSLTProcessor::processTopLevel(Document* aSource, element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name); if (name.isEmpty()) { - notifyError("missing required name attribute for xsl:variable"); + String err("missing required name attribute for xsl:variable"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } ExprResult* exprResult = processVariable(aSource, element, aPs); @@ -694,10 +700,10 @@ void XSLTProcessor::processTopLevel(Document* aSource, //-- add error to ErrorObserver String err("missing required 'elements' attribute for "); err.append("xsl:preserve-space"); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); } else { - aPs->shouldStripSpace(elements, + aPs->shouldStripSpace(elements, element, MB_FALSE, currentFrame); } @@ -711,10 +717,10 @@ void XSLTProcessor::processTopLevel(Document* aSource, //-- add error to ErrorObserver String err("missing required 'elements' attribute for "); err.append("xsl:strip-space"); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); } else { - aPs->shouldStripSpace(elements, + aPs->shouldStripSpace(elements, element, MB_TRUE, currentFrame); } @@ -754,7 +760,7 @@ void XSLTProcessor::processInclude(String& aHref, if (((String*)iter->next())->isEqual(aHref)) { String err("Stylesheet includes itself. URI: "); err.append(aHref); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); delete iter; return; } @@ -767,7 +773,7 @@ void XSLTProcessor::processInclude(String& aHref, if (!stylesheet) { String err("Unable to load included stylesheet "); err.append(aHref); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); aPs->getEnteredStylesheets()->pop(); return; } @@ -785,7 +791,7 @@ void XSLTProcessor::processInclude(String& aHref, default: // This should never happen String err("Unsupported fragment identifier"); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } @@ -823,10 +829,9 @@ Document* XSLTProcessor::process(Document& xmlDocument, while (iter.hasNext()) ps.addErrorObserver(*(ErrorObserver*)iter.next()); - NodeSet nodeSet(&aXMLDocument); - ps.pushCurrentNode(&aXMLDocument); - ps.getNodeSetStack()->push(&nodeSet); - + txSingleNodeContext evalContext(&aXMLDocument, &ps); + ps.setEvalContext(&evalContext); + // Index templates and process top level xsl elements txListIterator importFrame(ps.getImportFrames()); importFrame.addAfter(new ProcessorState::ImportFrame(0)); @@ -882,9 +887,8 @@ void XSLTProcessor::process(Document& aXMLDocument, while (iter.hasNext()) ps.addErrorObserver(*(ErrorObserver*)iter.next()); - NodeSet nodeSet(&aXMLDocument); - ps.pushCurrentNode(&aXMLDocument); - ps.getNodeSetStack()->push(&nodeSet); + txSingleNodeContext evalContext(&aXMLDocument, &ps); + ps.setEvalContext(&evalContext); // Index templates and process top level xsl elements txListIterator importFrame(ps.getImportFrames()); @@ -926,7 +930,7 @@ void XSLTProcessor::process if (!xmlDoc) { String err("error reading XML document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; return; } //-- Read in XSL document @@ -942,7 +946,7 @@ void XSLTProcessor::process if (!xslDoc) { String err("error reading XSL stylesheet document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; delete xmlDoc; return; } @@ -954,7 +958,7 @@ void XSLTProcessor::process stylesheet = xslDoc->getElementById(frag); if (!stylesheet) { String err("unable to get fragment"); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; delete xmlDoc; delete xslDoc; return; @@ -987,7 +991,7 @@ void XSLTProcessor::process if (!xmlDoc) { String err("error reading XML document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; return; } //-- read in XSL Document @@ -995,7 +999,7 @@ void XSLTProcessor::process if (!xslDoc) { String err("error reading XSL stylesheet document: "); err.append(xmlParser.getErrorString()); - notifyError(err, ErrorObserver::FATAL); + cerr << err << endl; delete xmlDoc; return; } @@ -1031,7 +1035,7 @@ void XSLTProcessor::bindVariable String err("cannot rebind variables: "); err.append(name); err.append(" already exists in this scope."); - notifyError(err); + ps->receiveError(err, NS_ERROR_FAILURE); } } else { @@ -1068,39 +1072,6 @@ short XSLTProcessor::getElementType(Element* aElement, ProcessorState* aPs) return xslType->type; } -/** - * Notifies all registered ErrorObservers of the given error -**/ -void XSLTProcessor::notifyError(const char* errorMessage) { - String err(errorMessage); - notifyError(err, ErrorObserver::NORMAL); -} //-- notifyError - -/** - * Notifies all registered ErrorObservers of the given error -**/ -void XSLTProcessor::notifyError(String& errorMessage) { - notifyError(errorMessage, ErrorObserver::NORMAL); -} //-- notifyError - -/** - * Notifies all registered ErrorObservers of the given error -**/ -void XSLTProcessor::notifyError(String& errorMessage, ErrorObserver::ErrorLevel level) { - ListIterator* iter = errorObservers.iterator(); - - //-- send fatal errors to default observer if no error obersvers - //-- have been registered - if ((!iter->hasNext()) && (level == ErrorObserver::FATAL)) { - fatalObserver.recieveError(errorMessage, level); - } - while ( iter->hasNext() ) { - ErrorObserver* observer = (ErrorObserver*)iter->next(); - observer->recieveError(errorMessage, level); - } - delete iter; -} //-- notifyError - void XSLTProcessor::process(Node* node, const String& mode, ProcessorState* ps) { @@ -1150,7 +1121,7 @@ void XSLTProcessor::processAction(Node* aNode, curr = aPs->getCurrentTemplateRule(); if (!curr) { String err("apply-imports not allowed here"); - aPs->recieveError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } @@ -1174,16 +1145,13 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* exprResult = expr->evaluate(aNode, aPs); + ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); if (!exprResult) break; if (exprResult->getResultType() == ExprResult::NODESET) { NodeSet* nodeSet = (NodeSet*)exprResult; - //-- push nodeSet onto context stack - aPs->getNodeSetStack()->push(nodeSet); - // Look for xsl:sort elements txNodeSorter sorter(aPs); Node* child = actionElement->getFirstChild(); @@ -1202,22 +1170,27 @@ void XSLTProcessor::processAction(Node* aNode, String mode; actionElement->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, mode); - for (int i = 0; i < nodeSet->size(); i++) { + + txNodeSetContext evalContext(nodeSet, aPs); + txIEvalContext* priorEC = + aPs->setEvalContext(&evalContext); + while (evalContext.hasNext()) { + evalContext.next(); ProcessorState::ImportFrame *frame; - Node* currNode = nodeSet->get(i); + Node* currNode = evalContext.getContextNode(); Node* xslTemplate; xslTemplate = aPs->findTemplate(currNode, mode, &frame); processMatchedTemplate(xslTemplate, currNode, actualParams, mode, frame, aPs); } - //-- remove nodeSet from context stack - aPs->getNodeSetStack()->pop(); + aPs->setEvalContext(priorEC); delete actualParams; } else { - notifyError("error processing apply-templates"); + String err("error processing apply-templates"); + aPs->receiveError(err, NS_ERROR_FAILURE); } //-- clean up delete exprResult; @@ -1229,20 +1202,21 @@ void XSLTProcessor::processAction(Node* aNode, String nameAttr; if (!actionElement->getAttr(txXSLTAtoms::name, kNameSpaceID_None, nameAttr)) { - notifyError("missing required name attribute for xsl:attribute"); + String err("missing required name attribute for xsl:attribute"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } // Process name as an AttributeValueTemplate String name; - aPs->processAttrValueTemplate(nameAttr, aNode, name); + aPs->processAttrValueTemplate(nameAttr, actionElement, name); // Check name validity (must be valid QName and not xmlns) if (!XMLUtils::isValidQName(name)) { String err("error processing xsl:attribute, "); err.append(name); err.append(" is not a valid QName."); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } @@ -1250,7 +1224,7 @@ void XSLTProcessor::processAction(Node* aNode, if (nameAtom == txXMLAtoms::xmlns) { TX_RELEASE_ATOM(nameAtom); String err("error processing xsl:attribute, name is xmlns."); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } TX_IF_RELEASE_ATOM(nameAtom); @@ -1262,7 +1236,8 @@ void XSLTProcessor::processAction(Node* aNode, if (actionElement->getAttr(txXSLTAtoms::_namespace, kNameSpaceID_None, resultNs)) { String nsURI; - aPs->processAttrValueTemplate(resultNs, aNode, nsURI); + aPs->processAttrValueTemplate(resultNs, actionElement, + nsURI); resultNsID = resultDoc->namespaceURIToID(nsURI); } else { @@ -1314,7 +1289,8 @@ void XSLTProcessor::processAction(Node* aNode, } } else { - notifyError("missing required name attribute for xsl:call-template"); + String err("missing required name attribute for xsl:call-template"); + aPs->receiveError(err, NS_ERROR_FAILURE); } break; } @@ -1335,7 +1311,8 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* result = expr->evaluate(aNode, aPs); + ExprResult* result = expr->evaluate + (aPs->getEvalContext()); if (result && result->booleanValue()) { processChildren(aNode, xslTemplate, aPs); caseFound = MB_TRUE; @@ -1384,7 +1361,7 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* exprResult = expr->evaluate(aNode, aPs); + ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); xslCopyOf(exprResult, aPs); delete exprResult; break; @@ -1396,20 +1373,21 @@ void XSLTProcessor::processAction(Node* aNode, String nameAttr; if (!actionElement->getAttr(txXSLTAtoms::name, kNameSpaceID_None, nameAttr)) { - notifyError("missing required name attribute for xsl:element"); + String err("missing required name attribute for xsl:element"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } // Process name as an AttributeValueTemplate String name; - aPs->processAttrValueTemplate(nameAttr, aNode, name); + aPs->processAttrValueTemplate(nameAttr, actionElement, name); // Check name validity (must be valid QName and not xmlns) if (!XMLUtils::isValidQName(name)) { String err("error processing xsl:element, '"); err.append(name); err.append("' is not a valid QName."); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); // XXX We should processChildren without creating attributes or // namespace nodes. break; @@ -1421,7 +1399,7 @@ void XSLTProcessor::processAction(Node* aNode, PRInt32 resultNsID; if (actionElement->getAttr(txXSLTAtoms::_namespace, kNameSpaceID_None, resultNs)) { String nsURI; - aPs->processAttrValueTemplate(resultNs, aNode, nsURI); + aPs->processAttrValueTemplate(resultNs, actionElement, nsURI); if (nsURI.isEmpty()) resultNsID = kNameSpaceID_None; else @@ -1439,7 +1417,7 @@ void XSLTProcessor::processAction(Node* aNode, String err("error processing xsl:element, can't resolve prefix on'"); err.append(name); err.append("'."); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); // XXX We should processChildren without creating attributes or // namespace nodes. break; @@ -1459,15 +1437,15 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* exprResult = expr->evaluate(aNode, aPs); + ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); if (!exprResult) break; if (exprResult->getResultType() == ExprResult::NODESET) { NodeSet* nodeSet = (NodeSet*)exprResult; - - //-- push nodeSet onto context stack - aPs->getNodeSetStack()->push(nodeSet); + txNodeSetContext evalContext(nodeSet, aPs); + txIEvalContext* priorEC = + aPs->setEvalContext(&evalContext); // Look for xsl:sort elements txNodeSorter sorter(aPs); @@ -1498,20 +1476,18 @@ void XSLTProcessor::processAction(Node* aNode, oldTemplate = aPs->getCurrentTemplateRule(); aPs->setCurrentTemplateRule(0); - for (int i = 0; i < nodeSet->size(); i++) { - Node* currNode = nodeSet->get(i); - aPs->pushCurrentNode(currNode); + while (evalContext.hasNext()) { + evalContext.next(); + Node* currNode = evalContext.getContextNode(); processChildren(currNode, actionElement, aPs); - aPs->popCurrentNode(); } aPs->setCurrentTemplateRule(oldTemplate); - - // Remove nodeSet from context stack - aPs->getNodeSetStack()->pop(); + aPs->setEvalContext(priorEC); } else { - notifyError("error processing for-each"); + String err("error processing for-each"); + aPs->receiveError(err, NS_ERROR_FAILURE); } //-- clean up exprResult delete exprResult; @@ -1524,7 +1500,7 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* exprResult = expr->evaluate(aNode, aPs); + ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); if (!exprResult) break; @@ -1560,7 +1536,7 @@ void XSLTProcessor::processAction(Node* aNode, case XSLType::NUMBER: { String result; - Numbering::doNumbering(actionElement, result, aNode, aPs); + Numbering::doNumbering(actionElement, result, aPs); NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); mResultHandler->characters(result); break; @@ -1579,13 +1555,13 @@ void XSLTProcessor::processAction(Node* aNode, kNameSpaceID_None, nameAttr)) { String err("missing required name attribute for xsl:"); err.append(PROC_INST); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } // Process name as an AttributeValueTemplate String name; - aPs->processAttrValueTemplate(nameAttr, aNode, name); + aPs->processAttrValueTemplate(nameAttr, actionElement, name); // Check name validity (must be valid NCName and a PITarget) // XXX Need to check for NCName and PITarget @@ -1595,7 +1571,7 @@ void XSLTProcessor::processAction(Node* aNode, err.append(", '"); err.append(name); err.append("' is not a valid QName."); - notifyError(err); + aPs->receiveError(err, NS_ERROR_FAILURE); } // Compute value @@ -1640,10 +1616,11 @@ void XSLTProcessor::processAction(Node* aNode, if (!expr) break; - ExprResult* exprResult = expr->evaluate(aNode, aPs); + ExprResult* exprResult = expr->evaluate(aPs->getEvalContext()); String value; if (!exprResult) { - notifyError("null ExprResult"); + String err("null ExprResult"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } exprResult->stringValue(value); @@ -1670,7 +1647,8 @@ void XSLTProcessor::processAction(Node* aNode, String name; if (!actionElement->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name)) { - notifyError("missing required name attribute for xsl:variable"); + String err("missing required name attribute for xsl:variable"); + aPs->receiveError(err, NS_ERROR_FAILURE); break; } ExprResult* exprResult = processVariable(aNode, actionElement, aPs); @@ -1699,7 +1677,7 @@ void XSLTProcessor::processAction(Node* aNode, continue; // Process Attribute Value Templates String value; - aPs->processAttrValueTemplate(attr->getValue(), aNode, value); + aPs->processAttrValueTemplate(attr->getValue(), actionElement, value); NS_ASSERTION(mResultHandler, "mResultHandler must not be NULL!"); mResultHandler->attribute(attr->getName(), attr->getNamespaceID(), value); } @@ -1798,7 +1776,8 @@ NamedMap* XSLTProcessor::processParameters(Element* xslAction, Node* context, Pr String name; if (!action->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name)) { - notifyError("missing required name attribute for xsl:with-param"); + String err("missing required name attribute for xsl:with-param"); + ps->receiveError(err, NS_ERROR_FAILURE); } else { ExprResult* exprResult = processVariable(context, action, ps); @@ -1807,7 +1786,7 @@ NamedMap* XSLTProcessor::processParameters(Element* xslAction, Node* context, Pr String err("value for parameter '"); err.append(name); err.append("' specified more than once."); - notifyError(err); + ps->receiveError(err, NS_ERROR_FAILURE); } else { VariableBinding* binding = new VariableBinding(name, exprResult); @@ -1925,9 +1904,7 @@ void XSLTProcessor::processMatchedTemplate(Node* aXslTemplate, newTemplate.mParams = aParams; aPs->setCurrentTemplateRule(&newTemplate); - aPs->pushCurrentNode(aNode); processTemplate(aNode, aXslTemplate, aPs, aParams); - aPs->popCurrentNode(); aPs->setCurrentTemplateRule(oldTemplate); } @@ -1956,28 +1933,29 @@ void XSLTProcessor::processDefaultTemplate(Node* node, if (!mNodeExpr) break; - ExprResult* exprResult = mNodeExpr->evaluate(node, ps); + ExprResult* exprResult = mNodeExpr->evaluate(ps->getEvalContext()); if (!exprResult || exprResult->getResultType() != ExprResult::NODESET) { - notifyError("None-nodeset returned while processing default template"); + String err("None-nodeset returned while processing default template"); + ps->receiveError(err, NS_ERROR_FAILURE); delete exprResult; return; } NodeSet* nodeSet = (NodeSet*)exprResult; + txNodeSetContext evalContext(nodeSet, ps); + txIEvalContext* priorEC = ps->setEvalContext(&evalContext); - //-- push nodeSet onto context stack - ps->getNodeSetStack()->push(nodeSet); - for (int i = 0; i < nodeSet->size(); i++) { - Node* currNode = nodeSet->get(i); + while (evalContext.hasNext()) { + evalContext.next(); + Node* currNode = evalContext.getContextNode(); ProcessorState::ImportFrame *frame; Node* xslTemplate = ps->findTemplate(currNode, mode, &frame); processMatchedTemplate(xslTemplate, currNode, 0, mode, frame, ps); } - //-- remove nodeSet from context stack - ps->getNodeSetStack()->pop(); + ps->setEvalContext(priorEC); delete exprResult; break; } @@ -2022,7 +2000,8 @@ void XSLTProcessor::processTemplateParams String name; if (!action->getAttr(txXSLTAtoms::name, kNameSpaceID_None, name)) { - notifyError("missing required name attribute for xsl:param"); + String err("missing required name attribute for xsl:param"); + ps->receiveError(err, NS_ERROR_FAILURE); } else { VariableBinding* binding = 0; @@ -2075,7 +2054,7 @@ ExprResult* XSLTProcessor::processVariable Expr* expr = ps->getExpr(xslVariable, ProcessorState::SelectAttr); if (!expr) return new StringResult("unable to process variable"); - return expr->evaluate(node, ps); + return expr->evaluate(ps->getEvalContext()); } else if (xslVariable->hasChildNodes()) { txResultTreeFragment* rtf = new txResultTreeFragment(); @@ -2418,10 +2397,9 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, // XXX Need to add error observers - // Set current node and nodeset. - NodeSet nodeSet(&sourceDocument); - ps.pushCurrentNode(&sourceDocument); - ps.getNodeSetStack()->push(&nodeSet); + // Set current txIEvalContext + txSingleNodeContext evalContext(&sourceDocument, &ps); + ps.setEvalContext(&evalContext); // Index templates and process top level xsl elements ListIterator importFrame(ps.getImportFrames()); diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h index d20f7dd3204..756c54ddcaf 100644 --- a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h @@ -275,21 +275,6 @@ private: **/ short getElementType(Element* aElement, ProcessorState* aPs); - /** - * Notifies all registered ErrorObservers of the given error - **/ - void notifyError(const char* errorMessage); - - /** - * Notifies all registered ErrorObservers of the given error - **/ - void notifyError(String& errorMessage); - - /** - * Notifies all registered ErrorObservers of the given error - **/ - void notifyError(String& errorMessage, ErrorObserver::ErrorLevel level); - #ifdef TX_EXE /** * Parses the contents of data, and returns the type and href psuedo attributes diff --git a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp index cd9adf74937..04de602ef6b 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp @@ -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()); } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp index e808d6c283d..28b3487e322 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp index 3b00c8e7e84..2808637066f 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/ElementAvailableFnCall.cpp @@ -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(¶ms); 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; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp index c9cfd7413fc..7258c6268d6 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/FunctionAvailableFnCall.cpp @@ -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(¶ms); 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; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp index 59331770397..c193afe117f 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/GenerateIdFunctionCall.cpp @@ -24,6 +24,7 @@ #include "XSLTFunctions.h" #include "Names.h" +#include "txIXPathContext.h" #ifdef TX_EXE #include #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(¶ms); 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 diff --git a/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp index db6ed23c9b8..79cc50a2472 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp @@ -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); } } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h index 13a921d4ae2..27f87ad856c 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h +++ b/mozilla/extensions/transformiix/source/xslt/functions/XSLTFunctions.h @@ -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: }; diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp index 1c76314a28c..b71ed2b97bf 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp @@ -39,6 +39,7 @@ #include "XSLTFunctions.h" #include "primitives.h" #include "Names.h" +#include "txIXPathContext.h" #include #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); } diff --git a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp index 0792360cb65..050cbe08640 100644 --- a/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp +++ b/mozilla/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp @@ -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(¶ms); 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; isize(); i++) { diff --git a/mozilla/extensions/transformiix/source/xslt/makefile.win b/mozilla/extensions/transformiix/source/xslt/makefile.win index a0c9c3b8aaa..83d05c18595 100644 --- a/mozilla/extensions/transformiix/source/xslt/makefile.win +++ b/mozilla/extensions/transformiix/source/xslt/makefile.win @@ -51,6 +51,8 @@ CPP_OBJS= \ .\$(OBJDIR)\txRtfHandler.obj \ .\$(OBJDIR)\txTextHandler.obj \ .\$(OBJDIR)\VariableBinding.obj \ + .\$(OBJDIR)\txXSLTPatterns.obj \ + .\$(OBJDIR)\txPatternParser.obj \ .\$(OBJDIR)\XSLTProcessor.obj !ifdef TX_EXE diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp new file mode 100644 index 00000000000..7077631eef3 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.cpp @@ -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 + * + * 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; +} diff --git a/mozilla/extensions/transformiix/source/xslt/txPatternParser.h b/mozilla/extensions/transformiix/source/xslt/txPatternParser.h new file mode 100644 index 00000000000..fc4731cd56c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txPatternParser.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp new file mode 100644 index 00000000000..59a60f8e94d --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.cpp @@ -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 + * + * 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 content = do_QueryInterface(aNode->getNSObj()); + NS_ASSERTION(content, "a Element without nsIContent"); + if (!content) { + return MB_FALSE; + } + nsCOMPtr ni; + content->GetNodeInfo(*getter_AddRefs(ni)); + if (!ni) { + return MB_FALSE; + } + nsCOMPtr 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 +} diff --git a/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h new file mode 100644 index 00000000000..d9c0ee865ff --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/txXSLTPatterns.h @@ -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 + * + * 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 diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp index bdf8c0aeee4..ef1167fc145 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.cpp @@ -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; } diff --git a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h index 3e5e2aaf5d4..536698a238a 100644 --- a/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h +++ b/mozilla/extensions/transformiix/source/xslt/util/txNodeSorter.h @@ -83,7 +83,8 @@ private: }; int compareNodes(SortableNode* sNode1, - SortableNode* sNode2); + SortableNode* sNode2, + NodeSet* aNodes); MBool getAttrAsAVT(Element* aSortElement, txAtom* aAttrName,