From e087ec3f85700089eae8d584f0b8082f25c3c4e8 Mon Sep 17 00:00:00 2001 From: "kvisco%ziplink.net" Date: Thu, 6 Apr 2000 07:47:44 +0000 Subject: [PATCH] Changed directory structure, changed name of XSLProcessor to XSLTProcessor git-svn-id: svn://10.0.0.236/trunk@65423 18797224-902f-48f8-a5cc-f745e15eee43 --- .../extensions/transformiix/source/Makefile | 46 +- .../extensions/transformiix/source/clean.mk | 14 +- .../transformiix/source/main/transformiix.cpp | 36 +- .../transformiix/source/makefile.win | 2 +- .../source/xpath/AdditiveExpr.cpp | 139 ++ .../source/xpath/AttributeExpr.cpp | 150 ++ .../source/xpath/AttributeValueTemplate.cpp | 99 ++ .../source/xpath/BasicNodeExpr.cpp | 139 ++ .../transformiix/source/xpath/BooleanExpr.cpp | 134 ++ .../source/xpath/BooleanFunctionCall.cpp | 103 ++ .../source/xpath/BooleanResult.cpp | 97 + .../transformiix/source/xpath/ElementExpr.cpp | 144 ++ .../source/xpath/ErrorFunctionCall.cpp | 64 + .../transformiix/source/xpath/Expr.h | 1509 ++++++++++++++++ .../transformiix/source/xpath/ExprLexer.cpp | 698 ++++++++ .../transformiix/source/xpath/ExprLexer.h | 291 +++ .../transformiix/source/xpath/ExprParser.cpp | 905 ++++++++++ .../transformiix/source/xpath/ExprParser.h | 106 ++ .../transformiix/source/xpath/ExprResult.h | 162 ++ .../transformiix/source/xpath/FilterExpr.cpp | 147 ++ .../source/xpath/FunctionCall.cpp | 202 +++ .../transformiix/source/xpath/FunctionLib.h | 365 ++++ .../source/xpath/IdentityExpr.cpp | 59 + .../source/xpath/LocationStep.cpp | 317 ++++ .../transformiix/source/xpath/Makefile | 168 ++ .../source/xpath/MultiplicativeExpr.cpp | 146 ++ .../transformiix/source/xpath/NodeSet.cpp | 352 ++++ .../transformiix/source/xpath/NodeSet.h | 241 +++ .../source/xpath/NodeSetFunctionCall.cpp | 166 ++ .../transformiix/source/xpath/NumberExpr.cpp | 66 + .../source/xpath/NumberFunctionCall.cpp | 146 ++ .../source/xpath/NumberResult.cpp | 112 ++ .../transformiix/source/xpath/ParentExpr.cpp | 59 + .../transformiix/source/xpath/Parser.cpp | 185 ++ .../transformiix/source/xpath/PathExpr.cpp | 306 ++++ .../source/xpath/PredicateList.cpp | 143 ++ .../source/xpath/RelationalExpr.cpp | 208 +++ .../transformiix/source/xpath/RootExpr.cpp | 82 + .../transformiix/source/xpath/StringExpr.cpp | 79 + .../source/xpath/StringFunctionCall.cpp | 243 +++ .../source/xpath/StringResult.cpp | 96 + .../transformiix/source/xpath/TextExpr.cpp | 94 + .../transformiix/source/xpath/UnionExpr.cpp | 166 ++ .../source/xpath/VariableRefExpr.cpp | 118 ++ .../source/xpath/WildCardExpr.cpp | 100 ++ .../transformiix/source/xpath/XPathNames.cpp | 64 + .../transformiix/source/xpath/makefile.win | 115 ++ .../transformiix/source/xpath/parser.exe | Bin 0 -> 2326 bytes .../transformiix/source/xpath/parser.mk | 30 + .../transformiix/source/xslt/Makefile | 61 + .../transformiix/source/xslt/Names.cpp | 145 ++ .../transformiix/source/xslt/Names.h | 142 ++ .../transformiix/source/xslt/Numbering.cpp | 195 ++ .../transformiix/source/xslt/Numbering.h | 64 + .../transformiix/source/xslt/OutputFormat.cpp | 227 +++ .../transformiix/source/xslt/OutputFormat.h | 203 +++ .../source/xslt/ProcessorState.cpp | 760 ++++++++ .../transformiix/source/xslt/ProcessorState.h | 350 ++++ .../source/xslt/VariableBinding.cpp | 125 ++ .../source/xslt/VariableBinding.h | 127 ++ .../source/xslt/XSLTProcessor.cpp | 1565 +++++++++++++++++ .../transformiix/source/xslt/XSLTProcessor.h | 416 +++++ .../transformiix/source/xslt/makefile.win | 62 + .../transformiix/source/xslt/util/Makefile | 10 + .../source/xslt/util/NodeStack.cpp | 271 +++ .../transformiix/source/xslt/util/NodeStack.h | 198 +++ .../source/xslt/util/makefile.win | 53 + 67 files changed, 14338 insertions(+), 49 deletions(-) create mode 100644 mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/BooleanResult.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/ErrorFunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/Expr.h create mode 100644 mozilla/extensions/transformiix/source/xpath/ExprLexer.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/ExprLexer.h create mode 100644 mozilla/extensions/transformiix/source/xpath/ExprParser.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/ExprParser.h create mode 100644 mozilla/extensions/transformiix/source/xpath/ExprResult.h create mode 100644 mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/FunctionLib.h create mode 100644 mozilla/extensions/transformiix/source/xpath/IdentityExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/LocationStep.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/Makefile create mode 100644 mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/NodeSet.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/NodeSet.h create mode 100644 mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/NumberResult.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/ParentExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/Parser.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/PathExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/PredicateList.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/RootExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/StringExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/StringResult.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/TextExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/WildCardExpr.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/XPathNames.cpp create mode 100644 mozilla/extensions/transformiix/source/xpath/makefile.win create mode 100755 mozilla/extensions/transformiix/source/xpath/parser.exe create mode 100644 mozilla/extensions/transformiix/source/xpath/parser.mk create mode 100644 mozilla/extensions/transformiix/source/xslt/Makefile create mode 100644 mozilla/extensions/transformiix/source/xslt/Names.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/Names.h create mode 100644 mozilla/extensions/transformiix/source/xslt/Numbering.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/Numbering.h create mode 100644 mozilla/extensions/transformiix/source/xslt/OutputFormat.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/OutputFormat.h create mode 100644 mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/ProcessorState.h create mode 100644 mozilla/extensions/transformiix/source/xslt/VariableBinding.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/VariableBinding.h create mode 100644 mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h create mode 100644 mozilla/extensions/transformiix/source/xslt/makefile.win create mode 100644 mozilla/extensions/transformiix/source/xslt/util/Makefile create mode 100644 mozilla/extensions/transformiix/source/xslt/util/NodeStack.cpp create mode 100644 mozilla/extensions/transformiix/source/xslt/util/NodeStack.h create mode 100644 mozilla/extensions/transformiix/source/xslt/util/makefile.win diff --git a/mozilla/extensions/transformiix/source/Makefile b/mozilla/extensions/transformiix/source/Makefile index 06079e45dd7..3cbefd7d062 100644 --- a/mozilla/extensions/transformiix/source/Makefile +++ b/mozilla/extensions/transformiix/source/Makefile @@ -3,14 +3,14 @@ target: TransforMiiX CC := g++ ROOT_PATH = . -XML_PATH = $(ROOT_PATH)/xml -XSL_PATH = $(ROOT_PATH)/xsl BASE_PATH = $(ROOT_PATH)/base -DOM_PATH = $(XML_PATH)/dom NET_PATH = $(ROOT_PATH)/net -EXPR_PATH = $(XSL_PATH)/expr +XML_PATH = $(ROOT_PATH)/xml +DOM_PATH = $(XML_PATH)/dom +XPATH_PATH = $(ROOT_PATH)/xpath +XSLT_PATH = $(ROOT_PATH)/xslt XMLUTIL_PATH = $(XML_PATH)/util -XSLUTIL_PATH = $(XSL_PATH)/util +XSLTUTIL_PATH = $(XSLT_PATH)/util XMLPRINTER_PATH = $(XML_PATH)/printer XMLPARSER_PATH = $(XML_PATH)/parser EXPAT_PARSER_PATH = $(XMLPARSER_PATH)/xmlparse @@ -21,10 +21,10 @@ INCLUDE_PATHS = -I$(BASE_PATH) \ -I$(NET_PATH) \ -I$(DOM_PATH) \ -I$(XML_PATH) \ - -I$(EXPR_PATH) \ - -I$(XSL_PATH) \ - -I$(XMLUTIL_PATH) \ - -I$(XSLUTIL_PATH) \ + -I$(XPATH_PATH) \ + -I$(XSLT_PATH) \ + -I$(XMLUTIL_PATH) \ + -I$(XSLTUTIL_PATH) \ -I$(XMLPARSER_PATH) \ -I$(XMLPRINTER_PATH) \ -I$(EXPAT_PARSER_PATH) -I- @@ -32,29 +32,29 @@ INCLUDE_PATHS = -I$(BASE_PATH) \ BASE_OBJS = $(BASE_PATH)/*.o NET_OBJS = $(NET_PATH)/*.o DOM_OBJS = $(DOM_PATH)/*.o -EXPR_OBJS = $(EXPR_PATH)/*.o +XPATH_OBJS = $(XPATH_PATH)/*.o XML_OBJS = $(XML_PATH)/*.o XMLUTIL_OBJS = $(XMLUTIL_PATH)/*.o XMLPRINTER_OBJS = $(XMLPRINTER_PATH)/*.o XMLPARSER_OBJS = $(XMLPARSER_PATH)/*.o EXPAT_TOKEN_OBJS = $(EXPAT_TOKEN_PATH)/*.o EXPAT_PARSER_OBJS = $(EXPAT_PARSER_PATH)/*.o -XSL_OBJS = $(XSL_PATH)/*.o -XSLUTIL_OBJS = $(XSLUTIL_PATH)/*.o +XSLT_OBJS = $(XSLT_PATH)/*.o +XSLTUTIL_OBJS = $(XSLTUTIL_PATH)/*.o ALL_OBJS = $(BASE_OBJS) \ $(NET_OBJS) \ $(DOM_OBJS) \ - $(EXPR_OBJS) \ + $(XPATH_OBJS) \ $(XML_OBJS) \ $(XMLUTIL_OBJS) \ $(XMLPRINTER_OBJS) \ $(XMLPARSER_OBJS) \ $(EXPAT_TOKEN_OBJS) \ $(EXPAT_PARSER_OBJS) \ - $(XSL_OBJS) \ - $(XSLUTIL_OBJS) - + $(XSLT_OBJS) \ + $(XSLTUTIL_OBJS) + MAIN_CPP = main/transformiix.cpp TransforMiiX: $(ALL_OBJS) @@ -82,19 +82,19 @@ $(EXPAT_PARSER_OBJS): $(XMLPARSER_OBJS): cd $(XMLPARSER_PATH); make - + $(XMLPRINTER_OBJS): cd $(XMLPRINTER_PATH); make $(NET_OBJS): cd $(NET_PATH); make -$(XSLUTIL_OBJS): - cd $(XSLUTIL_PATH); make +$(XSLTUTIL_OBJS): + cd $(XSLTUTIL_PATH); make -$(EXPR_OBJS): - cd $(EXPR_PATH); make +$(XPATH_OBJS): + cd $(XPATH_PATH); make -$(XSL_OBJS): - cd $(XSL_PATH); make +$(XSLT_OBJS): + cd $(XSLT_PATH); make diff --git a/mozilla/extensions/transformiix/source/clean.mk b/mozilla/extensions/transformiix/source/clean.mk index 8b894609234..8d7e473d762 100644 --- a/mozilla/extensions/transformiix/source/clean.mk +++ b/mozilla/extensions/transformiix/source/clean.mk @@ -4,12 +4,12 @@ PROJ_PATH = ${PWD} ROOT_PATH = $(PROJ_PATH) XML_PATH = $(ROOT_PATH)/xml XMLUTIL_PATH = $(XML_PATH)/util -XSL_PATH = $(ROOT_PATH)/xsl +XSLT_PATH = $(ROOT_PATH)/xslt BASE_PATH = $(ROOT_PATH)/base DOM_PATH = $(XML_PATH)/dom NET_PATH = $(ROOT_PATH)/net -EXPR_PATH = $(XSL_PATH)/expr -XSLUTIL_PATH = $(XSL_PATH)/util +XPATH_PATH = $(ROOT_PATH)/xpath +XSLTUTIL_PATH = $(XSLT_PATH)/util XMLPRINTER_PATH = $(XML_PATH)/printer XMLPARSER_PATH = $(XML_PATH)/parser EXPAT_PARSER_PATH = $(XMLPARSER_PATH)/xmlparse @@ -20,12 +20,12 @@ clean: cd $(BASE_PATH); $(CMDS) \ cd $(NET_PATH); $(CMDS) \ cd $(XML_PATH); $(CMDS) \ - cd $(XMLUTIL_PATH); $(CMDS) \ + cd $(XMLUTIL_PATH); $(CMDS) \ cd $(DOM_PATH); $(CMDS) \ cd $(XMLPARSER_PATH); $(CMDS) \ cd $(EXPAT_PARSER_PATH); $(CMDS) \ cd $(EXPAT_TOKEN_PATH); $(CMDS) \ cd $(XMLPRINTER_PATH); $(CMDS) \ - cd $(XSL_PATH); $(CMDS) \ - cd $(XSLUTIL_PATH); $(CMDS) \ - cd $(EXPR_PATH); $(CMDS) + cd $(XSLT_PATH); $(CMDS) \ + cd $(XSLTUTIL_PATH); $(CMDS) \ + cd $(XPATH_PATH); $(CMDS) diff --git a/mozilla/extensions/transformiix/source/main/transformiix.cpp b/mozilla/extensions/transformiix/source/main/transformiix.cpp index 7c12d555faa..0453a2b55bd 100644 --- a/mozilla/extensions/transformiix/source/main/transformiix.cpp +++ b/mozilla/extensions/transformiix/source/main/transformiix.cpp @@ -21,11 +21,11 @@ * Keith Visco, kvisco@ziplink.net * -- original author. * - * $Id: transformiix.cpp,v 1.3 2000-03-31 07:11:29 kvisco%ziplink.net Exp $ + * $Id: transformiix.cpp,v 1.4 2000-04-06 07:44:35 kvisco%ziplink.net Exp $ */ -#include "XSLProcessor.h" +#include "XSLTProcessor.h" //--------------/ //- Prototypes -/ @@ -47,11 +47,11 @@ void printUsage(); **/ int main(int argc, char** argv) { - XSLProcessor xslProcessor; + XSLTProcessor xsltProcessor; String copyright("(C) 1999 The MITRE Corporation, Keith Visco, and contributors"); - cout << xslProcessor.getAppName() << " "; - cout << xslProcessor.getAppVersion() << endl; + cout << xsltProcessor.getAppName() << " "; + cout << xsltProcessor.getAppVersion() << endl; cout << copyright <length()+1]; - ifstream xslInput(xslFilename->toCharArray(chars), ios::in); + //-- open XSLT file + chars = new char[xsltFilename->length()+1]; + ifstream xsltInput(xsltFilename->toCharArray(chars), ios::in); delete chars; - xslProcessor.process(xmlInput, xslInput, *resultOutput, documentBase); + xsltProcessor.process(xmlInput, xsltInput, *resultOutput, documentBase); } resultFileStream.close(); return 0; } //-- main void printHelp() { - cout << "The following flags are available for use with TransforMiiX -"; + cout << "The following flags are available for use with Transformiix -"; cout< diff --git a/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp b/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp new file mode 100644 index 00000000000..75c6c404083 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/AdditiveExpr.cpp @@ -0,0 +1,139 @@ +/* + * 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. + * + * $Id: AdditiveExpr.cpp,v 1.1 2000-04-06 07:44:37 kvisco%ziplink.net Exp $ + */ + +/** + * Represents a AdditiveExpr, an binary expression that + * performs an additive operation between it's lvalue and rvalue:
+ * + : addition + * - : subtraction + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:37 $ +**/ + +#include "Expr.h" + +/** + * Creates a new AdditiveExpr using the default operator (ADDITION) +**/ +AdditiveExpr::AdditiveExpr() { + this->op = ADDITION; + this->leftExpr = 0; + this->rightExpr = 0; +} //-- AdditiveExpr + +/** + * Creates a new AdditiveExpr using the given operator +**/ +AdditiveExpr::AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op) { + this->op = op; + this->leftExpr = leftExpr; + this->rightExpr = rightExpr; +} //-- AdditiveExpr + +AdditiveExpr::~AdditiveExpr() { + delete leftExpr; + delete rightExpr; +} //-- ~AdditiveExpr + +/** + * Sets the left side of this AdditiveExpr +**/ +void AdditiveExpr::setLeftExpr(Expr* leftExpr) { + this->leftExpr = leftExpr; +} //-- setLeftExpr + +/** + * Sets the right side of this AdditiveExpr +**/ +void AdditiveExpr::setRightExpr(Expr* rightExpr) { + this->rightExpr = rightExpr; +} //-- setRightExpr + +/** + * 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* AdditiveExpr::evaluate(Node* context, ContextState* cs) { + + + double rightDbl = Double::NaN; + ExprResult* exprRes = 0; + + if ( rightExpr ) { + exprRes = rightExpr->evaluate(context, cs); + if ( exprRes ) rightDbl = exprRes->numberValue(); + delete exprRes; + } + + double leftDbl = Double::NaN; + if ( leftExpr ) { + exprRes = leftExpr->evaluate(context, cs); + if ( exprRes ) leftDbl = exprRes->numberValue(); + delete exprRes; + } + + double result = 0; + + switch ( op ) { + case SUBTRACTION: + result = leftDbl - rightDbl; + break; + default: + result = leftDbl + rightDbl; + break; + } + return new NumberResult(result); +} //-- 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 AdditiveExpr::toString(String& str) { + + if ( leftExpr ) leftExpr->toString(str); + else str.append("null"); + + switch ( op ) { + case SUBTRACTION: + str.append(" - "); + break; + default: + str.append(" + "); + break; + } + if ( rightExpr ) rightExpr->toString(str); + else str.append("null"); + +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp new file mode 100644 index 00000000000..cf66e8c81e8 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/AttributeExpr.cpp @@ -0,0 +1,150 @@ +/* + * 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. + * + * $Id: AttributeExpr.cpp,v 1.1 2000-04-06 07:44:41 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * This class represents a ElementExpr as defined by the XSL + * Working Draft + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:41 $ +**/ + +//- Constructors -/ + +AttributeExpr::AttributeExpr() { + this->isWild = MB_FALSE; +} //-- AttributeExpr + +AttributeExpr::AttributeExpr(String& name) { + //-- copy name + this->name = name; + this->isWild = MB_FALSE; +} //-- AttributeExpr + +/** + * Destructor +**/ +AttributeExpr::~AttributeExpr() { +} //-- ~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) { + + NodeSet* nodeSet = new NodeSet(); + if ( !context ) return nodeSet; + NamedNodeMap* atts = context->getAttributes(); + if ( atts ) { + for (int i = 0; i < atts->getLength(); i++ ) { + Attr* attr = (Attr*)atts->item(i); + if ( isWild ) nodeSet->add(attr); + else { + String attName = attr->getName(); + if ( name.isEqual(attName) ){ + nodeSet->add(attr); + } + } + } + } + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double AttributeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + return 0.0; +} //-- getDefaultPriority + +/** + * Returns the name of this ElementExpr + * @return the name of this ElementExpr +**/ +const String& AttributeExpr::getName() { + return (const String&) this->name; +} //-- getName + +void AttributeExpr::setName(const String& name) { + this->name.clear(); + this->name.append(name); +} //-- setName + +void AttributeExpr::setWild(MBool isWild) { + this->isWild = isWild; +} //-- setWild + //-----------------------------/ + //- Methods from NodeExpr.cpp -/ +//-----------------------------/ + +/** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr +**/ +short AttributeExpr::getType() { + return NodeExpr::ATTRIBUTE_EXPR; +} //-- getType + +/** + * Determines whether this NodeExpr matches the given node within + * the given context +**/ +MBool AttributeExpr::matches(Node* node, Node* context, ContextState* cs) { + if ( (node) && (node->getNodeType() == Node::ATTRIBUTE_NODE) ) { + if ( isWild ) return MB_TRUE; + const String nodeName = ((Attr*)node)->getName(); + 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) { + dest.append('@'); + if (isWild) dest.append('*'); + else dest.append(this->name); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp b/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp new file mode 100644 index 00000000000..ca998cd0bd8 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/AttributeValueTemplate.cpp @@ -0,0 +1,99 @@ +/* + * 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. + * + * $Id: AttributeValueTemplate.cpp,v 1.1 2000-04-06 07:44:42 kvisco%ziplink.net Exp $ + */ + +/** + * AttributeValueTemplate + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:42 $ +**/ + +#include "Expr.h" + +/** + * Create a new AttributeValueTemplate +**/ +AttributeValueTemplate::AttributeValueTemplate() {}; + +/** + * Default destructor +**/ +AttributeValueTemplate::~AttributeValueTemplate() { + ListIterator* iter = expressions.iterator(); + while ( iter->hasNext() ) { + iter->next(); //advance iterator to allow remove + Expr* expr = (Expr*)iter->remove(); + delete expr; + } + delete iter; + +} //-- ~AttributeValueTemplate + +/** + * Adds the given Expr to this AttributeValueTemplate +**/ +void AttributeValueTemplate::addExpr(Expr* expr) { + if (expr) expressions.add(expr); +} //-- addExpr + +/** + * 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* AttributeValueTemplate::evaluate(Node* context, ContextState* cs) { + ListIterator* iter = expressions.iterator(); + String result; + while ( iter->hasNext() ) { + Expr* expr = (Expr*)iter->next(); + ExprResult* exprResult = expr->evaluate(context, cs); + exprResult->stringValue(result); + delete exprResult; + } + delete iter; + return new StringResult(result); +} //-- 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 AttributeValueTemplate::toString(String& str) { + ListIterator* iter = expressions.iterator(); + while ( iter->hasNext() ) { + str.append('{'); + Expr* expr = (Expr*)iter->next(); + expr->toString(str); + str.append('}'); + } + delete iter; +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp new file mode 100644 index 00000000000..d6f958c99d5 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/BasicNodeExpr.cpp @@ -0,0 +1,139 @@ +/* + * 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. + * + * $Id: BasicNodeExpr.cpp,v 1.1 2000-04-06 07:44:45 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:45 $ +**/ + +//- Constructors -/ + +/** + * Creates a new BasicNodeExpr, which matchs any Node +**/ +BasicNodeExpr::BasicNodeExpr() { + this->type = NodeExpr::NODE_EXPR; +} //-- BasicNodeExpr + +/** + * Creates a new BasicNodeExpr of the given type +**/ +BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType) { + this->type = nodeExprType; +} //-- BasicNodeExpr + +/** + * Destroys this NodeExpr +**/ +BasicNodeExpr::~BasicNodeExpr() {}; + + //------------------/ + //- 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* BasicNodeExpr::evaluate(Node* context, ContextState* cs) { + NodeSet* nodeSet = new NodeSet(); + if ( !context ) return nodeSet; + NodeList* nl = context->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + if (matches(node, context, cs)) nodeSet->add(node); + } + return nodeSet; +} //-- evaluate + + //-----------------------------/ + //- Methods from NodeExpr.cpp -/ +//-----------------------------/ + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double BasicNodeExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + return -0.5; +} //-- getDefaultPriority + +/** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr +**/ +short BasicNodeExpr::getType() { + return type; +} //-- getType + +/** + * 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); + default: //-- node() + break; + } + 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()"); + 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 new file mode 100644 index 00000000000..5ab27bab3cd --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/BooleanExpr.cpp @@ -0,0 +1,134 @@ +/* + * 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. + * + * $Id: BooleanExpr.cpp,v 1.1 2000-04-06 07:44:46 kvisco%ziplink.net Exp $ + */ + + +/** + * Represents a BooleanExpr, a binary expression that + * performs a boolean operation between it's lvalue and rvalue:
+ * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:46 $ +**/ + +#include "Expr.h" + +/** + * Creates a new BooleanExpr using the default operator (AND) +**/ +BooleanExpr::BooleanExpr() { + this->op = AND; + this->leftExpr = 0; + this->rightExpr = 0; +} //-- BooleanExpr + +/** + * Creates a new BooleanExpr using the given operator +**/ +BooleanExpr::BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op) { + this->op = op; + this->leftExpr = leftExpr; + this->rightExpr = rightExpr; +} //-- BooleanExpr + +BooleanExpr::~BooleanExpr() { + delete leftExpr; + delete rightExpr; +} //-- ~BooleanExpr + +/** + * Sets the left side of this AdditiveExpr +**/ +void BooleanExpr::setLeftExpr(Expr* leftExpr) { + this->leftExpr = leftExpr; +} //-- setLeftExpr + +/** + * Sets the right side of this AdditiveExpr +**/ +void BooleanExpr::setRightExpr(Expr* rightExpr) { + this->rightExpr = rightExpr; +} //-- setRightExpr + +/** + * 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* BooleanExpr::evaluate(Node* context, ContextState* cs) { + + + MBool lval = MB_FALSE; + ExprResult* exprRes = 0; + if ( leftExpr ) { + exprRes = leftExpr->evaluate(context, cs); + if ( exprRes ) lval = exprRes->booleanValue(); + delete exprRes; + } + + + //-- check left expression for early decision + if (( op == OR ) && (lval)) return new BooleanResult(MB_TRUE); + else if (!lval) return new BooleanResult(MB_FALSE); + + + MBool rval = MB_FALSE; + if ( rightExpr ) { + exprRes = rightExpr->evaluate(context, cs); + if ( exprRes ) rval = exprRes->booleanValue(); + delete exprRes; + } + //-- just use rval, since we already checked lval + return new BooleanResult(rval); + +} //-- 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 BooleanExpr::toString(String& str) { + + if ( leftExpr ) leftExpr->toString(str); + else str.append("null"); + + switch ( op ) { + case OR: + str.append(" or "); + break; + default: + str.append(" and "); + break; + } + if ( rightExpr ) rightExpr->toString(str); + else str.append("null"); + +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp new file mode 100644 index 00000000000..bed9b6358f9 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/BooleanFunctionCall.cpp @@ -0,0 +1,103 @@ +/* + * 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. + * + * $Id: BooleanFunctionCall.cpp,v 1.1 2000-04-06 07:44:53 kvisco%ziplink.net Exp $ + */ + +#include "FunctionLib.h" + +/** + * Creates a default BooleanFunctionCall, which always evaluates to False + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:44:53 $ +**/ +BooleanFunctionCall::BooleanFunctionCall() : FunctionCall(XPathNames::FALSE_FN) { + this->type = FALSE; +} //-- BooleanFunctionCall + +/** + * Creates a BooleanFunctionCall of the given type +**/ +BooleanFunctionCall::BooleanFunctionCall(short type) : FunctionCall() +{ + switch ( type ) { + case BOOLEAN : + FunctionCall::setName(XPathNames::BOOLEAN_FN); + break; + case NOT : + FunctionCall::setName(XPathNames::NOT_FN); + break; + case TRUE : + FunctionCall::setName(XPathNames::TRUE_FN); + break; + default: + FunctionCall::setName(XPathNames::FALSE_FN); + break; + } + this->type = type; +} //-- BooleanFunctionCall + +/** + * 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* BooleanFunctionCall::evaluate(Node* context, ContextState* cs) { + + BooleanResult* result = new BooleanResult(); + ListIterator* iter = params.iterator(); + int argc = params.getLength(); + Expr* param = 0; + String err; + + + switch ( type ) { + case BOOLEAN : + if ( requireParams(1,1,cs) ) { + param = (Expr*)iter->next(); + ExprResult* exprResult = param->evaluate(context, cs); + result->setValue(exprResult->booleanValue()); + delete exprResult; + } + break; + case NOT : + if ( requireParams(1,1,cs) ) { + param = (Expr*)iter->next(); + ExprResult* exprResult = param->evaluate(context, cs); + result->setValue(!exprResult->booleanValue()); + delete exprResult; + } + break; + case TRUE : + result->setValue(MB_TRUE); + break; + default: + result->setValue(MB_FALSE); + break; + } + delete iter; + return result; +} //-- evaluate + diff --git a/mozilla/extensions/transformiix/source/xpath/BooleanResult.cpp b/mozilla/extensions/transformiix/source/xpath/BooleanResult.cpp new file mode 100644 index 00000000000..37aa1fd0ea8 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/BooleanResult.cpp @@ -0,0 +1,97 @@ +/* + * 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. + * + * $Id: BooleanResult.cpp,v 1.1 2000-04-06 07:45:19 kvisco%ziplink.net Exp $ + */ + +/** + * Boolean Expression result + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:19 $ +**/ + +#include "ExprResult.h" + +/** + * Default Constructor +**/ +BooleanResult::BooleanResult() { + value = MB_FALSE; +} //-- BooleanResult + +BooleanResult::BooleanResult(const BooleanResult& boolResult) { + this->value = boolResult.getValue(); +} //-- BooleanResult + +/** + * Creates a new BooleanResult with the value of the given MBool parameter + * @param boolean the MBool to use for initialization of this BooleanResult's value +**/ +BooleanResult::BooleanResult(MBool boolean) { + this->value = boolean; +} //-- BooleanResult + +/** + * Returns the value of this BooleanResult + * @return the value of this BooleanResult +**/ +MBool BooleanResult::getValue() const { + return this->value; +} //-- getValue + +/** + * Sets the value of this BooleanResult + * @param boolean the MBool to use for this BooleanResult's value +**/ +void BooleanResult::setValue(MBool boolean) { + this->value = boolean; +} //-- setValue + +/** + * Sets the value of this BooleanResult + * @param boolResult the BooleanResult to use for setting this BooleanResult's value +**/ +void BooleanResult::setValue(const BooleanResult& boolResult) { + this->value = boolResult.getValue(); +} //-- setValue + +/* + * Virtual Methods from ExprResult +*/ + +short BooleanResult::getResultType() { + return ExprResult::BOOLEAN; +} //-- getResultType + +void BooleanResult::stringValue(String& str) { + if ( value ) str.append("true"); + else str.append("false"); +} //-- toString + +MBool BooleanResult::booleanValue() { + return this->value; +} //-- toBoolean + +double BooleanResult::numberValue() { + return ( value ) ? 1.0 : 0.0; +} //-- toNumber diff --git a/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp b/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp new file mode 100644 index 00000000000..3012af7d74c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ElementExpr.cpp @@ -0,0 +1,144 @@ +/* + * 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. + * + * $Id: ElementExpr.cpp,v 1.1 2000-04-06 07:45:22 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * This class represents a ElementExpr as defined by XPath 1.0 + * proposed recommendation + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:22 $ +**/ + +//- Constructors -/ + +ElementExpr::ElementExpr() { + //-- do nothing +} //-- ElementExpr + +ElementExpr::ElementExpr(String& name) { + //-- copy name + this->name = name; +} //-- ElementExpr + +/** + * Destructor +**/ +ElementExpr::~ElementExpr() { +} //-- ~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) { + + NodeSet* nodeSet = new NodeSet(); + + if ( !context ) return nodeSet; + + NodeList* nl = context->getChildNodes(); + + for (int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + if ( node->getNodeType() == Node::ELEMENT_NODE ) { + String tagName = node->getNodeName(); + if ( name.isEqual(tagName) ){ + nodeSet->add(node); + } + } + } + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double ElementExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + return 0.0; +} //-- getDefaultPriority + +/** + * Returns the name of this ElementExpr + * @return the name of this ElementExpr +**/ +const String& ElementExpr::getName() { + return (const String&) this->name; +} //-- getName + +void ElementExpr::setName(const String& name) { + this->name.clear(); + this->name.append(name); +} //-- setName + + + //-----------------------------/ + //- Methods from NodeExpr.cpp -/ +//-----------------------------/ + +/** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr +**/ +short ElementExpr::getType() { + return NodeExpr::ELEMENT_EXPR; +} //-- getType + +/** + * Determines whether this NodeExpr matches the given node within + * the given context +**/ +MBool ElementExpr::matches(Node* node, Node* context, ContextState* cs) { + if ( node) { + const String nodeName = node->getNodeName(); + 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 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 new file mode 100644 index 00000000000..b804bcc4e3a --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ErrorFunctionCall.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * + * $Id: ErrorFunctionCall.cpp,v 1.1 2000-04-06 07:45:23 kvisco%ziplink.net Exp $ + */ + +#include "FunctionLib.h" + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:23 $ +**/ + +/** + * 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.h b/mozilla/extensions/transformiix/source/xpath/Expr.h new file mode 100644 index 00000000000..49642e2278f --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/Expr.h @@ -0,0 +1,1509 @@ +/* + * 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. + * Larry Fitzpatick, OpenText, lef@opentext.com + * -- 19990806 + * - changed constant short declarations in many of the classes + * with enumerations, commented with //--LF + * + * $Id: Expr.h,v 1.1 2000-04-06 07:45:23 kvisco%ziplink.net Exp $ + */ + +/** + * XSL expression class definitions. + * Much of this code was ported from XSL:P.
+ * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:23 $ +**/ + +#ifndef TRANSFRMX_EXPR_H +#define TRANSFRMX_EXPR_H + +#include +#include "String.h" +#include "ErrorObserver.h" +#include "NodeSet.h" +#include "List.h" +#include "Stack.h" +#include "dom.h" +#include "ExprResult.h" +#include "baseutils.h" +#include "MITREObject.h" +#include "primitives.h" + +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; + + /** + * handles finding the parent of a node, since in DOM some + * nodes such as Attribute Nodes do not have parents + * @param node the Node to search for the parent of + * @return the parent of the given node, or null + **/ + virtual Node* getParentNode(Node* node) = 0; + + + virtual MBool isStripSpaceAllowed(Node* node) = 0; + + + /** + * Sorts the given NodeSet by DocumentOrder. + * @param nodes the NodeSet to sort + *
+ * Note: I will be moving this functionality elsewhere soon + **/ + virtual void sortByDocumentOrder(NodeSet* nodes) = 0; + +}; //-- ContextState + +/** + * A Base Class for all XSL Expressions +**/ +class Expr : public MITREObject { + +public: + + /** + * Virtual destructor, important for subclasses + **/ + virtual ~Expr() {}; + + /** + * 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) = 0; + + /** + * 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) = 0; + +}; //-- Expr + + +/** + * A base Pattern class +**/ +class Pattern { + +public: + + /** + * Virtual destructor, important for subclasses + **/ + virtual ~Pattern() {}; + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0; + + /** + * Determines whether this Pattern matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs) = 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 Expressions. + * @return the String representation of this Pattern. + **/ + virtual void toString(String& dest) = 0; + +}; //-- Pattern + + +/** + * A Base class for all Expressions and Patterns +**/ +class PatternExpr : + public Expr, + public Pattern +{ + +public: + + /** + * Virtual destructor, important for subclasses + **/ + virtual ~PatternExpr() {}; + + /** + * 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) = 0; + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0; + + /** + * Determines whether this PatternExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs) = 0; + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest) = 0; + +}; //-- PatternExpr + +/** + * Represents an AttributeValueTemplate +**/ +class AttributeValueTemplate: public Expr { + +public: + + AttributeValueTemplate(); + + virtual ~AttributeValueTemplate(); + + /** + * Adds the given Expr to this AttributeValueTemplate + **/ + void addExpr(Expr* expr); + + /** + * 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: + List expressions; +}; + + +/** + * This class represents a NodeTestExpr as defined by the XSL + * Working Draft +**/ +class NodeExpr : public PatternExpr { + +public: + + //-- NodeExpr Types + //-- LF - changed from const short to enum + enum NodeExprType { + ATTRIBUTE_EXPR = 1, + ELEMENT_EXPR, + TEXT_EXPR, + COMMENT_EXPR, + PI_EXPR, + NODE_EXPR, + WILD_CARD, + ROOT_EXPR + }; + + virtual ~NodeExpr() {}; + + //------------------/ + //- Public Methods -/ + //------------------/ + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs) = 0; + + /** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr + **/ + virtual short getType() = 0; + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs) = 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 Expressions. + * @return the String representation of this Pattern. + **/ + 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(); + AttributeExpr(String& name); + virtual ~AttributeExpr(); + + void setWild(MBool isWild); + + /** + * Returns the name of this AttributeExpr + * @return the name of this AttributeExpr + **/ + const String& getName(); + + /** + * Sets the name of this AttributeExpr + * @param name the name of the element that this AttributeExpr matches + **/ + void setName(const String& name); + + //-----------------------------------/ + //- Method signatures from NodeExpr -/ + //-----------------------------------/ + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * 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 type of this NodeExpr + * @return the type of this NodeExpr + **/ + short getType(); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * 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. + **/ + virtual void toString(String& dest); + +private: + + String name; + MBool isWild; + +}; //-- AttributeExpr + +/** + * +**/ +class BasicNodeExpr : public NodeExpr { + +public: + + //------------------/ + //- Public Methods -/ + //------------------/ + + /** + * Creates a new BasicNodeExpr of type NodeExpr::NODE_EXPR, which matches + * any node + **/ + BasicNodeExpr(); + + /** + * Creates a new BasicNodeExpr of the given type + **/ + BasicNodeExpr::BasicNodeExpr(NodeExpr::NodeExprType nodeExprType); + + /** + * Destroys this BasicNodeExpr + **/ + virtual ~BasicNodeExpr(); + + //-----------------------------------/ + //- Method signatures from NodeExpr -/ + //-----------------------------------/ + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * 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 type of this NodeExpr + * @return the type of this NodeExpr + **/ + short getType(); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * 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. + **/ + virtual void toString(String& dest); + +private: + NodeExpr::NodeExprType type; +}; //-- BasicNodeExpr + +/** + * This class represents a ElementExpr as defined by the XSL + * Working Draft +**/ +class ElementExpr : public NodeExpr { + +public: + + //------------------/ + //- Public Methods -/ + //------------------/ + + ElementExpr(); + ElementExpr(String& name); + virtual ~ElementExpr(); + + /** + * Returns the name of this ElementExpr + * @return the name of this ElementExpr + **/ + const String& getName(); + + /** + * Sets the name of this ElementExpr + * @param name the name of the element that this ElementExpr matches + **/ + void setName(const String& name); + + //-----------------------------------/ + //- Method signatures from NodeExpr -/ + //-----------------------------------/ + + /** + * 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 default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr + **/ + short getType(); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * 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. + **/ + virtual void toString(String& dest); + +private: + + String name; + +}; //-- ElementExpr + +/** + * This class represents a IdentityExpr, which only matches a node + * if it is equal to the context node +**/ +class IdentityExpr : public Expr { + +public: + + //------------------/ + //- 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 + **/ + virtual ExprResult* evaluate(Node* context, ContextState* cs); + + /** + * 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. + **/ + virtual void toString(String& dest); + +}; //-- IdentityExpr + +/** + * This class represents a ParentExpr, which only selects a node + * if it is equal to the context node's parent +**/ +class ParentExpr : public Expr { + +public: + + //------------------/ + //- 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 + **/ + virtual ExprResult* evaluate(Node* context, ContextState* cs); + + + /** + * 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. + **/ + virtual void toString(String& dest); + +}; //-- ParentExpr + +/** + * This class represents a TextExpr, which only matches any text node +**/ +class TextExpr : public NodeExpr { + +public: + + //------------------/ + //- 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 + **/ + virtual ExprResult* evaluate(Node* context, ContextState* cs); + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr + **/ + virtual short getType(); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + + /** + * 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. + **/ + virtual void toString(String& dest); + +}; //-- TextExpr + +/** + * This class represents a WildCardExpr as defined by the XSL + * Working Draft +**/ +class WildCardExpr : public NodeExpr { + +public: + + //------------------/ + //- 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 + **/ + virtual ExprResult* evaluate(Node* context, ContextState* cs); + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr + **/ + virtual short getType(); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + + /** + * 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. + **/ + virtual void toString(String& dest); + +}; //-- WildCardExpr + + +/** + * Represents an ordered list of Predicates, + * for use with Step and Filter Expressions +**/ +class PredicateList { + +public: + + /** + * Creates a new PredicateList + **/ + PredicateList(); + /** + * Destructor, will delete all Expressions in the list, so remove + * any you may need + **/ + virtual ~PredicateList(); + + /** + * Adds the given Expr to the list + * @param expr the Expr to add to the list + **/ + void add(Expr* expr); + + + void evaluatePredicates(NodeSet* nodes, ContextState* cs); + + /** + * returns true if this predicate list is empty + **/ + MBool isEmpty(); + + /** + * Removes the given Expr from the list + * @param expr the Expr to remove from the list + **/ + Expr* remove(Expr* expr); + + /** + * Returns the String representation of this PredicateList. + * @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 PredicateList. + **/ + virtual void toString(String& dest); + +private: + //-- list of predicates + List predicates; +}; //-- PredicateList + +class LocationStep : public PredicateList, public PatternExpr { + +public: + + // Axis Identifier Types + //-- LF changed from static const short to enum + enum _LocationStepType { + ANCESTOR_AXIS = 0, + ANCESTOR_OR_SELF_AXIS, + ATTRIBUTE_AXIS, + CHILD_AXIS, + DESCENDANT_AXIS, + DESCENDANT_OR_SELF_AXIS, + FOLLOWING_AXIS, + FOLLOWING_SIBLING_AXIS, + NAMESPACE_AXIS, + PARENT_AXIS, + PRECEDING_AXIS, + PRECEDING_SIBLING_AXIS, + SELF_AXIS + }; + + + /** + * Creates a new LocationStep using the default Axis Identifier and no + * NodeExpr (which matches nothing) + **/ + LocationStep(); + + /** + * Creates a new LocationStep using the default Axis Identifier and + * the given NodeExpr + * @param nodeExpr the NodeExpr to use when matching Nodes + **/ + LocationStep(NodeExpr* nodeExpr); + + /** + * 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(NodeExpr* nodeExpr, short axisIdentifier); + + /** + * Destructor, will delete all predicates and the given NodeExpr + **/ + virtual ~LocationStep(); + + /** + * Sets the Axis Identifier for this LocationStep + * @param axisIdentifier the Axis in which to search for nodes + **/ + void setAxisIdentifier(short axisIdentifier); + + /** + * Sets the NodeExpr of this LocationStep for use when matching nodes + * @param nodeExpr the NodeExpr to use when matching nodes + **/ + void setNodeExpr(NodeExpr* nodeExpr); + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ + //------------------------------------/ + + /** + * 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 default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Determines whether this PatternExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest); + +private: + + NodeExpr* nodeExpr; + short axisIdentifier; + + void fromDescendants(Node* context, ContextState* cs, NodeSet* nodes); + +}; //-- LocationStep + + +class FilterExpr : public PredicateList, public PatternExpr { + +public: + + /** + * Creates a new FilterExpr using the default no default Expr + * (which evaluates to nothing) + **/ + FilterExpr(); + + /** + * Creates a new FilterExpr using the given Expr + * @param expr the Expr to use for evaluation + **/ + FilterExpr(Expr* expr); + + /** + * Destructor, will delete all predicates and the given Expr + **/ + virtual ~FilterExpr(); + + /** + * Sets the Expr of this FilterExpr for evaluation + * @param expr the Expr to use for evaluation + **/ + void setExpr(Expr* expr); + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ + //------------------------------------/ + + /** + * 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 default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Determines whether this PatternExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest); + +private: + + Expr* expr; + +}; //-- FilterExpr + + +class NumberExpr : public Expr { + +public: + + NumberExpr(); + NumberExpr(double dbl); + ~NumberExpr(); + + /** + * 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: + + NumberResult numberResult; +}; + +/** + * Represents a String expression +**/ +class StringExpr : public Expr { + +public: + + StringExpr(); + StringExpr(String& value); + StringExpr(const String& value); + ~StringExpr(); + + /** + * 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: + + String value; +}; //-- StringExpr + + +/** + * Represents an AdditiveExpr, a binary expression that + * performs an additive operation between it's lvalue and rvalue:
+ * + : add + * - : subtract +**/ +class AdditiveExpr : public Expr { + +public: + + //-- AdditiveExpr Types + //-- LF, changed from static const short to enum + enum _AdditiveExprType { ADDITION = 1, SUBTRACTION }; + + AdditiveExpr(); + AdditiveExpr(Expr* leftExpr, Expr* rightExpr, short op); + ~AdditiveExpr(); + + /** + * Sets the left side of this AdditiveExpr + **/ + void setLeftExpr(Expr* leftExpr); + + /** + * Sets the right side of this AdditiveExpr + **/ + void setRightExpr(Expr* rightExpr); + + + /** + * 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: + short op; + Expr* leftExpr; + Expr* rightExpr; +}; //-- AdditiveExpr + +/** + * Represents a BooleanExpr, a binary expression that + * performs a boolean operation between it's lvalue and rvalue:
+**/ +class BooleanExpr : public Expr { + +public: + + //-- BooleanExpr Types + enum _BooleanExprType { AND = 1, OR }; + + BooleanExpr(); + BooleanExpr(Expr* leftExpr, Expr* rightExpr, short op); + ~BooleanExpr(); + + /** + * Sets the left side of this AdditiveExpr + **/ + void setLeftExpr(Expr* leftExpr); + + /** + * Sets the right side of this AdditiveExpr + **/ + void setRightExpr(Expr* rightExpr); + + + /** + * 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: + short op; + Expr* leftExpr; + Expr* rightExpr; +}; //-- BooleanExpr + +/** + * Represents a MultiplicativeExpr, a binary expression that + * performs a multiplicative operation between it's lvalue and rvalue:
+ * * : multiply + * mod : modulus + * div : divide + * +**/ +class MultiplicativeExpr : public Expr { + +public: + + //-- MultiplicativeExpr Types + //-- LF, changed from static const short to enum + enum _MultiplicativeExprType { DIVIDE = 1, MULTIPLY, MODULUS }; + + MultiplicativeExpr(); + MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op); + ~MultiplicativeExpr(); + + /** + * Sets the left side of this MultiplicativeExpr + **/ + void setLeftExpr(Expr* leftExpr); + + /** + * Sets the right side of this MultiplicativeExpr + **/ + void setRightExpr(Expr* rightExpr); + + + /** + * 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: + short op; + Expr* leftExpr; + Expr* rightExpr; +}; //-- MultiplicativeExpr + +/** + * Represents a RelationalExpr, an expression that compares it's lvalue + * to it's rvalue using:
+ * = : equal to + * < : less than + * > : greater than + * <= : less than or equal to + * >= : greater than or equal to + * +**/ +class RelationalExpr : public Expr { + +public: + + //-- RelationalExpr Types + //-- LF, changed from static const short to enum + enum _RelationalExprType { + EQUAL = 1, + NOT_EQUAL, + LESS_THAN, + GREATER_THAN, + LESS_OR_EQUAL, + GREATER_OR_EQUAL + }; + + RelationalExpr(); + RelationalExpr(Expr* leftExpr, Expr* rightExpr, short op); + ~RelationalExpr(); + + /** + * 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: + short op; + Expr* leftExpr; + Expr* rightExpr; + + MBool compareResults(ExprResult* left, ExprResult* right); +}; //-- RelationalExpr + +/** + * VariableRefExpr
+ * Represents a variable reference ($refname) +**/ +class VariableRefExpr : public Expr { + +public: + + VariableRefExpr(); + VariableRefExpr(const String& name); + VariableRefExpr(String& name); + ~VariableRefExpr(); + + /** + * Sets the name of the variable of reference + **/ + void setName(const String& name); + + /** + * 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: + String name; + +}; //-- VariableRefExpr + +/** + * Represents a PathExpr +**/ +class PathExpr : public PatternExpr { + +public: + + //-- Path Operators + //-- RELATIVE_OP is the default + //-- LF, changed from static const short to enum + enum _PathOperator { ANCESTOR_OP=1, PARENT_OP, RELATIVE_OP} ; + + /** + * Creates a new PathExpr + **/ + PathExpr(); + + /** + * Destructor, will delete all Pattern Expressions + **/ + virtual ~PathExpr(); + + /** + * Adds the PatternExpr to this PathExpr + * @param expr the Expr to add to this PathExpr + * @param index the index at which to add the given Expr + **/ + void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp); + + /** + * Adds the PatternExpr to this PathExpr + * @param expr the Expr to add to this PathExpr + **/ + void addPatternExpr(PatternExpr* expr, short ancestryOp); + + virtual MBool isAbsolute(); + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ + //------------------------------------/ + + /** + * 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 default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Determines whether this PatternExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest); + +private: + + struct PathExprItem { + PatternExpr* pExpr; + short ancestryOp; + }; + + List expressions; + + /** + * Selects from the descendants of the context node + * all nodes that match the PatternExpr + * -- this will be moving to a Utility class + **/ + void fromDescendants(PatternExpr* pExpr, + Node* context, + ContextState* cs, + NodeSet* nodes); + +}; //-- PathExpr + +/** + * This class represents a RootExpr, which only matches the Document node +**/ +class RootExpr : public PathExpr { + +public: + + //------------------/ + //- 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 + **/ + virtual ExprResult* evaluate(Node* context, ContextState* cs); + + virtual MBool isAbsolute(); + + /** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Determines whether this NodeExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest); + + +}; //-- RootExpr + +/** + * Represents a UnionExpr +**/ +class UnionExpr : public PatternExpr { + +public: + + /** + * Creates a new UnionExpr + **/ + UnionExpr(); + + /** + * Destructor, will delete all Path Expressions + **/ + virtual ~UnionExpr(); + + /** + * Adds the PathExpr to this UnionExpr + * @param expr the Expr to add to this UnionExpr + **/ + void addPathExpr(PathExpr* expr); + + /** + * Adds the PathExpr to this UnionExpr at the specified index + * @param expr the Expr to add to this UnionExpr + **/ + void addPathExpr(int index, PathExpr* expr); + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ + //------------------------------------/ + + /** + * 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 default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. + **/ + virtual double getDefaultPriority(Node* node, Node* context, ContextState* cs); + + /** + * Determines whether this PatternExpr matches the given node within + * the given context + **/ + virtual MBool matches(Node* node, Node* context, ContextState* cs); + + /** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. + **/ + virtual void toString(String& dest); + +private: + + List expressions; + +}; //-- UnionExpr + +/* */ +#endif + + diff --git a/mozilla/extensions/transformiix/source/xpath/ExprLexer.cpp b/mozilla/extensions/transformiix/source/xpath/ExprLexer.cpp new file mode 100644 index 00000000000..932a3c76518 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ExprLexer.cpp @@ -0,0 +1,698 @@ +/* + * 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. + * -- fixed bug with '<=' and '>=' reported by Bob Miller + * + * Bob Miller, Oblix Inc., kbob@oblix.com + * -- fixed bug with single quotes inside double quotes + * + * $Id: ExprLexer.cpp,v 1.1 2000-04-06 07:45:26 kvisco%ziplink.net Exp $ + */ + +/** + * Lexical analyzer for XPath expressions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:26 $ +**/ + +#include +#include "ExprLexer.h" + + //---------------------------/ + //- Implementation of Token -/ +//---------------------------/ + + +/** + * Default constructor for Token +**/ +Token::Token() { + this->type =0; +} //-- Token; + +/** + * Constructor for Token + * @param type, the type of Token being represented +**/ +Token::Token(short type) { + this->type = type; +} //-- Token; + +/** + * Constructor for Token + * @param value the value of this Token + * @param type, the type of Token being represented +**/ +Token::Token(const String& value, short type) { + this->type = type; + //-- make copy of value String + this->value = value; +} //-- Token + +Token::Token(UNICODE_CHAR uniChar, short type) { + this->type = type; + this->value.append(uniChar); +} //-- Token + +/** + * Copy Constructor +**/ +Token::Token(const Token& token) { + this->type = token.type; + this->value = token.value; +} //-- Token + +/** + * Destructor for Token +**/ +Token::~Token() { + //-- currently nothing is needed +} //-- ~Token + + + //--------------------------------/ + //- Implementation of ExprLexer -/ +//-------------------------------/ + +/* + * Complex Tokens +*/ +//-- Nodetype tokens +const String ExprLexer::COMMENT = "comment"; +const String ExprLexer::NODE = "node"; +const String ExprLexer::PI = "processing-instruction"; +const String ExprLexer::TEXT = "text"; + +//-- boolean +const String ExprLexer::AND = "and"; +const String ExprLexer::OR = "or"; + +//-- multiplicative operators +const String ExprLexer::MODULUS = "mod"; +const String ExprLexer::DIVIDE = "div"; + + +/** + * The set of a XSL Expression Tokens +**/ +const Token ExprLexer::TOKENS[] = { + + //-- Nodetype tokens + Token(ExprLexer::COMMENT, Token::COMMENT), + Token(ExprLexer::NODE, Token::NODE), + Token(ExprLexer::PI, Token::PI), + Token(ExprLexer::TEXT, Token::TEXT), + //-- boolean operators + Token(ExprLexer::AND, Token::AND_OP), + Token(ExprLexer::OR, Token::OR_OP), + + //-- multiplicative operators + Token(ExprLexer::MODULUS, Token::MODULUS_OP), + Token(ExprLexer::DIVIDE, Token::DIVIDE_OP) +}; + +const short ExprLexer::NUMBER_OF_TOKENS = 8; + + //---------------/ + //- Contructors -/ +//---------------/ + +/** + * Creates a new ExprLexer using the given String +**/ +ExprLexer::ExprLexer(const String& pattern) { + + firstItem = 0; + lastItem = 0; + tokenCount = 0; + prevToken = 0; + parse(pattern); + currentItem = firstItem; +} //-- ExprLexer + +/** + * Destroys this instance of an ExprLexer +**/ +ExprLexer::~ExprLexer() { + //-- delete tokens + + //cout << "~ExprLexer() - start"<next; + //cout << "deleting token: " << currentItem->token->value << endl; + delete currentItem->token; + delete currentItem; + currentItem = temp; + } + //cout << "~ExprLexer() - done"<next; + } + return c; +} //-- countRemainingTokens + + +MBool ExprLexer::hasMoreTokens() { + return (MBool) ( currentItem ); +} //-- hasMoreTokens + +Token* ExprLexer::nextToken() { + if ( currentItem ) { + Token* token = currentItem->token; + currentItem = currentItem->next; + return token; + } + return 0; +} //-- nextToken + +void ExprLexer::pushBack() { + if ( !currentItem ) { + currentItem = lastItem; + } + else currentItem = currentItem->previous; +} //-- pushBack + +/* +Token* ExprLexer::lastToken() { + if (lastItem) { + return lastItem->token; + } + return 0; +} //-- lastToken +*/ + +Token* ExprLexer::peek() { + Token* token = 0; + TokenListItem* tlItem = currentItem; + if (tlItem) token = tlItem->token; + return token; +} //-- peek + +Token* ExprLexer::lookAhead(int offset) { + Token* token = 0; + TokenListItem* tlItem = currentItem; + //-- advance to proper offset + for ( int i = 0; i < offset; i++ ) + if ( tlItem ) tlItem = currentItem->next; + + if (tlItem) token = tlItem->token; + return token; +} //-- lookAhead + +void ExprLexer::addToken(Token* token) { + TokenListItem* tlItem = new TokenListItem; + tlItem->token = token; + tlItem->next = 0; + if (lastItem) { + tlItem->previous = lastItem; + lastItem->next = tlItem; + } + if (!firstItem) firstItem = tlItem; + lastItem = tlItem; + prevToken = token; + ++tokenCount; +} //-- addToken + +/** + * Returns true if the given character represents an Alpha letter +**/ +MBool ExprLexer::isAlphaChar(Int32 ch) { + if ((ch >= 'a' ) && (ch <= 'z' )) return MB_TRUE; + if ((ch >= 'A' ) && (ch <= 'Z' )) return MB_TRUE; + return MB_FALSE; +} //-- isAlphaChar + +/** + * Returns true if the given character represents a numeric letter (digit) +**/ +MBool ExprLexer::isDigit(Int32 ch) { + if ((ch >= '0') && (ch <= '9')) return MB_TRUE; + return MB_FALSE; +} //-- isDigit + +/** + * Returns true if the given character is an allowable QName character +**/ +MBool ExprLexer::isNCNameChar(Int32 ch) { + if (isDigit(ch) || isAlphaChar(ch)) return MB_TRUE; + return (MBool) ((ch == '.') ||(ch == '_') || (ch == '-')); +} //-- isNCNameChar + +/** + * Returns true if the given character is an allowable NCName character +**/ +MBool ExprLexer::isQNameChar(Int32 ch) { + return (MBool) (( ch == ':') || isNCNameChar(ch)); +} //-- isQNameChar + +/** + * Returns true if the given String is a valid XML QName +**/ +MBool ExprLexer::isValidQName(String& name) { + + int size = name.length(); + if ( size == 0 ) return MB_FALSE; + else if ( !isAlphaChar(name.charAt(0))) return MB_FALSE; + else { + for ( int i = 1; i < size; i++) { + if ( ! isQNameChar(name.charAt(i))) return MB_FALSE; + } + } + return MB_TRUE; +} //-- isValidQName + +MBool ExprLexer::isOperatorToken(Token* token) { + if ( !token ) return MB_FALSE; + switch ( token->type ) { + //-- boolean operators + case Token::AND_OP: + case Token::OR_OP: + //-- relational operators + case Token::EQUAL_OP: + case Token::NOT_EQUAL_OP: + case Token::LESS_THAN_OP: + case Token::GREATER_THAN_OP: + case Token::LESS_OR_EQUAL_OP: + case Token::GREATER_OR_EQUAL_OP: + //-- additive operators + case Token::ADDITION_OP: + case Token::SUBTRACTION_OP: + //-- multiplicative operators + case Token::DIVIDE_OP: + case Token::MODULUS_OP: + case Token::MULTIPLY_OP: + return MB_TRUE; + default: + break; + } + + return MB_FALSE; +} //-- isOperatorToken + +MBool ExprLexer::matchDelimiter(UNICODE_CHAR ch) { + + short tokenType = 0; + MBool addChar = MB_TRUE; + switch (ch) { + case FORWARD_SLASH : + tokenType = Token::PARENT_OP; + break; + case L_PAREN : + tokenType = Token::L_PAREN; + break; + case R_PAREN : + tokenType = Token::R_PAREN; + break; + case L_BRACKET : + tokenType = Token::L_BRACKET; + break; + case R_BRACKET : + tokenType = Token::R_BRACKET; + break; + case L_ANGLE : + tokenType = Token::LESS_THAN_OP; + break; + case R_ANGLE : + tokenType = Token::GREATER_THAN_OP; + break; + case COMMA : + tokenType = Token::COMMA; + break; + case PERIOD : + tokenType = Token::SELF_NODE; + break; + case EQUAL : + tokenType = Token::EQUAL_OP; + break; + case PLUS : + tokenType = Token::ADDITION_OP; + break; + case HYPHEN : + tokenType = Token::SUBTRACTION_OP; + break; + case VERT_BAR: + tokenType = Token::UNION_OP; + break; + case ASTERIX: + tokenType = Token::WILD_CARD; + break; + case AT_SIGN: + tokenType = Token::AT_SIGN; + break; + case DOLLAR_SIGN: + tokenType = Token::VAR_REFERENCE; + addChar = MB_FALSE; + break; + default: + return MB_FALSE;; + } + Token* token = 0; + if ( addChar ) token = new Token(ch, tokenType); + else token = new Token(tokenType); + + addToken(token); + return MB_TRUE; +} //-- matchDelimiter + +/** + * Returns true if the value of the given String matches + * an OperatorName +**/ +MBool ExprLexer::matchesOperator(String& buffer) { + + int index = 0; + while (index < NUMBER_OF_TOKENS) { + Token tok = TOKENS[index++]; + if ( tok.value.isEqual(buffer) ) { + if (isOperatorToken( &tok )) return MB_TRUE; + } + } + return MB_FALSE; + +} //-- matchesOperator + +/** + * Matches the given String to the appropriate Token + * @param buffer the current StringBuffer representing the value of the Token + * @param ch, the current delimiter token +**/ +void ExprLexer::matchToken(String& buffer, UNICODE_CHAR ch) { + + if ( buffer.length() == 0) return; + + Token* match = new Token(); + MBool foundMatch = MB_FALSE; + int index = 0; + + //-- check previous token + switch(prevToken->type) { + case Token::VAR_REFERENCE : + if ( prevToken->value.length() == 0) { + prevToken->value.append(buffer); + buffer.clear(); + return; + } + break; + default: + break; + } + + //-- look for next match + while ( !foundMatch && (index < NUMBER_OF_TOKENS) ) { + + Token tok = TOKENS[index++]; + + if ( tok.value.isEqual(buffer) ) { + + foundMatch = MB_TRUE; + + switch (tok.type) { + + //-- NodeType tokens + case Token::COMMENT: + case Token::NODE : + case Token::PI : + case Token::TEXT : + // make sure next delimiter is '(' + if ( ch == L_PAREN) { + //-- copy buffer + match->value = buffer; + //-- copy type + match->type = tok.type; + } + break; + case Token::MULTIPLY_OP : + case Token::DIVIDE_OP: + case Token::MODULUS_OP: + switch ( prevToken->type ) { + case Token::AT_SIGN : + case Token::NULL_TOKEN: + case Token::L_PAREN: + case Token::L_BRACKET: + foundMatch = MB_FALSE; + break; //-- do not match + default: + if ( isOperatorToken(prevToken) ) { + foundMatch = MB_FALSE; + break; //-- do not match + } + match->value = buffer; + match->type = tok.type; + } + break; + default : + //-- copy buffer + match->value = buffer; + match->type = tok.type; + break; + } + } //-- if equal + } //-- while + + if (!foundMatch) { + //-- copy buffer + match->value = buffer; + //-- look for function name + if ( ch == L_PAREN) match->type = Token::FUNCTION_NAME; + else match->type = Token::CNAME; + } + addToken(match); + buffer.clear(); +} //-- matchToken + +/** + * Parses the given String into the set of Tokens +**/ +void ExprLexer::parse(const String& pattern) { + + + String tokenBuffer; + UNICODE_CHAR inLiteral = '\0'; + MBool inNumber = MB_FALSE; + + Int32 currentPos = 0; + + UNICODE_CHAR ch = '\0'; + UNICODE_CHAR prevCh = ch; + + //-- initialize previous token, this will automatically get + //-- deleted when it goes out of scope + Token nullToken('\0', Token::NULL_TOKEN); + + prevToken = &nullToken; + + while (currentPos < pattern.length()) { + + prevCh = ch; + ch = pattern.charAt(currentPos); + + if ( inLiteral ) { + //-- look for end of literal + if ( ch == inLiteral ) { + inLiteral = '\0'; + addToken(new Token(tokenBuffer, Token::LITERAL)); + tokenBuffer.clear(); + } + else { + tokenBuffer.append(ch); + } + } + else if ( inNumber ) { + if (isDigit(ch) || (ch == '.')) { + tokenBuffer.append(ch); + } + else { + inNumber = MB_FALSE; + addToken(new Token(tokenBuffer, Token::NUMBER)); + tokenBuffer.clear(); + //-- push back last char + --currentPos; + } + } + else if (isDigit(ch)) { + if ((tokenBuffer.length() == 0 ) || matchesOperator(tokenBuffer) ) { + //-- match operator and free up token buffer + matchToken(tokenBuffer, ch); + inNumber = MB_TRUE; + } + else if (( tokenBuffer.length() == 1 ) && (prevCh = '-')) { + inNumber = MB_TRUE; + } + tokenBuffer.append(ch); + } + else { + switch (ch) { + //-- ignore whitespace + case SPACE: + case TAB: + case CR: + case LF: + break; + case S_QUOTE : + case D_QUOTE : + matchToken(tokenBuffer, ch); + inLiteral = ch; + break; + case PERIOD: + if ( inNumber ) tokenBuffer.append(ch); + else if ( prevToken->type == Token::SELF_NODE ) { + prevToken->type = Token::PARENT_NODE; + } + else if ( tokenBuffer.length() > 0 ) + tokenBuffer.append(ch); + else matchDelimiter(ch); + break; + case COLON: + if ( prevCh == ch) { + Int32 bufSize = tokenBuffer.length(); + tokenBuffer.setLength(bufSize-1); + addToken(new Token(tokenBuffer, Token::AXIS_IDENTIFIER)); + tokenBuffer.clear(); + } + else tokenBuffer.append(ch); + break; + case FORWARD_SLASH : + matchToken(tokenBuffer, ch); + if ( prevToken->type == Token::PARENT_OP ) { + prevToken->type = Token::ANCESTOR_OP; + prevToken->value.append(ch); + } + else matchDelimiter(ch); + break; + case BANG : //-- used as previous...see EQUAL + matchToken(tokenBuffer,ch); + addToken(new Token(ch, Token::ERROR)); + break; + case EQUAL: + switch ( prevCh ) { + case BANG: + prevToken->type = Token::NOT_EQUAL_OP; + prevToken->value.append("="); + break; + case L_ANGLE: + prevToken->type = Token::LESS_OR_EQUAL_OP; + prevToken->value.append("="); + break; + case R_ANGLE: + prevToken->type = Token::GREATER_OR_EQUAL_OP; + prevToken->value.append("="); + break; + default: + matchToken(tokenBuffer, ch); + matchDelimiter(ch); + break; + } + break; + case L_ANGLE : + case R_ANGLE : + matchToken(tokenBuffer, ch); + matchDelimiter(ch); + break; + case HYPHEN : + if ( isValidQName(tokenBuffer) ) tokenBuffer.append(ch); + else { + switch ( prevToken->type ) { + case Token::NULL_TOKEN: + case Token::L_PAREN: + case Token::L_BRACKET: + case Token::COMMA: + inNumber = MB_TRUE; + tokenBuffer.append(ch); + break; + default: + matchToken(tokenBuffer, ch); + matchDelimiter(ch); + break; + } + } + break; + case ASTERIX: + matchToken(tokenBuffer, ch); + switch ( prevToken->type ) { + case Token::PARENT_OP : + case Token::ANCESTOR_OP: + case Token::AT_SIGN : + case Token::NULL_TOKEN: + case Token::L_PAREN: + case Token::L_BRACKET: + matchDelimiter(ch); + break; + default: + if ( isOperatorToken(prevToken) ) { + matchDelimiter(ch); + break; //-- do not match + } + addToken( new Token(ch, Token::MULTIPLY_OP) ); + } + break; + case L_PAREN: + case R_PAREN: + case L_BRACKET: + case R_BRACKET: + case COMMA: + case AT_SIGN : + case PLUS: + case DOLLAR_SIGN : + case VERT_BAR: + matchToken(tokenBuffer, ch); + matchDelimiter(ch); + break; + default: + switch (prevCh) { + case SPACE : + case TAB : + case CR : + case LF : + matchToken(tokenBuffer, ch); + tokenBuffer.append(ch); + break; + default: + tokenBuffer.append(ch); + break; + } + break; + } + } + ++currentPos; + } + //-- end lexical parsing of current token + //-- freeBuffer if needed + + if ( inNumber ) { + addToken(new Token(tokenBuffer, Token::NUMBER)); + } + else matchToken(tokenBuffer, ch); + prevToken = 0; +} //-- parse + diff --git a/mozilla/extensions/transformiix/source/xpath/ExprLexer.h b/mozilla/extensions/transformiix/source/xpath/ExprLexer.h new file mode 100644 index 00000000000..82eb28c75ef --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ExprLexer.h @@ -0,0 +1,291 @@ +/* + * 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. + * + * Larry Fitzpatrick + * -- changed constant short declarations in Token and ExprLexer to + * enumerations, commented with //--LF + * + * $Id: ExprLexer.h,v 1.1 2000-04-06 07:45:29 kvisco%ziplink.net Exp $ + */ + + +#ifndef MITREXSL_EXPRLEXER_H +#define MITREXSL_EXPRLEXER_H + +#include "String.h" +#include "baseutils.h" +#include + +/** + * A Token class for the ExprLexer. + *
+ * This class was ported from XSL:P, an open source Java based + * XSLT processor, written by yours truly. + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:29 $ +**/ +class Token { + +public: + + //---------------/ + //- Token Types -/ + //---------------/ + + //-- LF - changed from static const short declarations to enum + //-- token types + enum TokenType { + //-- Trivial Tokens + ERROR = 0, + NULL_TOKEN, + LITERAL, + NUMBER, + CNAME, + L_PAREN, + R_PAREN, + L_BRACKET, + R_BRACKET, + COMMA, + FUNCTION_NAME, + WILD_CARD, + AT_SIGN, + VAR_REFERENCE, + PARENT_NODE, + SELF_NODE, + AXIS_IDENTIFIER, + //-------------/ + //- operators -/ + //-------------/ + + //-- boolean ops + AND_OP, + OR_OP, + + //-- relational + EQUAL_OP, + NOT_EQUAL_OP, + LESS_THAN_OP, + GREATER_THAN_OP, + LESS_OR_EQUAL_OP, + GREATER_OR_EQUAL_OP, + //-- additive operators + ADDITION_OP, + SUBTRACTION_OP, + //-- multiplicative + DIVIDE_OP , + MULTIPLY_OP, + MODULUS_OP, + //-- path operators + PARENT_OP, + ANCESTOR_OP, + UNION_OP, + //-- node type tokens + COMMENT, + NODE, + PI, + TEXT + }; + + + /** + * Default Constructor + **/ + Token(); + Token(short type); + Token(const String& value, short type); + Token(UNICODE_CHAR uniChar, short type); + /** + * Copy Constructor + **/ + Token(const Token& token); + + ~Token(); + String value; + short type; +}; //--Token + +/** + * A class for splitting an "Expr" String into tokens and + * performing basic Lexical Analysis. + * + *
This class was ported from XSL:P, an open source Java based XSL processor + * @author Keith Visco +**/ +class ExprLexer { + + +public: + + /* + * Trivial Tokens + */ + //-- LF, changed to enum + enum _TrivialTokens { + D_QUOTE = '\"', + S_QUOTE = '\'', + L_PAREN = '(', + R_PAREN = ')', + L_BRACKET = '[', + R_BRACKET = ']', + L_ANGLE = '<', + R_ANGLE = '>', + COMMA = ',', + PERIOD = '.', + ASTERIX = '*', + FORWARD_SLASH = '/', + EQUAL = '=', + BANG = '!', + VERT_BAR = '|', + AT_SIGN = '@', + DOLLAR_SIGN = '$', + PLUS = '+', + HYPHEN = '-', + COLON = ':', + //-- whitespace tokens + SPACE = ' ', + TAB = '\t', + CR = '\n', + LF = '\r' + }; + + + /* + * Complex Tokens + */ + //-- Nodetype tokens + static const String COMMENT; + static const String NODE; + static const String PI; + static const String TEXT; + + //-- boolean + static const String AND; + static const String OR; + + //-- Multiplicative + static const String MODULUS; + static const String DIVIDE; + + /* + * Default Token Set + */ + static const Token TOKENS[]; + static const short NUMBER_OF_TOKENS; + + /** + * Constructor for ExprLexer + **/ + ExprLexer(const String& pattern); + + ~ExprLexer(); + + /** + * Counts the total number of tokens in this Lexer, even if the token + * has already been seen + * @return the total number of tokens in this Lexer + **/ + int countAllTokens(); + + /** + * Counts the remaining number of tokens in this Lexer + * @return the number of remaining tokens in this Lexer + **/ + int countRemainingTokens(); + + /** + * Returns the type of token that was last return by a call to nextToken + **/ + + Token* lookAhead(int offset); + Token* nextToken(); + Token* peek(); + void pushBack(); + MBool hasMoreTokens(); + + MBool isOperatorToken(Token* token); + +private: + + struct TokenListItem { + Token* token; + TokenListItem* next; + TokenListItem* previous; + }; + + TokenListItem* currentItem; + TokenListItem* firstItem; + TokenListItem* lastItem; + + int tokenCount; + + Token* prevToken; + + void addToken(Token* token); + + /** + * Returns true if the given character represents an Alpha letter + **/ + static MBool isAlphaChar(Int32 ch); + + /** + * Returns true if the given character represents a numeric letter (digit) + **/ + static MBool isDigit(Int32 ch); + + /** + * Returns true if the given character is an allowable QName character + **/ + static MBool isQNameChar(Int32 ch); + + /** + * Returns true if the given character is an allowable NCName character + **/ + static MBool isNCNameChar(Int32 ch); + + /** + * Returns true if the given String is a valid XML QName + **/ + static MBool isValidQName(String& name); + + MBool matchDelimiter(UNICODE_CHAR ch); + + /** + * Returns true if the value of the given String matches + * an OperatorName + **/ + MBool matchesOperator(String& buffer); + + /** + * Matches the given String to the appropriate Token + * @param buffer the current StringBuffer representing the value of the Token + * @param ch, the current delimiter token + **/ + void matchToken(String& buffer, UNICODE_CHAR ch); + + + void parse(const String& pattern); + +}; //-- ExprLexer + +#endif + diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp new file mode 100644 index 00000000000..f320078532c --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.cpp @@ -0,0 +1,905 @@ +/* + * 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. + * Olivier Gerardin, ogerardin@vo.lu + * -- fixed a bug in CreateExpr (@xxx=/yyy was parsed as + * @xxx=@xxx/yyy) + * + * $Id: ExprParser.cpp,v 1.1 2000-04-06 07:45:29 kvisco%ziplink.net Exp $ + */ + +/** + * ExprParser + * This class is used to parse XSL Expressions + * @author Keith Visco + * @see ExprLexer + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:29 $ +**/ + +#include "ExprParser.h" + +const String ExprParser::L_CURLY_BRACE = "{"; +const String ExprParser::R_CURLY_BRACE = "}"; + +/** + * Creates a new ExprParser +**/ +ExprParser::ExprParser() {}; + +/** + * Default Destructor +**/ +ExprParser::~ExprParser() {}; + +/** + * Creates an Attribute Value Template using the given value +**/ +AttributeValueTemplate* ExprParser::createAttributeValueTemplate + (const String& attValue) +{ + + AttributeValueTemplate* avt = new AttributeValueTemplate(); + Int32 size = attValue.length(); + int cc = 0; + String buffer; + MBool inExpr = MB_FALSE; + MBool inLiteral = MB_FALSE; + char endLiteral = '"'; + char prevCh = '\0'; + + while ( cc < size) { + UNICODE_CHAR ch = attValue.charAt(cc++); + // if in literal just add ch to buffer + if ( inLiteral && (ch != endLiteral) ) { + buffer.append(ch); + prevCh = ch; + continue; + } + switch ( ch ) { + case '\'' : + case '"' : + buffer.append(ch); + if (inLiteral) inLiteral = MB_FALSE; + else { + inLiteral = MB_TRUE; + endLiteral = ch; + } + break; + case '{' : + // Ignore case where we find two { without a } + if (!inExpr) { + //-- clear buffer + if ( buffer.length() > 0) { + avt->addExpr(new StringExpr(buffer)); + buffer.clear(); + } + inExpr = MB_TRUE; + } + else if (prevCh == ch) { + inExpr = MB_FALSE; + buffer.append(ch); + } + else { + buffer.append(ch); //-- simply append '{' + ch = '\0'; + } + break; + case '}': + if (inExpr) { + inExpr = MB_FALSE; + avt->addExpr(createExpr(buffer)); + buffer.clear(); + //-- change in case another '}' follows + ch = '\0'; + } + else if (prevCh != ch) { + if ( buffer.length() > 0) buffer.append('}'); + else avt->addExpr(new StringExpr(R_CURLY_BRACE)); + } + break; + default: + buffer.append(ch); + break; + } + prevCh = ch; + } + if ( buffer.length() > 0) { + if ( inExpr ) { + //-- error + String errMsg("#error evaluating AttributeValueTemplate. "); + errMsg.append("Missing '}' after: "); + errMsg.append(buffer); + avt->addExpr(new StringExpr(errMsg)); + } + else avt->addExpr(new StringExpr(buffer)); + } + return avt; + +} //-- createAttributeValueTemplate + +Expr* ExprParser::createExpr(const String& pattern) { + ExprLexer lexer(pattern); + return createExpr(lexer); +} //-- createExpr + +PatternExpr* ExprParser::createPatternExpr(const String& pattern) { + ExprLexer lexer(pattern); + return createUnionExpr(lexer); +} //-- createPatternExpr + +LocationStep* ExprParser::createLocationStep(const String& path) { + ExprLexer lexer(path); + LocationStep* lstep = createLocationStep(lexer); + return lstep; +} //-- createLocationPath + + //--------------------/ + //- Private Methods -/ +//-------------------/ + +/** + * Creates a binary Expr for the given operator +**/ +Expr* ExprParser::createBinaryExpr (Expr* left, Expr* right, Token* op) { + if ( !op ) return 0; + switch(op->type) { + + + //-- additive ops + case Token::ADDITION_OP : + return new AdditiveExpr(left, right, AdditiveExpr::ADDITION); + case Token::SUBTRACTION_OP: + return new AdditiveExpr(left, right, AdditiveExpr::SUBTRACTION); + + //-- case boolean ops + case Token::AND_OP: + return new BooleanExpr(left, right, BooleanExpr::AND); + case Token::OR_OP: + return new BooleanExpr(left, right, BooleanExpr::OR); + + //-- equality ops + case Token::EQUAL_OP : + return new RelationalExpr(left, right, RelationalExpr::EQUAL); + case Token::NOT_EQUAL_OP : + return new RelationalExpr(left, right, RelationalExpr::NOT_EQUAL); + + //-- relational ops + case Token::LESS_THAN_OP: + return new RelationalExpr(left, right, RelationalExpr::LESS_THAN); + case Token::GREATER_THAN_OP: + return new RelationalExpr(left, right, RelationalExpr::GREATER_THAN); + case Token::LESS_OR_EQUAL_OP: + return new RelationalExpr(left, right, RelationalExpr::LESS_OR_EQUAL); + case Token::GREATER_OR_EQUAL_OP: + return new RelationalExpr(left, right, RelationalExpr::GREATER_OR_EQUAL); + + //-- multiplicative ops + case Token::DIVIDE_OP : + return new MultiplicativeExpr(left, right, MultiplicativeExpr::DIVIDE); + case Token::MODULUS_OP : + return new MultiplicativeExpr(left, right, MultiplicativeExpr::MODULUS); + case Token::MULTIPLY_OP : + return new MultiplicativeExpr(left, right, MultiplicativeExpr::MULTIPLY); + default: + break; + + } + return 0; + //return new ErrorExpr(); +} //-- createBinaryExpr + + +Expr* ExprParser::createExpr(ExprLexer& lexer) { + + MBool done = MB_FALSE; + + Expr* expr = 0; + + Stack exprs; + Stack ops; + + while ( lexer.hasMoreTokens() && (!done)) { + + Token* tok = lexer.nextToken(); + switch ( tok->type ) { + case Token::R_BRACKET: + case Token::R_PAREN: + case Token::COMMA : + lexer.pushBack(); + done = MB_TRUE; + break; + case Token::L_PAREN: //-- Grouping Expression + expr = createExpr(lexer); + //-- look for end ')' + if ( lexer.hasMoreTokens() && + ( lexer.nextToken()->type == Token::R_PAREN ) ) break; + else { + //-- error + delete expr; + expr = new StringExpr("missing ')' in expression"); + } + break; + case Token::ANCESTOR_OP: + case Token::PARENT_OP: + lexer.pushBack(); + if ( !expr ) expr = createPathExpr(lexer); + else { + PathExpr* pathExpr = createPathExpr(lexer); + pathExpr->addPatternExpr(0, (PatternExpr*)expr, + PathExpr::RELATIVE_OP); + expr = pathExpr; + } + //done = MB_TRUE; + break; + case Token::UNION_OP : + { + UnionExpr* unionExpr = createUnionExpr(lexer); + unionExpr->addPathExpr(0, (PathExpr*)expr ); + expr = unionExpr; + done = MB_TRUE; + break; + } + case Token::LITERAL : + expr = new StringExpr(tok->value); + break; + case Token::NUMBER: + { + StringResult str(tok->value); + expr = new NumberExpr(str.numberValue()); + break; + } + case Token::FUNCTION_NAME: + { + lexer.pushBack(); + expr = createFunctionCall(lexer); + break; + } + case Token::VAR_REFERENCE: + expr = new VariableRefExpr(tok->value); + break; + //-- additive ops + case Token::ADDITION_OP: + case Token::DIVIDE_OP: + //-- boolean ops + case Token::AND_OP : + case Token::OR_OP : + //-- equality ops + case Token::EQUAL_OP: + case Token::NOT_EQUAL_OP: + //-- relational ops + case Token::LESS_THAN_OP: + case Token::GREATER_THAN_OP: + case Token::LESS_OR_EQUAL_OP: + case Token::GREATER_OR_EQUAL_OP: + //-- multiplicative ops + case Token::MODULUS_OP: + case Token::MULTIPLY_OP: + case Token::SUBTRACTION_OP: + { + if ( !exprs.empty() ) { + short ttype = ((Token*)ops.peek())->type; + if (precedenceLevel(tok->type) < precedenceLevel(ttype)) { + expr = createBinaryExpr((Expr*)exprs.pop(), expr, + (Token*)ops.pop()); + } + } + exprs.push(expr); + ops.push(tok); + expr = 0; // OG, prevent reuse of expr + break; + } + default: + lexer.pushBack(); + expr = createPatternExpr(lexer); + break; + } + } + + // make sure expr != 0, will this happen? + if (( expr == 0 ) && (!exprs.empty())) + expr = (Expr*) exprs.pop(); + + while (!exprs.empty() ) { + expr = createBinaryExpr((Expr*)exprs.pop(), expr, (Token*)ops.pop()); + } + + return expr; + +} //-- createExpr + +FilterExpr* ExprParser::createFilterExpr(ExprLexer& lexer) { + + FilterExpr* filterExpr = new FilterExpr(); + Token* tok = lexer.nextToken(); + if ( !tok ) return filterExpr; + + Expr* expr = 0; + switch ( tok->type ) { + case Token::FUNCTION_NAME : + expr = createFunctionCall(lexer); + filterExpr->setExpr(expr); + break; + case Token::VAR_REFERENCE : + expr = new VariableRefExpr(tok->value); + filterExpr->setExpr(expr); + break; + case Token::L_PAREN: + //-- primary group expr: + expr = createExpr(lexer); + tok = lexer.nextToken(); + if ( (!tok) || (tok->type != Token::R_PAREN ) ) { + String errMsg("error: "); + expr->toString(errMsg); + errMsg.append(" - missing ')'"); + delete expr; //-- free up current expr + expr = new ErrorFunctionCall(errMsg); + } + filterExpr->setExpr(expr); + break; + case Token::PARENT_NODE : + expr = new ParentExpr(); + filterExpr->setExpr(expr); + break; + case Token::SELF_NODE : + expr = new IdentityExpr(); + filterExpr->setExpr(expr); + break; + default: + break; + } + + //-- handle predicates + parsePredicates(filterExpr, lexer); + + return filterExpr; + +} //-- createFilterExpr + +FunctionCall* ExprParser::createFunctionCall(ExprLexer& lexer) { + + if ( !lexer.hasMoreTokens() ) { + //-- should never see this, I hope + return new ErrorFunctionCall("no tokens, invalid function call"); + } + + FunctionCall* fnCall = 0; + + Token* tok = lexer.nextToken(); + + if ( tok->type != Token::FUNCTION_NAME ) { + return new ErrorFunctionCall("invalid function call"); + } + + String fnName = tok->value; + + //-- compare function names + //-- * we should hash these names for speed + + if ( XPathNames::BOOLEAN_FN.isEqual(tok->value) ) { + fnCall = new BooleanFunctionCall(BooleanFunctionCall::BOOLEAN); + } + else if ( XPathNames::CONCAT_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::CONCAT); + } + else if ( XPathNames::CONTAINS_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::CONTAINS); + } + else if ( XPathNames::COUNT_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::COUNT); + } + else if ( XPathNames::FALSE_FN.isEqual(tok->value) ) { + fnCall = new BooleanFunctionCall(); + } + else if ( XPathNames::LAST_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LAST); + } + else if ( XPathNames::LOCAL_NAME_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::LOCAL_NAME); + } + else if ( XPathNames::NAME_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAME); + } + else if ( XPathNames::NAMESPACE_URI_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::NAMESPACE_URI); + } + else if ( XPathNames::NOT_FN.isEqual(tok->value) ) { + fnCall = new BooleanFunctionCall(BooleanFunctionCall::NOT); + } + else if ( XPathNames::POSITION_FN.isEqual(tok->value) ) { + fnCall = new NodeSetFunctionCall(NodeSetFunctionCall::POSITION); + } + else if ( XPathNames::STARTS_WITH_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::STARTS_WITH); + } + else if ( XPathNames::STRING_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::STRING); + } + else if ( XPathNames::STRING_LENGTH_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::STRING_LENGTH); + } + else if ( XPathNames::SUBSTRING_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING); + } + else if ( XPathNames::SUBSTRING_AFTER_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_AFTER); + } + else if ( XPathNames::SUBSTRING_BEFORE_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::SUBSTRING_BEFORE); + } + else if ( XPathNames::TRANSLATE_FN.isEqual(tok->value) ) { + fnCall = new StringFunctionCall(StringFunctionCall::TRANSLATE); + } + else if ( XPathNames::TRUE_FN.isEqual(tok->value) ) { + fnCall = new BooleanFunctionCall(BooleanFunctionCall::TRUE); + } + // OG+ + else if ( XPathNames::NUMBER_FN.isEqual(tok->value) ) { + fnCall = new NumberFunctionCall(NumberFunctionCall::NUMBER); + } + else if ( XPathNames::ROUND_FN.isEqual(tok->value) ) { + fnCall = new NumberFunctionCall(NumberFunctionCall::ROUND); + } + else if ( XPathNames::CEILING_FN.isEqual(tok->value) ) { + fnCall = new NumberFunctionCall(NumberFunctionCall::CEILING); + } + else if ( XPathNames::FLOOR_FN.isEqual(tok->value) ) { + fnCall = new NumberFunctionCall(NumberFunctionCall::FLOOR); + } + // OG- + else { + //-- create error function() for now, should be ext function + String err = "not a valid function: "; + err.append(tok->value); + fnCall = new ErrorFunctionCall(err); + } + //-- handle parametes + List params; + String* errMsg = parseParameters(¶ms, lexer); + if (errMsg) { + String err("error with function call, \""); + err.append(fnName); + err.append("\" : "); + err.append(*errMsg); + fnCall = new ErrorFunctionCall(err); + delete errMsg; + } + // copy params + else if (params.getLength() > 0) { + ListIterator* iter = params.iterator(); + while ( iter->hasNext() ) fnCall->addParam( (Expr*)iter->next() ); + delete iter; + } + return fnCall; +} //-- createFunctionCall + +LocationStep* ExprParser::createLocationStep(ExprLexer& lexer) { + + LocationStep* lstep = new LocationStep(); + short axisIdentifier = LocationStep::CHILD_AXIS; + + //-- get Axis Identifier, if present + Token* tok = lexer.peek(); + MBool setDefaultAxis = MB_TRUE; + if ( tok->type == Token::AXIS_IDENTIFIER ) { + //-- eat token + lexer.nextToken(); + setDefaultAxis = MB_FALSE; + + //-- should switch to a hash here for speed if necessary + if ( ANCESTOR_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::ANCESTOR_AXIS; + else if ( ANCESTOR_OR_SELF_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::ANCESTOR_OR_SELF_AXIS; + else if ( ATTRIBUTE_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::ATTRIBUTE_AXIS; + else if ( CHILD_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::CHILD_AXIS; + else if ( DESCENDANT_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::DESCENDANT_AXIS; + else if ( DESCENDANT_OR_SELF_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::DESCENDANT_OR_SELF_AXIS; + else if ( FOLLOWING_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::FOLLOWING_AXIS; + else if ( FOLLOWING_SIBLING_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::FOLLOWING_SIBLING_AXIS; + else if ( NAMESPACE_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::NAMESPACE_AXIS; + else if ( PARENT_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::PARENT_AXIS; + else if ( PRECEDING_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::PRECEDING_AXIS; + else if ( PRECEDING_SIBLING_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::PRECEDING_SIBLING_AXIS; + else if ( SELF_AXIS.isEqual(tok->value) ) + axisIdentifier = LocationStep::SELF_AXIS; + //-- child axis is default + else { + //-- handle error gracefully, simply ignore invalid axis and + //-- use default. Add error message when message observer + //-- is implemented + setDefaultAxis = MB_TRUE; + } + + } + + //-- parse NodeExpr + NodeExpr* nodeExpr = createNodeExpr(lexer); + lstep->setNodeExpr(nodeExpr); + + + //-- set default axis identifiers + if ((setDefaultAxis) && (nodeExpr)) { + switch ( nodeExpr->getType() ) { + case NodeExpr::ATTRIBUTE_EXPR: + axisIdentifier = LocationStep::ATTRIBUTE_AXIS; + break; + default: + axisIdentifier = LocationStep::CHILD_AXIS; + } + } + lstep->setAxisIdentifier(axisIdentifier); + + //-- handle predicates + + parsePredicates(lstep, lexer); + + // + //String tmp; + //lstep->toString(tmp); + //cout << "returning LocationStep: "<< tmp < + + return lstep; +} //-- createLocationPath + +NodeExpr* ExprParser::createNodeExpr(ExprLexer& lexer) { + + //cout << "creating NodeExpr: "<type <type ) { + case Token::CNAME : + nodeExpr = new ElementExpr(tok->value); + break; + case Token::WILD_CARD: + nodeExpr = new WildCardExpr(); + break; + case Token::COMMENT: + nodeExpr = new BasicNodeExpr(NodeExpr::COMMENT_EXPR); + errMsg = parseParameters(¶ms, lexer); + //-- ignore errMsg for now + delete errMsg; + break; + case Token::NODE : + nodeExpr = new BasicNodeExpr(); + errMsg = parseParameters(¶ms, lexer); + //-- ignore errMsg for now + delete errMsg; + break; + case Token::PI : + nodeExpr = new BasicNodeExpr(NodeExpr::PI_EXPR); + errMsg = parseParameters(¶ms, lexer); + //-- ignore errMsg for now + delete errMsg; + break; + case Token::TEXT : + nodeExpr = new TextExpr(); + errMsg = parseParameters(¶ms, lexer); + //-- ignore errMsg for now + delete errMsg; + break; + case Token::AT_SIGN: + tok = lexer.nextToken(); + if ( !tok ) { + //-- handle error + } + else if (tok->type == Token::CNAME) { + nodeExpr = new AttributeExpr(tok->value); + } + else if ( tok->type == Token::WILD_CARD ) { + AttributeExpr* attExpr = new AttributeExpr(); + attExpr->setWild(MB_TRUE); + nodeExpr = attExpr; + } + else { + //-- handle error + } + break; + default: + break; + } + return nodeExpr; +} //-- createNodeExpr + +/** + * Creates a PathExpr using the given ExprLexer + * @param lexer the ExprLexer for retrieving Tokens +**/ +PathExpr* ExprParser::createPathExpr(ExprLexer& lexer) { + + + //-- check for RootExpr + if ( lexer.countRemainingTokens() == 1 ) { + if ( lexer.peek()->type == Token::PARENT_OP ) { + lexer.nextToken(); //-- eat token + return new RootExpr(); + } + } + + PathExpr* pathExpr = new PathExpr(); + short ancestryOp = PathExpr::RELATIVE_OP; + + while ( lexer.hasMoreTokens() ) { + Token* tok = lexer.nextToken(); + if ( lexer.isOperatorToken(tok) ) { + lexer.pushBack(); + return pathExpr; + } + switch ( tok->type ) { + case Token::R_PAREN: + case Token::R_BRACKET: + case Token::UNION_OP: + lexer.pushBack(); + return pathExpr; + case Token::ANCESTOR_OP : + ancestryOp = PathExpr::ANCESTOR_OP; + break; + case Token::PARENT_OP : + ancestryOp = PathExpr::PARENT_OP; + break; + default: + lexer.pushBack(); + pathExpr->addPatternExpr(createPatternExpr(lexer), ancestryOp); + ancestryOp = PathExpr::RELATIVE_OP; + break; + } + } + + /* * + String tmp; + pathExpr->toString(tmp); + cout << "creating pathExpr: " << tmp << endl; + /* */ + + return pathExpr; +} //-- createPathExpr + +/** + * Creates a PatternExpr using the given ExprLexer + * @param lexer the ExprLexer for retrieving Tokens +**/ +PatternExpr* ExprParser::createPatternExpr(ExprLexer& lexer) { + + PatternExpr* pExpr = 0; + Token* tok = lexer.peek(); + if ( isLocationStepToken(tok) ) { + pExpr = createLocationStep(lexer); + } + else if ( isFilterExprToken(tok) ) { + pExpr = createFilterExpr(lexer); + } + else { + cout << "invalid token: " << tok->value << endl; + //-- eat token for now + lexer.nextToken(); + } + return pExpr; +} //-- createPatternExpr + +/** + * Creates a PathExpr using the given ExprLexer + * @param lexer the ExprLexer for retrieving Tokens +**/ +UnionExpr* ExprParser::createUnionExpr(ExprLexer& lexer) { + UnionExpr* unionExpr = new UnionExpr(); + + while ( lexer.hasMoreTokens() ) { + Token* tok = lexer.nextToken(); + switch ( tok->type ) { + + case Token::R_PAREN: + case Token::R_BRACKET: + lexer.pushBack(); + return unionExpr; + case Token::UNION_OP : + //-- eat token + break; + default: + lexer.pushBack(); + unionExpr->addPathExpr(createPathExpr(lexer)); + break; + } + } + //String tmp; + //unionExpr->toString(tmp); + //cout << "creating UnionExpr: " << tmp << endl; + return unionExpr; +} //-- createUnionExpr + +MBool ExprParser::isFilterExprToken(Token* token) { + if ( !token ) return MB_FALSE; + switch (token->type) { + case Token::LITERAL: + case Token::NUMBER: + case Token::FUNCTION_NAME: + case Token::VAR_REFERENCE: + case Token::L_PAREN: // grouping expr + case Token::PARENT_NODE: + case Token::SELF_NODE : + return MB_TRUE; + default: + return MB_FALSE; + } +} //-- isFilterExprToken + +MBool ExprParser::isLocationStepToken(Token* token) { + if (!token) return MB_FALSE; + return ((token->type == Token::AXIS_IDENTIFIER) || isNodeTypeToken(token)); +} //-- isLocationStepToken + +MBool ExprParser::isNodeTypeToken(Token* token) { + if (!token) return MB_FALSE; + + switch ( token->type ) { + case Token::AT_SIGN: + case Token::CNAME: + case Token::WILD_CARD: + case Token::COMMENT: + case Token::NODE : + case Token::PI : + case Token::TEXT : + return MB_TRUE; + default: + return MB_FALSE; + } +} //-- isLocationStepToken + +/** + * 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 +**/ +String* ExprParser::parsePredicates(PredicateList* predicateList, ExprLexer& lexer) { + + String* errorMsg = 0; + + Token* tok = lexer.peek(); + + if ( !tok ) return 0; //-- no predicates + if ( tok->type != Token::L_BRACKET ) return 0; //-- not start of predicate list + + lexer.nextToken(); + + while ( lexer.hasMoreTokens() ) { + tok = lexer.peek(); + if(!tok) { + //-- error missing ']' + errorMsg = new String("missing close of predicate expression ']'"); + break; + } + if ( tok->type == Token::R_BRACKET) { + lexer.nextToken(); //-- eat ']' + break; + } + Expr* expr = createExpr(lexer); + predicateList->add(expr); + } + return errorMsg; + +} //-- parsePredicates + + +/** + * Using the given lexer, parses the tokens if they represent a parameter list + * If an error occurs a non-zero String pointer will be returned containing the + * error message. + * @param list, the List to add parameter expressions to + * @param lexer the ExprLexer to use for parsing tokens + * @return 0 if successful, or a String pointer to the error message +**/ +String* ExprParser::parseParameters(List* list, ExprLexer& lexer) { + + String* errorMsg = 0; + + Token* tok = lexer.peek(); + + if ( !tok ) return 0; //-- no params + if ( tok->type != Token::L_PAREN ) return 0; //-- not start of param list + + lexer.nextToken(); //-- eat L_PAREN + + MBool done = MB_FALSE; + MBool foundSep = MB_FALSE; + + while ( lexer.hasMoreTokens() && !done) { + tok = lexer.peek(); + switch ( tok->type ) { + case Token::R_PAREN : + if (foundSep) errorMsg = new String("missing expression after ','"); + lexer.nextToken(); //-- eat R_PAREN + done = MB_TRUE; + break; + case Token::COMMA: //-- param separator + //-- eat COMMA + lexer.nextToken(); + foundSep = MB_TRUE; + break; + default: + if ((list->getLength() > 0) && (!foundSep)) { + errorMsg = new String("missing ',' or ')'"); + done = MB_TRUE; + break; + } + foundSep = MB_FALSE; + Expr* expr = createExpr(lexer); + list->add(expr); + break; + } + } + return errorMsg; + +} //-- parseParameters + +short ExprParser::precedenceLevel(short tokenType) { + switch(tokenType) { + case Token::OR_OP: + return 1; + case Token::AND_OP: + return 2; + //-- equality + case Token::EQUAL_OP: + case Token::NOT_EQUAL_OP: + return 3; + //-- relational + case Token::LESS_THAN_OP: + case Token::GREATER_THAN_OP: + case Token::LESS_OR_EQUAL_OP: + case Token::GREATER_OR_EQUAL_OP: + return 4; + //-- additive operators + case Token::ADDITION_OP: + case Token::SUBTRACTION_OP: + return 5; + //-- multiplicative + case Token::DIVIDE_OP: + case Token::MULTIPLY_OP: + case Token::MODULUS_OP: + return 6; + default: + break; + } + return 0; +} //-- precedenceLevel + diff --git a/mozilla/extensions/transformiix/source/xpath/ExprParser.h b/mozilla/extensions/transformiix/source/xpath/ExprParser.h new file mode 100644 index 00000000000..780ea5bdab7 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ExprParser.h @@ -0,0 +1,106 @@ +/* + * 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. + * + * $Id: ExprParser.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $ + */ + +/** + * ExprParser + * This class is used to parse XSL Expressions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $ + * @see ExprLexer +**/ + +#ifndef MITREXSL_EXPRPARSER_H +#define MITREXSL_EXPRPARSER_H + +#include "String.h" +#include "ExprLexer.h" +#include "Expr.h" +#include "FunctionLib.h" +#include "List.h" +#include "Stack.h" +#include + +class ExprParser { + +public: + + static const String R_CURLY_BRACE; + static const String L_CURLY_BRACE; + + /** + * Creates a new ExprParser + **/ + ExprParser(); + + /** + * destroys the ExprParser + **/ + ~ExprParser(); + + Expr* createExpr (const String& pattern); + PatternExpr* createPatternExpr (const String& pattern); + LocationStep* createLocationStep(const String& path); + + /** + * Creates an Attribute Value Template using the given value + **/ + AttributeValueTemplate* createAttributeValueTemplate(const String& attValue); + + +private: + + + Expr* createBinaryExpr (Expr* left, Expr* right, Token* op); + Expr* createExpr (ExprLexer& lexer); + FilterExpr* createFilterExpr (ExprLexer& lexer); + FunctionCall* createFunctionCall (ExprLexer& lexer); + LocationStep* createLocationStep (ExprLexer& lexer); + NodeExpr* createNodeExpr (ExprLexer& lexer); + PathExpr* createPathExpr (ExprLexer& lexer); + PatternExpr* createPatternExpr (ExprLexer& lexer); + UnionExpr* createUnionExpr (ExprLexer& lexer); + + MBool isFilterExprToken (Token* tok); + MBool isLocationStepToken (Token* tok); + 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. + * @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 + **/ + String* parsePredicates(PredicateList* predicateList, ExprLexer& lexer); + String* parseParameters(List* list, ExprLexer& lexer); + + +}; //-- ExprParser + +#endif diff --git a/mozilla/extensions/transformiix/source/xpath/ExprResult.h b/mozilla/extensions/transformiix/source/xpath/ExprResult.h new file mode 100644 index 00000000000..d5d210fb2c7 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ExprResult.h @@ -0,0 +1,162 @@ +/* + * 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. + * Larry Fitzpatrick, OpenText, lef@opentext.com + * -- changed constant short result types to enum + * + * $Id: ExprResult.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $ + */ + +#include "MITREObject.h" +#include "String.h" +#include "baseutils.h" +#include "primitives.h" + +#ifndef MITREXSL_EXPRRESULT_H +#define MITREXSL_EXPRRESULT_H + + +/* + * ExprResult + *
+ * Classes Represented: + * BooleanResult, ExprResult, NumberResult, StringResult + *
+ * Note: for NodeSet, see NodeSet.h
+ * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $ +*/ + +class ExprResult : public MITREObject { + +public: + + //-- ResultTypes + enum _ResultType { + NODESET = 1, + STRING, + BOOLEAN, + TREE_FRAGMENT, + NUMBER + }; + + virtual ~ExprResult() {}; + + /** + * Returns the type of ExprResult represented + * @return the type of ExprResult represented + **/ + virtual short getResultType() = 0; + /** + * Creates a String representation of this ExprResult + * @param str the destination string to append the String representation to. + **/ + virtual void stringValue(String& str) = 0; + + /** + * Converts this ExprResult to a Boolean (MBool) value + * @return the Boolean value + **/ + virtual MBool booleanValue() = 0; + + /** + * Converts this ExprResult to a Number (double) value + * @return the Number value + **/ + virtual double numberValue() = 0; + +}; + +class BooleanResult : public ExprResult { + +public: + + BooleanResult(); + BooleanResult(MBool boolean); + BooleanResult(const BooleanResult& boolResult); + + MBool getValue() const; + + void setValue(MBool boolean); + + void setValue(const BooleanResult& boolResult); + + virtual short getResultType(); + virtual void stringValue(String& str); + virtual MBool booleanValue(); + virtual double numberValue(); + +private: + MBool value; +}; + +class NumberResult : public ExprResult { + +public: + + NumberResult(); + NumberResult(double dbl); + NumberResult(const NumberResult& nbrResult); + + double getValue() const; + + void setValue(double dbl); + + void setValue(const NumberResult& nbrResult); + + MBool isNaN() const; + + virtual short getResultType(); + virtual void stringValue(String& str); + virtual MBool booleanValue(); + virtual double numberValue(); + +private: + double value; + +}; + + +class StringResult : public ExprResult { + +public: + + StringResult(); + StringResult(String& str); + StringResult(const String& str); + StringResult(const StringResult& strResult); + + String& getValue(); + void setValue(const String& str); + + virtual short getResultType(); + virtual void stringValue(String& str); + virtual MBool booleanValue(); + virtual double numberValue(); + + +private: + String value; +}; + +#endif + diff --git a/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp new file mode 100644 index 00000000000..85242508a57 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/FilterExpr.cpp @@ -0,0 +1,147 @@ +/* + * 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. + * Bob Miller, kbob@oblix.com + * -- plugged core leak. + * + * $Id: FilterExpr.cpp,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $ +**/ +//-- Implementation of FilterExpr --/ + + +FilterExpr::FilterExpr() : PredicateList() { + expr = 0; +} + +/** + * Creates a new FilterExpr using the given Expr + * @param expr the Expr to use for evaluation +**/ +FilterExpr::FilterExpr(Expr* expr) : PredicateList() { + this->expr = expr; +} //-- FilterExpr + +/** + * Destroys this FilterExpr, all predicates and the expr will be deleted +**/ +FilterExpr::~FilterExpr() { + delete expr; +} //-- ~FilterExpr + +/** + * Sets the Expr of this FilterExpr for use during evaluation + * @param expr the Expr to use for evaluation +**/ +void FilterExpr::setExpr(Expr* expr) { + this->expr = expr; +} //-- setExpr + + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ +//------------------------------------/ + +/** + * 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 ProcessorState containing the stack information needed + * for evaluation + * @return the result of the evaluation + * @see PatternExpr +**/ +ExprResult* FilterExpr::evaluate(Node* context, ContextState* cs) { + + if (( !context ) || (! expr )) return new NodeSet; + + ExprResult* exprResult = expr->evaluate(context, cs); + NodeSet* nodeSet = 0; + + switch (exprResult->getResultType()) { + case ExprResult::NODESET: + nodeSet = (NodeSet*)exprResult; + break; + /* + case ExprResult.TREE_FRAGMENT: + nodeSet = new NodeSet(1); + nodeSet.add(((TreeFragmentResult)exprResult).getValue()); + break; + */ + default: + break; + /* + throw new InvalidExprException + ("expecting NodeSet or TreeFragment as the result of the "+ + "expression: " + primaryExpr); + */ + } + + //-- filter nodes (apply predicates) + evaluatePredicates(nodeSet, cs); + + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double FilterExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + //-- this method will never be called, it's only here since + //-- I made it manditory for PatternExprs I will remove it soon + return Double::NEGATIVE_INFINITY; +} //-- getDefaultPriority + +/** + * Determines whether this PatternExpr matches the given node within + * the given context +**/ +MBool FilterExpr::matches(Node* node, Node* context, ContextState* cs) { + + if ( !expr ) return MB_FALSE; + NodeSet* nodes = (NodeSet*)evaluate(node, cs); + MBool result = (nodes->contains(node)); + delete nodes; + return result; + +} //-- matches + +/** + * Creates a String representation of this Expr + * @param str the destination String to append to + * @see Expr +**/ +void FilterExpr::toString(String& str) { + if ( expr ) expr->toString(str); + else str.append("null"); + PredicateList::toString(str); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp new file mode 100644 index 00000000000..a1987a64b0d --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/FunctionCall.cpp @@ -0,0 +1,202 @@ +/* + * 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. + * + * $Id: FunctionCall.cpp,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $ + */ + +#include "FunctionLib.h" + +/** + * This class represents a FunctionCall as defined by the XSL Working Draft + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:30 $ +**/ + +const String FunctionCall::INVALID_PARAM_COUNT = + "invalid number of parameters for function: "; + +//- Constructors -/ + +/** + * Creates a new FunctionCall +**/ +FunctionCall::FunctionCall() { + this->name = "void"; +} //-- FunctionCall + +/** + * Creates a new FunctionCall with the given function + * Note: The object references in parameters will be deleted when this + * FunctionCall gets destroyed. +**/ +FunctionCall::FunctionCall(const String& name) { + //-- copy name + this->name = name; +} //-- FunctionCall + +/** + * Creates a new FunctionCall with the given function name and parameter list + * Note: The object references in parameters will be deleted when this + * FunctionCall gets destroyed. +**/ +FunctionCall::FunctionCall(const String& name, List* parameters) { + //-- copy name + this->name = name; + + if (parameters) { + ListIterator* pIter = parameters->iterator(); + while ( pIter->hasNext() ) { + params.add(pIter->next()); + } + delete pIter; + } + +} //-- FunctionCall + + +/** + * Destructor +**/ +FunctionCall::~FunctionCall() { + + ListIterator* iter = params.iterator(); + while ( iter->hasNext() ) { + iter->next(); + Expr* expr = (Expr*) iter->remove(); + delete expr; + } + delete iter; +} //-- ~FunctionCall + + //------------------/ + //- Public Methods -/ +//------------------/ + +/** + * 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) { + if ( expr ) params.add(expr); +} //-- addParam + +/** + * Evaluates the given Expression and converts it's result to a String. + * The value is appended to the given destination String +**/ +void FunctionCall::evaluateToString + (Expr* expr, Node* context, ContextState* cs, String& dest) +{ + if (!expr) return; + ExprResult* exprResult = expr->evaluate(context, cs); + exprResult->stringValue(dest); + delete exprResult; +} //-- evaluateToString + +/** + * Evaluates the given Expression and converts it's result to a number. +**/ +double FunctionCall::evaluateToNumber + (Expr* expr, Node* context, ContextState* cs) +{ + double result = Double::NaN; + if (!expr) return result; + ExprResult* exprResult = expr->evaluate(context, cs); + result = exprResult->numberValue(); + delete exprResult; + return result; +} //-- evaluateToNumber + +/** + * Returns the name of this FunctionCall + * @return the name of this FunctionCall +**/ +const String& FunctionCall::getName() { + return (const String&) this->name; +} //-- getName + +/** + * Called to check number of parameters +**/ +MBool FunctionCall::requireParams + (int paramCountMin, int paramCountMax, ContextState* cs) +{ + + int argc = params.getLength(); + if (( argc < paramCountMin) || (argc > paramCountMax)) { + String err(INVALID_PARAM_COUNT); + toString(err); + cs->recieveError(err); + return MB_FALSE; + } + return MB_TRUE; +} //-- requireParams + +/** + * Called to check number of parameters +**/ +MBool FunctionCall::requireParams(int paramCountMin, ContextState* cs) { + int argc = params.getLength(); + if (argc < paramCountMin) { + String err(INVALID_PARAM_COUNT); + toString(err); + cs->recieveError(err); + return MB_FALSE; + } + return MB_TRUE; +} //-- requireParams + +/** + * Sets the function name of this FunctionCall + * @param name the name of this Function +**/ +void FunctionCall::setName(const String& name) { + this->name.clear(); + this->name.append(name); +} //-- setName + +/** + * 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 FunctionCall::toString(String& dest) { + dest.append(this->name); + dest.append('('); + //-- add parameters + ListIterator* iterator = params.iterator(); + int argc = 0; + while ( iterator->hasNext() ) { + if ( argc > 0 ) dest.append(','); + Expr* expr = (Expr*)iterator->next(); + expr->toString(dest); + ++argc; + + } + delete iterator; + dest.append(')'); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/FunctionLib.h b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h new file mode 100644 index 00000000000..f2ae3bc2580 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/FunctionLib.h @@ -0,0 +1,365 @@ +/* + * 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. + * + * Olivier Gerardin, ogerardin@vo.lu + * -- added number functions + * + * $Id: FunctionLib.h,v 1.1 2000-04-06 07:45:30 kvisco%ziplink.net Exp $ + */ + + + +#ifndef MITREXSL_FUNCTIONLIB_H +#define MITREXSL_FUNCTIONLIB_H + +#include "String.h" +#include "primitives.h" +#include "NodeSet.h" +#include "List.h" +#include "dom.h" +#include "ExprResult.h" +#include "baseutils.h" +#include "Expr.h" +#include "Names.h" +#include "XMLUtils.h" +#include + +class XPathNames { + +public: +//-- Function Names +static const String BOOLEAN_FN; +static const String CONCAT_FN; +static const String CONTAINS_FN; +static const String COUNT_FN ; +static const String FALSE_FN; +static const String LAST_FN; +static const String LOCAL_NAME_FN; +static const String NAME_FN; +static const String NAMESPACE_URI_FN; +static const String NOT_FN; +static const String POSITION_FN; +static const String STARTS_WITH_FN; +static const String STRING_FN; +static const String STRING_LENGTH_FN; +static const String SUBSTRING_FN; +static const String SUBSTRING_AFTER_FN; +static const String SUBSTRING_BEFORE_FN; +static const String TRANSLATE_FN; +static const String TRUE_FN; +// OG+ +static const String NUMBER_FN; +static const String ROUND_FN; +static const String CEILING_FN; +static const String FLOOR_FN; +// OG- + +//-- internal XSL processor functions +static const String ERROR_FN; + + +}; //-- XPathNames + +/** + * This class represents a FunctionCall as defined by the XSL + * Working Draft. + * This file was ported from XSL:P
+ * @author Keith Visco + *
+ *
+ * Modifications:
+ * 19990805: Keith Visco
+ *   - added NodeSetFunctionCall
+ *   - moved position() function into NodeSetFunctionCall
+ *   - removed PositionFunctionCall
+ * 19990806: Larry Fitzpatrick
+ *   - changed constant short declarations for BooleanFunctionCall
+ *     with enumerations
+ * 19990806: Keith Visco
+ *   - added StringFunctionCall
+ *   - stated using Larry's enum suggestion instead of using static const shorts,
+ *     as you can see, I am a Java developer! ;-)
+ * 
+**/ +class FunctionCall : public Expr { + +public: + + static const String INVALID_PARAM_COUNT; + + + virtual ~FunctionCall(); + + /** + * 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); + + /** + * 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) = 0; + + /** + * Returns the name of this FunctionCall + * @return the name of this FunctionCall + **/ + const String& getName(); + + virtual MBool requireParams(int paramCountMin, ContextState* cs); + + virtual MBool requireParams(int paramCountMin, + int paramCountMax, + ContextState* cs); + + /** + * Sets the function name of this FunctionCall + * @param name the name of this Function + **/ + void setName(const String& name); + /** + * 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 Expressions. + * @return the String representation of this Pattern. + **/ + virtual void toString(String& dest); + + +protected: + + List params; + + FunctionCall(); + FunctionCall(const String& name); + FunctionCall(const String& name, List* parameters); + + + /** + * Evaluates the given Expression and converts it's result to a String. + * The value is appended to the given destination String + **/ + void FunctionCall::evaluateToString + (Expr* expr, Node* context, ContextState* cs, String& dest); + + /** + * Evaluates the given Expression and converts it's result to a number. + **/ + double evaluateToNumber(Expr* expr, Node* context, ContextState* cs); + +private: + + String name; +}; //-- FunctionCall + +/** + * Represents the Set of boolean functions + * @author Keith Visco +**/ +class BooleanFunctionCall : public FunctionCall { + +public: + + enum _BooleanFunctions { BOOLEAN = 1, FALSE, NOT, TRUE }; + + /** + * Creates a default BooleanFunctionCall, which always evaluates to False + **/ + BooleanFunctionCall(); + + /** + * Creates a BooleanFunctionCall of the given type + **/ + BooleanFunctionCall(short type); + + /** + * 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: + short type; +}; //-- BooleanFunctionCall + +/** + * Internal Function created when there is an Error during parsing + * an Expression +**/ +class ErrorFunctionCall : public FunctionCall { +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); + + void setErrorMessage(String& errorMsg); + +private: + + String errorMessage; + +}; //-- ErrorFunctionCall + +/** + * Represents the XPath NodeSet function calls +**/ +class NodeSetFunctionCall : public FunctionCall { + +public: + + enum _NodeSetFunctions { + COUNT = 1, //-- count() + LAST, //-- last() + LOCAL_NAME, //-- local-name() + NAMESPACE_URI, //-- namespace-uri() + NAME, //-- name() + POSITION //-- position() + }; + + /** + * Creates a default NodeSetFunction call. Position function is the default. + **/ + NodeSetFunctionCall(); + + /** + * Creates a NodeSetFunctionCall of the given type + **/ + NodeSetFunctionCall(short type); + + /** + * 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: + short type; +}; //-- NodeSetFunctionCall + + +/** + * Represents the XPath String Function Calls +**/ +class StringFunctionCall : public FunctionCall { + +public: + + enum _StringFunctions { + CONCAT = 1, //-- concat() + CONTAINS, //-- contains() + NORMALIZE, //-- normalize() + STARTS_WITH, //-- starts-with() + STRING, //-- string() + STRING_LENGTH, //-- string-length() + SUBSTRING, //-- substring() + SUBSTRING_AFTER, //-- substring-after() + SUBSTRING_BEFORE, //-- substring-before() + TRANSLATE //-- translate() + }; + + /** + * Creates a default String function. String() function is the default. + **/ + StringFunctionCall(); + + /** + * Creates a String function of the given type + **/ + StringFunctionCall(short type); + + /** + * 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: + short type; +}; //-- StringFunctionCall + + +// OG+ +/** + * Represents the XPath Number Function Calls +**/ +class NumberFunctionCall : public FunctionCall { + +public: + + enum _NumberFunctions { + NUMBER = 1, //-- number() + ROUND, //-- round() + FLOOR, //-- floor() + CEILING //-- ceiling() + }; + + /** + * Creates a default Number function. number() function is the default. + **/ + NumberFunctionCall(); + + /** + * Creates a Number function of the given type + **/ + NumberFunctionCall(short type); + + /** + * 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: + short type; +}; //-- NumberFunctionCall +// OG- + +#endif diff --git a/mozilla/extensions/transformiix/source/xpath/IdentityExpr.cpp b/mozilla/extensions/transformiix/source/xpath/IdentityExpr.cpp new file mode 100644 index 00000000000..66a0ba2d2d4 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/IdentityExpr.cpp @@ -0,0 +1,59 @@ +/* + * 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. + * + * $Id: IdentityExpr.cpp,v 1.1 2000-04-06 07:45:31 kvisco%ziplink.net Exp $ + */ + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:31 $ +**/ +#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* IdentityExpr::evaluate(Node* context, ContextState* cs) { + NodeSet* nodeSet = new NodeSet(); + if ( context ) { + nodeSet->add(context); + } + return nodeSet; +} //-- evaluate + +/** + * 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 IdentityExpr::toString(String& dest) { + dest.append('.'); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp new file mode 100644 index 00000000000..74506ae2e4d --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/LocationStep.cpp @@ -0,0 +1,317 @@ +/* + * 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. + * + * $Id: LocationStep.cpp,v 1.1 2000-04-06 07:45:31 kvisco%ziplink.net Exp $ + */ + +/** + * LocationStep + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:31 $ +**/ + +#include "Expr.h" + +/** + * Creates a new LocationStep using the default Axis Identifier and no + * NodeExpr (which matches nothing) +**/ +LocationStep::LocationStep() : PredicateList() { + nodeExpr = 0; + this->axisIdentifier = CHILD_AXIS; +} //-- LocationStep + +/** + * Creates a new LocationStep using the default Axis Identifier and + * the given NodeExpr + * @param nodeExpr the NodeExpr to use when matching Nodes +**/ +LocationStep::LocationStep(NodeExpr* nodeExpr) : PredicateList() { + this->nodeExpr = nodeExpr; + this->axisIdentifier = CHILD_AXIS; +} //-- LocationStep + +/** + * 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 + +/** + * Destroys this LocationStep + * All predicates will be deleted + * The NodeExpr will be deleted +**/ +LocationStep::~LocationStep() { + delete nodeExpr; +} //-- ~LocationStep + +/** + * Sets the Axis Identifier for this LocationStep + * @param axisIdentifier the Axis in which to search for nodes +**/ +void LocationStep::setAxisIdentifier(short axisIdentifier) { + this->axisIdentifier = axisIdentifier; +} //-- setAxisIdentifier + + +/** + * Sets the NodeExpr of this LocationStep for use when matching nodes + * @param nodeExpr the NodeExpr to use when matching nodes +**/ +void LocationStep::setNodeExpr(NodeExpr* nodeExpr) { + this->nodeExpr = nodeExpr; +} //-- setNodeExpr + + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ +//------------------------------------/ + +/** + * 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 ProcessorState containing the stack information needed + * for evaluation + * @return the result of the evaluation + * @see PatternExpr +**/ +ExprResult* LocationStep::evaluate(Node* context, ContextState* cs) { + + NodeSet* nodes = new NodeSet(); + if (( !context ) || (! nodeExpr )) return nodes; + + Node* node = context; + switch (axisIdentifier) { + case ANCESTOR_AXIS : + if (node) node = context->getParentNode(); + //-- do not break here + case ANCESTOR_OR_SELF_AXIS : + while (node) { + if (nodeExpr->matches(node, context, cs)) { + nodes->add(node); + } + node = node->getParentNode(); + } + break; + case ATTRIBUTE_AXIS : + { + NamedNodeMap* atts = context->getAttributes(); + if ( atts ) { + for ( int i = 0; i < atts->getLength(); i++ ) { + Attr* attr = (Attr*)atts->item(i); + if ( nodeExpr->matches(attr, context, cs) ) nodes->add(attr); + } + } + break; + } + case DESCENDANT_OR_SELF_AXIS : + if ( nodeExpr->matches(context, context, cs)) + nodes->add(context); + //-- do not break here + case DESCENDANT_AXIS : + fromDescendants(context, cs, nodes); + break; + case FOLLOWING_AXIS : + { + node = context->getNextSibling(); + while (node) { + if (nodeExpr->matches(node, context, cs)) + nodes->add(node); + + if (node->hasChildNodes()) + fromDescendants(node, cs, nodes); + + Node* tmpNode = node->getNextSibling(); + if (!tmpNode) { + node = node->getParentNode(); + if ((node) && (node->getNodeType() != Node::DOCUMENT_NODE)) + node = node->getNextSibling(); + } + else node = tmpNode; + } + break; + } + case FOLLOWING_SIBLING_AXIS : + node = context->getNextSibling(); + while (node) { + if (nodeExpr->matches(node, context, cs)) + nodes->add(node); + node = node->getNextSibling(); + } + break; + case NAMESPACE_AXIS : //-- not yet implemented + cout << "namespace axis not yet implemented"<getParentNode(); + if ( nodeExpr->matches(parent, context, cs) ) + nodes->add(parent); + break; + } + case PRECEDING_AXIS : + node = context->getPreviousSibling(); + if ( !node ) node = context->getParentNode(); + while (node) { + if (nodeExpr->matches(node, context, cs)) + nodes->add(node); + + Node* temp = node->getPreviousSibling(); + if (!temp) node = node->getParentNode(); + else node = temp; + } + break; + case PRECEDING_SIBLING_AXIS: + node = context->getPreviousSibling(); + while (node) { + if (nodeExpr->matches(node, context, cs)) + nodes->add(node); + node = node->getPreviousSibling(); + } + break; + case SELF_AXIS : + if ( nodeExpr->matches(context, context, cs) ) + nodes->add(context); + break; + default: //-- Children Axis + { + NodeList* nl = context->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++ ) { + if ( nodeExpr->matches(nl->item(i), context, cs) ) + nodes->add(nl->item(i)); + } + break; + } + } //-- switch + + //-- apply predicates + evaluatePredicates(nodes, cs); + + return nodes; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double LocationStep::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + + if ( !nodeExpr ) { + return Double::NEGATIVE_INFINITY; + } + if (!this->isEmpty()) { + return 0.5; + } + return nodeExpr->getDefaultPriority(node, context, cs); + +} //-- getDefaultPriority + + +void LocationStep::fromDescendants(Node* context, ContextState* cs, NodeSet* nodes) { + + if (( !context ) || (! nodeExpr )) return; + + NodeList* nl = context->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++) { + Node* child = nl->item(i); + if (nodeExpr->matches(child, context, cs)) + nodes->add(child); + //-- check childs descendants + if (child->hasChildNodes()) fromDescendants(child, cs, nodes); + } + +} //-- fromDescendants + +/** + * Determines whether this PatternExpr matches the given node within + * the given context +**/ +MBool LocationStep::matches(Node* node, Node* context, ContextState* cs) { + + if ( !nodeExpr ) return MB_FALSE; + + if ( !nodeExpr->matches(node, context, cs) ) return MB_FALSE; + + NodeSet nodes; + nodes.add(node); + evaluatePredicates(&nodes, cs); + + return (MBool)(nodes.size() > 0); + +} //-- 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) { + case ANCESTOR_AXIS : + str.append("ancestor::"); + break; + case ANCESTOR_OR_SELF_AXIS : + str.append("ancestor-or-self::"); + break; + case DESCENDANT_AXIS: + str.append("descendant::"); + break; + case DESCENDANT_OR_SELF_AXIS: + str.append("descendant-or-self::"); + break; + case FOLLOWING_AXIS : + str.append("following::"); + break; + case FOLLOWING_SIBLING_AXIS: + str.append("following-sibling::"); + break; + case NAMESPACE_AXIS: + str.append("namespace::"); + break; + case PARENT_AXIS : + str.append("parent::"); + break; + case PRECEDING_AXIS : + str.append("preceding::"); + break; + case PRECEDING_SIBLING_AXIS : + str.append("preceding-sibling::"); + break; + case SELF_AXIS : + str.append("self::"); + break; + default: + break; + } + if ( nodeExpr ) nodeExpr->toString(str); + else str.append("null"); + PredicateList::toString(str); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/Makefile b/mozilla/extensions/transformiix/source/xpath/Makefile new file mode 100644 index 00000000000..aeef9921c36 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/Makefile @@ -0,0 +1,168 @@ +target: xpath + +CC := $(CC) -g + +ROOT_PATH = .. +XML_PATH = $(ROOT_PATH)/xml +DOM_PATH = $(XML_PATH)/dom +BASE_PATH = $(ROOT_PATH)/base +PROCESSOR_PATH = $(ROOT_PATH)/xslt + +INCLUDE_PATHS = -I. \ + -I$(DOM_PATH) \ + -I$(BASE_PATH) \ + -I$(XML_PATH) \ + -I$(PROCESSOR_PATH) \ + -I- + + +XPATH_OBJS = AdditiveExpr.o \ + AttributeExpr.o \ + AttributeValueTemplate.o \ + BasicNodeExpr.o \ + BooleanExpr.o \ + BooleanResult.o \ + ElementExpr.o \ + ExprLexer.o \ + ExprParser.o \ + FilterExpr.o \ + IdentityExpr.o \ + LocationStep.o \ + MultiplicativeExpr.o \ + NodeSet.o \ + NumberExpr.o \ + NumberResult.o \ + PredicateList.o \ + ParentExpr.o \ + PathExpr.o \ + RelationalExpr.o \ + RootExpr.o \ + StringExpr.o \ + StringResult.o \ + TextExpr.o \ + UnionExpr.o \ + VariableRefExpr.o \ + WildCardExpr.o \ + XPathNames.o + +FUNCTION_CALL_OBJS = \ + BooleanFunctionCall.o \ + ErrorFunctionCall.o \ + FunctionCall.o \ + NodeSetFunctionCall.o \ + NumberFunctionCall.o \ + StringFunctionCall.o + +ALL_OBJS = $(XPATH_OBJS) \ + $(FUNCTION_CALL_OBJS) + +xpath: $(ALL_OBJS) + +AdditiveExpr.o: Expr.h AdditiveExpr.cpp + $(CC) $(INCLUDE_PATHS) -c AdditiveExpr.cpp + + +AttributeExpr.o: Expr.h AttributeExpr.cpp + $(CC) $(INCLUDE_PATHS) -c AttributeExpr.cpp + +AttributeValueTemplate.o: Expr.h AttributeValueTemplate.cpp + $(CC) $(INCLUDE_PATHS) -c AttributeValueTemplate.cpp + +BasicNodeExpr.o: Expr.h BasicNodeExpr.cpp + $(CC) $(INCLUDE_PATHS) -c BasicNodeExpr.cpp + +BooleanExpr.o: Expr.h BooleanExpr.cpp + $(CC) $(INCLUDE_PATHS) -c BooleanExpr.cpp + +BooleanResult.o: ExprResult.h BooleanResult.cpp + $(CC) $(INCLUDE_PATHS) -c BooleanResult.cpp + +ElementExpr.o: Expr.h ElementExpr.cpp + $(CC) $(INCLUDE_PATHS) -c ElementExpr.cpp + +ExprLexer.o: ExprLexer.cpp ExprLexer.h + $(CC) $(INCLUDE_PATHS) -c ExprLexer.cpp + +ExprParser.o: Expr.h ExprParser.cpp ExprParser.h + $(CC) $(INCLUDE_PATHS) -c ExprParser.cpp + +FilterExpr.o: FilterExpr.cpp Expr.h + $(CC) $(INCLUDE_PATHS) -c FilterExpr.cpp + +IdentityExpr.o: Expr.h IdentityExpr.cpp + $(CC) $(INCLUDE_PATHS) -c IdentityExpr.cpp + +LocationStep.o: Expr.h LocationStep.cpp + $(CC) $(INCLUDE_PATHS) -c LocationStep.cpp + +MultiplicativeExpr.o: Expr.h MultiplicativeExpr.cpp + $(CC) $(INCLUDE_PATHS) -c MultiplicativeExpr.cpp + +NodeSet.o: NodeSet.h NodeSet.cpp + $(CC) $(INCLUDE_PATHS) -c NodeSet.cpp + +NumberExpr.o: Expr.h NumberExpr.cpp + $(CC) $(INCLUDE_PATHS) -c NumberExpr.cpp + +NumberResult.o: ExprResult.h NumberResult.cpp + $(CC) $(INCLUDE_PATHS) -c NumberResult.cpp + +ParentExpr.o: Expr.h ParentExpr.cpp + $(CC) $(INCLUDE_PATHS) -c ParentExpr.cpp + +PathExpr.o: Expr.h PathExpr.cpp + $(CC) $(INCLUDE_PATHS) -c PathExpr.cpp + +PredicateList.o: Expr.h PredicateList.cpp + $(CC) $(INCLUDE_PATHS) -c PredicateList.cpp + +RelationalExpr.o: Expr.h RelationalExpr.cpp + $(CC) $(INCLUDE_PATHS) -c RelationalExpr.cpp + +RootExpr.o: Expr.h RootExpr.cpp + $(CC) $(INCLUDE_PATHS) -c RootExpr.cpp + +StringExpr.o: Expr.h StringExpr.cpp + $(CC) $(INCLUDE_PATHS) -c StringExpr.cpp + +StringResult.o: ExprResult.h StringResult.cpp + $(CC) $(INCLUDE_PATHS) -c StringResult.cpp + +TextExpr.o: Expr.h TextExpr.cpp + $(CC) $(INCLUDE_PATHS) -c TextExpr.cpp + +UnionExpr.o: Expr.h UnionExpr.cpp + $(CC) $(INCLUDE_PATHS) -c UnionExpr.cpp + +VariableRefExpr.o: Expr.h VariableRefExpr.cpp + $(CC) $(INCLUDE_PATHS) -c VariableRefExpr.cpp + +WildCardExpr.o: Expr.h WildCardExpr.cpp + $(CC) $(INCLUDE_PATHS) -c WildCardExpr.cpp + +XPathNames.o: FunctionLib.h XPathNames.cpp + $(CC) $(INCLUDE_PATHS) -c XPathNames.cpp + + +######################## +## FunctionCall package +######################## + + +BooleanFunctionCall.o: FunctionLib.h BooleanFunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c BooleanFunctionCall.cpp + +ErrorFunctionCall.o: FunctionLib.h ErrorFunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c ErrorFunctionCall.cpp + +FunctionCall.o: FunctionLib.h FunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c FunctionCall.cpp + +NodeSetFunctionCall.o: FunctionLib.h NodeSetFunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c NodeSetFunctionCall.cpp + +NumberFunctionCall.o: FunctionLib.h NumberFunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c NumberFunctionCall.cpp + +StringFunctionCall.o: FunctionLib.h StringFunctionCall.cpp + $(CC) $(INCLUDE_PATHS) -c StringFunctionCall.cpp diff --git a/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp b/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp new file mode 100644 index 00000000000..107e25f03fb --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/MultiplicativeExpr.cpp @@ -0,0 +1,146 @@ +/* + * 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. + * + * $Id: MultiplicativeExpr.cpp,v 1.1 2000-04-06 07:45:32 kvisco%ziplink.net Exp $ + */ + +/** + * Represents a MultiplicativeExpr, an binary expression that + * performs a multiplicative operation between it's lvalue and rvalue:
+ * * : multiply + * mod : modulus + * div : divide + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:32 $ +**/ + +#include "Expr.h" + +/** + * Creates a new MultiplicativeExpr using the default operator (MULTIPLY) +**/ +MultiplicativeExpr::MultiplicativeExpr() { + this->op = MULTIPLY; + this->leftExpr = 0; + this->rightExpr = 0; +} //-- RelationalExpr + +/** + * Creates a new MultiplicativeExpr using the given operator +**/ +MultiplicativeExpr::MultiplicativeExpr(Expr* leftExpr, Expr* rightExpr, short op) { + this->op = op; + this->leftExpr = leftExpr; + this->rightExpr = rightExpr; +} //-- MultiplicativeExpr + +MultiplicativeExpr::~MultiplicativeExpr() { + delete leftExpr; + delete rightExpr; +} //-- ~MultiplicativeExpr + +/** + * Sets the left side of this MultiplicativeExpr +**/ +void MultiplicativeExpr::setLeftExpr(Expr* leftExpr) { + this->leftExpr = leftExpr; +} //-- setLeftExpr + +/** + * Sets the right side of this MultiplicativeExpr +**/ +void MultiplicativeExpr::setRightExpr(Expr* rightExpr) { + this->rightExpr = rightExpr; +} //-- setRightExpr + +/** + * 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* MultiplicativeExpr::evaluate(Node* context, ContextState* cs) { + + + double rightDbl = Double::NaN; + ExprResult* exprRes = 0; + + if ( rightExpr ) { + exprRes = rightExpr->evaluate(context, cs); + if ( exprRes ) rightDbl = exprRes->numberValue(); + delete exprRes; + } + + double leftDbl = Double::NaN; + if ( leftExpr ) { + exprRes = leftExpr->evaluate(context, cs); + if ( exprRes ) leftDbl = exprRes->numberValue(); + delete exprRes; + } + + double result = 0; + + switch ( op ) { + case DIVIDE: + result = (leftDbl / rightDbl); + break; + case MODULUS: + result = fmod(leftDbl, rightDbl); + break; + default: + result = leftDbl * rightDbl; + break; + } + return new NumberResult(result); +} //-- 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 MultiplicativeExpr::toString(String& str) { + + if ( leftExpr ) leftExpr->toString(str); + else str.append("null"); + + switch ( op ) { + case DIVIDE: + str.append(" div "); + break; + case MODULUS: + str.append(" mod "); + break; + default: + str.append(" * "); + break; + } + if ( rightExpr ) rightExpr->toString(str); + else str.append("null"); + +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp new file mode 100644 index 00000000000..571f7346954 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NodeSet.cpp @@ -0,0 +1,352 @@ +/* + * 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. + * + * Larry Fitzpatrick, OpenText, lef@opentext.com + * -- moved initialization of DEFAULT_SIZE from NodeSet.h to here + * + * Olivier Gerardin, ogerardin@vo.lu + * -- fixed numberValue() + * + * $Id: NodeSet.cpp,v 1.1 2000-04-06 07:45:32 kvisco%ziplink.net Exp $ + */ + +#include "NodeSet.h" +#include +/** + * NodeSet
+ * This class was ported from XSL:P.
+ * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:32 $ +**/ + + + //-------------/ + //- Constants -/ +//-------------/ +const int NodeSet::DEFAULT_SIZE = 25; + + + //----------------/ + //- Constructors -/ +//----------------/ + +/** + * Creates a new NodeSet with the default Size +**/ +NodeSet::NodeSet() { + initialize(DEFAULT_SIZE); +} //-- NodeSet + +/** + * Creates a new NodeSet with the default Size +**/ +NodeSet::NodeSet(int size) { + initialize(size); +} //-- NodeSet + +/** + * Creates a new NodeSet, copying the Node references from the source + * NodeSet +**/ +NodeSet::NodeSet(const NodeSet& source) { + initialize(source.size()); + source.copyInto(*this); +} //--NodeSet + +/** + * Helper method for Constructors +**/ +void NodeSet::initialize(int size) { + elements = new Node*[size]; + for ( int i = 0; i < size; i++ ) elements[i] = 0; + elementCount = 0; + bufferSize = size; + initialSize = size; +} //-- initialize + +/** + * Destructor for NodeSet +**/ +NodeSet::~NodeSet() { + delete [] elements; +} //-- ~NodeSet + +/** + * Adds the specified Node to this NodeSet if it is not already + * contained within in this NodeSet. + * @param node the Node to add to the NodeSet + * @return true if the Node is added to the NodeSet +**/ +MBool NodeSet::add(Node* node) { + if (!contains(node)) { + if (elementCount == bufferSize) increaseSize(); + elements[elementCount++] = node; + return MB_TRUE; + } + return MB_FALSE; +} //-- add + +/** + * Adds the specified Node to the NodeSet at the specified index, + * as long as the Node is not already contained within the set + * @param node the Node to add to the NodeSet + * @return true if the Node is added to the NodeSet. If the index is + * out of bounds the Node will not be added to the set and false will be returned. +**/ +MBool NodeSet::add(int index, Node* node) +{ + if ((index < 0) || (index > elementCount)) return MB_FALSE; + + if (contains(node)) return MB_FALSE; + + // make sure we have room to add the object + if (elementCount == bufferSize) increaseSize(); + + if (index == elementCount) { + elements[elementCount++] = node; + } + else { + shiftUp(index); + elements[index] = node; + ++elementCount; + } + return MB_TRUE; +} //-- add + +/** + * Removes all elements from the list +**/ +void NodeSet::clear() { + for (int i = 0; i < elementCount; i++) { + elements[i] = 0; + } + elementCount = 0; +} //-- clear + +/** + * Returns true if the specified Node is contained in the set. + * if the specfied Node is null, then if the NodeSet contains a null + * value, true will be returned. + * @param node the element to search the NodeSet for + * @return true if specified Node is contained in the NodeSet +**/ +MBool NodeSet::contains(Node* node) { + return (MBool)(indexOf(node) >= 0); +} //-- contains + +/** + * Copies the elements of this NodeSet, into the destination NodeSet +**/ +void NodeSet::copyInto(NodeSet& dest) const { + for ( int i = 0; i < elementCount; i++ ) dest.add(elements[i]); +} //-- copyInto + +/** + * Compares the specified object with this NodeSet for equality. + * Returns true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. + * @return true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. +**/ +MBool NodeSet::equals(NodeSet* nodeSet) { + if (!nodeSet) return MB_FALSE; + if (nodeSet->size() != size()) return MB_FALSE; + + for (int i = 0; i < size(); i++) { + if (!nodeSet->contains(get(i))) return MB_FALSE; + } + return MB_TRUE; +} //-- equals + +/** + * Returns the Node at the specified position in this NodeSet. + * @param index the position of the Node to return +**/ +Node* NodeSet::get(int index) { + if ((index < 0) || index >= elementCount) return 0; + return elements[index]; +} //-- get + + +/** + * Returns the index of the specified Node, + * or -1 if the Node is not contained in the NodeSet + * @param node the Node to get the index for +**/ +int NodeSet::indexOf(Node* node) { + for (int i = 0; i < elementCount; i++) + if (node == elements[i]) return i; + return -1; +} //-- indexOf + +/** + * Returns true if there are no Nodes in the NodeSet. + * @return true if there are no Nodes in the NodeSet. +**/ +MBool NodeSet::isEmpty() { + return (elementCount == 0) ? MB_TRUE : MB_FALSE; +} //-- isEmpty + +/** + * Removes the Node at the specified index from the NodeSet + * @param index the position in the NodeSet to remove the Node from + * @return the Node that was removed from the list +**/ +Node* NodeSet::remove(int index) { + + if ((index < 0) || (index >= elementCount)) return 0; + + Node* node = elements[index]; + shiftDown(index+1); + --elementCount; + return node; +} //-- remove + +/** + * Removes the the specified Node from the NodeSet + * @param node the Node to remove from the NodeSet + * @return true if the Node was removed from the list +**/ +MBool NodeSet::remove(Node* node) { + int index = indexOf(node); + + if (index > -1) { + remove(index); + } + else return MB_FALSE; + + return MB_TRUE; +} //-- remove + + +/** + * Returns the number of elements in the NodeSet + * @return the number of elements in the NodeSet +**/ +int NodeSet::size() const{ + return elementCount; +} //-- size + +/** + * Creates a String representation of this NodeSet + * @param str the destination string to append the String representation to. +**/ +void NodeSet::toString(String& str) { + str.append("#NodeSet"); +} //-- toString + + //-------------------/ + //- Private Methods -/ +//-------------------/ + +/** + * increase the NodeSet capacity by a factor of its initial size +**/ +void NodeSet::increaseSize() { + + bufferSize += bufferSize; + Node** tmpNodes = elements; + elements = new Node*[bufferSize]; + int i=0; + for (i=0;i < elementCount; i++) elements[i] = tmpNodes[i]; + for (;i elementCount)) return; + + //-- from Java + //-- System.arraycopy(elements, index, elements, index - 1, elementCount - index); + for (int i = index; i < elementCount; i++) { + elements[i-1] = elements[i]; + } + + elements[elementCount-1] = 0; +} //-- shiftDown + +/** + * Shifts all elements at the specified index up by 1 +**/ +void NodeSet::shiftUp(int index) { + if (index == elementCount) return; + if (elementCount == bufferSize) increaseSize(); + + //-- from Java + //-- System.arraycopy(elements, index, elements, index + 1, elementCount - index); + for (int i = elementCount; i > index; i--) { + elements[i] = elements[i-1]; + } +} //-- shiftUp + + //------------------------------------/ + //- Virtual Methods from: ExprResult -/ +//------------------------------------/ + +/** + * Returns the type of ExprResult represented + * @return the type of ExprResult represented +**/ +short NodeSet::getResultType() { + return ExprResult::NODESET; +} //-- getResultType + +/** + * Converts this ExprResult to a Boolean (MBool) value + * @return the Boolean value +**/ +MBool NodeSet::booleanValue() { + return (MBool) (size() > 0); +} //- booleanValue + +/** + * Converts this ExprResult to a Number (double) value + * @return the Number value +**/ +double NodeSet::numberValue() { + // OG+ + // As per the XPath spec, the number value of a node-set is the number value + // of its string value. + String str; + stringValue(str); + Double dbl(str); + return dbl.doubleValue(); + // OG- +} //-- numberValue + +/** + * Creates a String representation of this ExprResult + * @param str the destination string to append the String representation to. +**/ +void NodeSet::stringValue(String& str) { + if ( size()>0) { + XMLDOMUtils::getNodeValue(get(0), &str); + } +} //-- stringValue + diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSet.h b/mozilla/extensions/transformiix/source/xpath/NodeSet.h new file mode 100644 index 00000000000..a5676d0a76a --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NodeSet.h @@ -0,0 +1,241 @@ +/* + * 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. + * + * Larry Fitzpatrick, OpenText, lef@opentext.com + * -- moved initialization of DEFAULT_SIZE to NodeSet.cpp + * + * $Id: NodeSet.h,v 1.1 2000-04-06 07:45:33 kvisco%ziplink.net Exp $ + */ + +/** + * NodeSet + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:33 $ +**/ + +#ifndef TRANSFRMX_NODESET_H +#define TRANSFRMX_NODESET_H + +#include "MITREObject.h" +#include "dom.h" +#include "ExprResult.h" +#include "XMLDOMUtils.h" + +class NodeSet : public ExprResult { + + +public: + + //----------------/ + //- Constructors -/ + //----------------/ + + /** + * Creates a new NodeSet with the default Size + **/ + NodeSet(); + + /** + * Creates a new NodeSet with the specified Size + **/ + NodeSet(int size); + + /** + * Creates a new NodeSet using the given NodeSet + **/ + NodeSet(const NodeSet& source); + + /** + * Destructor for NodeSet, will not delete Node References + **/ + virtual ~NodeSet(); + + /** + * Adds the specified Node to this NodeSet if it is not already + * contained within in this NodeSet. + * @param node the Node to add to the NodeSet + * @return true if the Node is added to the NodeSet + **/ + MBool add(Node* node); + + /** + * Adds the specified Node to the NodeSet at the specified index, + * as long as the Node is not already contained within the set + * @param node the Node to add to the NodeSet + * @return true if the Node is added to the NodeSet + * @exception IndexOutOfBoundsException + **/ + MBool add(int index, Node* node); + + /** + * Removes all elements from the list + **/ + void clear(); + + /** + * Returns true if the specified Node is contained in the set. + * if the specfied Node is null, then if the NodeSet contains a null + * value, true will be returned. + * @param node the element to search the NodeSet for + * @return true if specified Node is contained in the NodeSet + **/ + MBool contains(Node* node); + + /** + * Copies the elements of this NodeSet, into the destination NodeSet + **/ + void copyInto(NodeSet& dest) const; + + /** + * Compares the specified object with this NodeSet for equality. + * Returns true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. + * @return true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. + **/ + MBool equals(NodeSet* nodeSet); + + /** + * Returns the Node at the specified position in this NodeSet. + * @param index the position of the Node to return + * @exception IndexOutOfBoundsException + **/ + Node* get(int index); + + + /** + * Returns the index of the specified Node, + * or -1 if the Node is not contained in the NodeSet + * @param node the Node to get the index for + **/ + int indexOf(Node* node); + + /** + * Returns true if there are no Nodes in the NodeSet. + * @return true if there are no Nodes in the NodeSet. + **/ + MBool isEmpty(); + + /** + * Removes the Node at the specified index from the NodeSet + * @param index the position in the NodeSet to remove the Node from + * @return the Node that was removed from the list + **/ + Node* remove(int index); + + /** + * Removes the the specified Node from the NodeSet + * @param node the Node to remove from the NodeSet + * @return true if the Node was removed from the list + **/ + MBool remove(Node* node); + + + /** + * Returns the number of elements in the NodeSet + * @return the number of elements in the NodeSet + **/ + int size() const; + + /** + * Creates a String representation of this NodeSet + * @param str the destination string to append the String representation to. + **/ + void toString(String& str); + + //------------------------------------/ + //- Virtual Methods from: ExprResult -/ + //------------------------------------/ + + /** + * Returns the type of ExprResult represented + * @return the type of ExprResult represented + **/ + virtual short getResultType(); + + /** + * Converts this ExprResult to a Boolean (MBool) value + * @return the Boolean value + **/ + virtual MBool booleanValue(); + + /** + * Converts this ExprResult to a Number (double) value + * @return the Number value + **/ + virtual double numberValue(); + + /** + * Creates a String representation of this ExprResult + * @param str the destination string to append the String representation to. + **/ + virtual void stringValue(String& str); + +private: + + + //-------------------/ + //- Private Members -/ + //-------------------/ + + static const int DEFAULT_SIZE; + + Node** elements; + + int initialSize; + int bufferSize; + + /** + * The next available location in the elements array + **/ + int elementCount; + + //-------------------/ + //- Private Methods -/ + //-------------------/ + + /** + * Helper method for constructors + **/ + void initialize(int size); + + /** + * increase the NodeSet capacity by a factor of its initial size + **/ + void increaseSize(); + + /** + * Shifts all elements at the specified index to down by 1 + **/ + void shiftDown(int index); + + /** + * Shifts all elements at the specified index up by 1 + **/ + void shiftUp(int index); + +}; //-- NodeSet + +#endif diff --git a/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp new file mode 100644 index 00000000000..c0702802a50 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NodeSetFunctionCall.cpp @@ -0,0 +1,166 @@ +/* + * 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. + * + * $Id: NodeSetFunctionCall.cpp,v 1.1 2000-04-06 07:45:34 kvisco%ziplink.net Exp $ + */ + +/** + * NodeSetFunctionCall + * A representation of the XPath NodeSet funtions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:34 $ +**/ + +#include "FunctionLib.h" + +/** + * Creates a default NodeSetFunctionCall. The Position function + * is the default +**/ +NodeSetFunctionCall::NodeSetFunctionCall() : FunctionCall(XPathNames::POSITION_FN) { + type = POSITION; +} //-- NodeSetFunctionCall + +/** + * Creates a NodeSetFunctionCall of the given type +**/ +NodeSetFunctionCall::NodeSetFunctionCall(short type) : FunctionCall() { + this->type = type; + switch ( type ) { + case COUNT : + FunctionCall::setName(XPathNames::COUNT_FN); + break; + case LAST : + FunctionCall::setName(XPathNames::LAST_FN); + break; + case LOCAL_NAME: + FunctionCall::setName(XPathNames::LOCAL_NAME_FN); + break; + case NAME: + FunctionCall::setName(XPathNames::NAME_FN); + break; + case NAMESPACE_URI: + FunctionCall::setName(XPathNames::NAMESPACE_URI_FN); + break; + default: + FunctionCall::setName(XPathNames::POSITION_FN); + break; + } +} //-- NodeSetFunctionCall + +/** + * 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* NodeSetFunctionCall::evaluate(Node* context, ContextState* cs) { + NodeSet* nodeSet = (NodeSet*)cs->getNodeSetStack()->peek(); + ListIterator* iter = params.iterator(); + Int32 argc = params.getLength(); + ExprResult* result = 0; + Expr* param = 0; + switch ( type ) { + case COUNT : + if ( argc == 1 ) { + double count = 0.0; + param = (Expr*)iter->next(); + ExprResult* exprResult = param->evaluate(context, cs); + if ( exprResult->getResultType() != ExprResult::NODESET ) { + String err("NodeSet expected as argument to count()"); + cs->recieveError(err); + } + else count = (double) ((NodeSet*)exprResult)->size(); + delete exprResult; + result = new NumberResult(count); + } + else { + String err(INVALID_PARAM_COUNT); + this->toString(err); + cs->recieveError(err); + result = new NumberResult(0.0); + } + break; + case LAST : + if ( nodeSet ) result = new NumberResult((double)nodeSet->size()); + else result = new NumberResult(0.0); + break; + case LOCAL_NAME: + case NAME: + case NAMESPACE_URI : + { + String name; + Node* node = 0; + if ( argc < 2 ) { + + //-- check for optional arg + if ( argc == 1) { + param = (Expr*)iter->next(); + ExprResult* exprResult = param->evaluate(context, cs); + if ( exprResult->getResultType() != ExprResult::NODESET ) { + String err("NodeSet expected as argument to "); + this->toString(err); + cs->recieveError(err); + } + else { + NodeSet* nodes = (NodeSet*)exprResult; + if (nodes->size() > 0) node = nodes->get(0); + } + delete exprResult; + } + if ( !node ) node = context; + + switch ( type ) { + case LOCAL_NAME : + XMLUtils::getLocalPart(node->getNodeName(),name); + break; + case NAMESPACE_URI : + XMLUtils::getNameSpace(node->getNodeName(),name); + break; + default: + name = node->getNodeName(); + break; + } + result = new StringResult(name); + } + else { + String err(INVALID_PARAM_COUNT); + this->toString(err); + cs->recieveError(err); + result = new StringResult(""); + } + break; + } + default : //-- position + if ( nodeSet ) + result = new NumberResult((double)nodeSet->indexOf(context)+1); + else + result = new NumberResult(0.0); + break; + } + delete iter; + return result; +} //-- evaluate + + diff --git a/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp b/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp new file mode 100644 index 00000000000..b73905bdf32 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NumberExpr.cpp @@ -0,0 +1,66 @@ +/* + * 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. + * + * $Id: NumberExpr.cpp,v 1.1 2000-04-06 07:45:34 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + + //--------------/ + //- NumberExpr -/ +//--------------/ + +NumberExpr::NumberExpr() { + numberResult.setValue(0.0); +} //-- NumberExpr + +NumberExpr::NumberExpr(double dbl) { + numberResult.setValue(dbl); +} //-- NumberExpr + +NumberExpr::~NumberExpr() { +} //-- ~NumberExpr + +/** + * 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* NumberExpr::evaluate(Node* context, ContextState* cs) { + return new NumberResult(numberResult); +} //-- 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 NumberExpr::toString(String& str) { + numberResult.stringValue(str); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp new file mode 100644 index 00000000000..11de08d466e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NumberFunctionCall.cpp @@ -0,0 +1,146 @@ +/* + * 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): + * Olivier Gerardin, ogerardin@vo.lu + * -- original author. + */ + +/** + * NumberFunctionCall + * A representation of the XPath Number funtions + * @author Olivier Gerardin +**/ + +#include "FunctionLib.h" + +/** + * Creates a default NumberFunctionCall. The number() function + * is the default +**/ +NumberFunctionCall::NumberFunctionCall() : FunctionCall(XPathNames::NUMBER_FN) { + type = NUMBER; +} //-- NumberFunctionCall + +/** + * Creates a NumberFunctionCall of the given type +**/ +NumberFunctionCall::NumberFunctionCall(short type) : FunctionCall() { + this->type = type; + switch ( type ) { + case ROUND : + FunctionCall::setName(XPathNames::ROUND_FN); + break; + case CEILING : + FunctionCall::setName(XPathNames::CEILING_FN); + break; + case FLOOR : + FunctionCall::setName(XPathNames::FLOOR_FN); + break; + case NUMBER : + default : + FunctionCall::setName(XPathNames::NUMBER_FN); + break; + } +} //-- NumberFunctionCall + +/** + * 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* NumberFunctionCall::evaluate(Node* context, ContextState* cs) { + NumberResult* result = new NumberResult(); + ListIterator* iter = params.iterator(); + int argc = params.getLength(); + Expr* param = 0; + String err; + + switch ( type ) { + case CEILING : + if ( requireParams(1, 1, cs) ) { + double dbl = evaluateToNumber((Expr*)iter->next(), context, cs); + result->setValue(ceil(dbl)); + } + else { + result->setValue(0.0); + } + break; + + case FLOOR : + if ( requireParams(1, 1, cs) ) { + double dbl = evaluateToNumber((Expr*)iter->next(), context, cs); + result->setValue(floor(dbl)); + } + else { + result->setValue(0.0); + } + break; + + case ROUND : + if ( requireParams(1, 1, cs) ) { + double dbl = evaluateToNumber((Expr*)iter->next(), context, cs); + double res = rint(dbl); + if ((dbl>0.0) && (res == dbl-0.5)) { + // fix for native round function from math library (rint()) which does not + // match the XPath spec for positive half values + result->setValue(res+1.0); + } + else { + result->setValue(res); + } + break; + } + else result->setValue(0.0); + break; + + case NUMBER : + default : //-- number( object? ) + if ( requireParams(0, 1, cs) ) { + if (iter->hasNext()) { + param = (Expr*) iter->next(); + ExprResult* exprResult = param->evaluate(context, cs); + result->setValue(exprResult->numberValue()); + delete exprResult; + } + else { + String resultStr; + String temp; + XMLDOMUtils::getNodeValue(context, &temp); + if ( cs->isStripSpaceAllowed(context) ) { + XMLUtils::stripSpace(temp, resultStr); + } + else { + resultStr.append(temp); + } + Double dbl(resultStr); + result->setValue(dbl.doubleValue()); + } + } + else { + result = new NumberResult(0.0); + } + break; + } + delete iter; + return result; +} //-- evaluate + diff --git a/mozilla/extensions/transformiix/source/xpath/NumberResult.cpp b/mozilla/extensions/transformiix/source/xpath/NumberResult.cpp new file mode 100644 index 00000000000..834f4f720a2 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/NumberResult.cpp @@ -0,0 +1,112 @@ +/* + * 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. + * + * $Id: NumberResult.cpp,v 1.1 2000-04-06 07:45:35 kvisco%ziplink.net Exp $ + */ + +/** + * NumberResult + * Represents the a number as the result of evaluating an Expr + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:35 $ +**/ + +#include "ExprResult.h" + +/** + * Default Constructor +**/ +NumberResult::NumberResult() { + value = 0.0; +} //-- NumberResult + +NumberResult::NumberResult(const NumberResult& nbrResult) { + this->value = nbrResult.getValue(); +} //-- NumberResult + +/** + * Creates a new NumberResult with the value of the given double parameter + * @param dbl the double to use for initialization of this NumberResult's value +**/ +NumberResult::NumberResult(double dbl) { + this->value = dbl; +} //-- NumberResult + +/** + * Returns the value of this NumberResult + * @return the value of this NumberResult +**/ +double NumberResult::getValue() const { + return this->value; +} //-- getValue + +/** + * +**/ +MBool NumberResult::isNaN() const { + return Double::isNaN(value); +} //-- isNaN +/** + * Sets the value of this NumberResult + * @param dbl the double to use for this NumberResult's value +**/ +void NumberResult::setValue(double dbl) { + this->value = dbl; +} //-- setValue + +/** + * Sets the value of this NumberResult + * @param nbrResult the NumberResult to use for setting this NumberResult's value +**/ +void NumberResult::setValue(const NumberResult& nbrResult) { + this->value = nbrResult.getValue(); +} //-- setValue + +/* + * Virtual Methods from ExprResult +*/ + +short NumberResult::getResultType() { + return ExprResult::NUMBER; +} //-- getResultType + +void NumberResult::stringValue(String& str) { + int intVal = (int)value; + if (intVal == value) { //-- no fraction + Integer::toString(intVal, str); + } + else Double::toString(value, str); +} //-- stringValue + +MBool NumberResult::booleanValue() { + // OG+ + // As per the XPath spec, the boolean value of a number is true if and only if + // it is neither positive 0 nor negative 0 nor NaN + return (MBool)(this->value != 0.0 && this->value != -0.0 && ! isNaN()); + // OG- +} //-- booleanValue + +double NumberResult::numberValue() { + return this->value; +} //-- numberValue + diff --git a/mozilla/extensions/transformiix/source/xpath/ParentExpr.cpp b/mozilla/extensions/transformiix/source/xpath/ParentExpr.cpp new file mode 100644 index 00000000000..0535823fb4e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/ParentExpr.cpp @@ -0,0 +1,59 @@ +/* + * 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. + * + * $Id: ParentExpr.cpp,v 1.1 2000-04-06 07:45:35 kvisco%ziplink.net Exp $ + */ + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:35 $ +**/ +#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* ParentExpr::evaluate(Node* context, ContextState* cs) { + NodeSet* nodeSet = new NodeSet(); + if ( !context ) return nodeSet; + Node* node = context->getParentNode(); + if (node) nodeSet->add(node); + return nodeSet; +} //-- evaluate + +/** + * 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 ParentExpr::toString(String& dest) { + dest.append(".."); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/Parser.cpp b/mozilla/extensions/transformiix/source/xpath/Parser.cpp new file mode 100644 index 00000000000..06452776e3e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/Parser.cpp @@ -0,0 +1,185 @@ +/* + * 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. + * + * $Id: Parser.cpp,v 1.1 2000-04-06 07:45:36 kvisco%ziplink.net Exp $ + */ + +/** + * Test App for Expressions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:36 $ +**/ + +#include +#include "String.h" +#include "Expr.h" +#include "ExprLexer.h" +#include "ExprParser.h" +#include "NamedMap.h" +#include "ExprResult.h" + +void main(int argc, char** argv) { + + + cout <value; + + //-- do padding + for ( int i = token->value.length(); i < 20; i++) cout<<" "; + + //-- print token type + switch (token->type) { + case Token::AT_SIGN: + cout << "#AT_SIGN"; + break; + case Token::PARENT_OP : + cout<<"#PARENT_OP"; + break; + case Token::ANCESTOR_OP : + cout<<"#ANCESTOR_OP"; + break; + case Token::L_PAREN : + cout<<"#L_PAREN"; + break; + case Token::R_PAREN : + cout<<"#R_PAREN"; + break; + case Token::L_BRACKET: + cout<<"#L_BRACKET"; + break; + case Token::R_BRACKET: + cout<<"#R_BRACKET"; + break; + case Token::COMMA: + cout<<"#COMMA"; + break; + case Token::LITERAL: + cout<<"#LITERAL"; + break; + case Token::CNAME: + cout<<"#CNAME"; + break; + case Token::COMMENT: + cout<<"#COMMENT"; + break; + case Token::NODE: + cout<<"#NODE"; + break; + case Token::PI: + cout<<"#PI"; + break; + case Token::TEXT: + cout<<"#TEXT"; + break; + case Token::FUNCTION_NAME: + cout<<"#FUNCTION_NAME"; + break; + case Token::WILD_CARD: + cout << "#WILDCARD"; + break; + case Token::NUMBER: + cout << "#NUMBER"; + break; + case Token::PARENT_NODE : + cout << "#PARENT_NODE"; + break; + case Token::SELF_NODE : + cout << "#SELF_NODE"; + break; + case Token::VAR_REFERENCE: + cout << "#VAR_REFERENCE"; + case Token::AXIS_IDENTIFIER: + cout << "#AXIS_IDENTIFIER"; + break; + default: + if ( lexer.isOperatorToken(token) ) { + cout << "#operator"; + } + else cout<<"#unknown"; + break; + } + } + else cout<<"NULL"; + cout<toString(resultString); + cout << "result: "<toString(resultString); + cout << "result of avt: "<hasNext() ) { + iter->next(); + PathExprItem* pxi = (PathExprItem*)iter->remove(); + delete pxi->pExpr; + delete pxi; + } + delete iter; +} //-- ~PathExpr + +/** + * Adds the PatternExpr to this PathExpr + * @param expr the Expr to add to this PathExpr + * @param index the index at which to add the given Expr +**/ +void PathExpr::addPatternExpr(int index, PatternExpr* expr, short ancestryOp) { + if (expr) { + PathExprItem* pxi = new PathExprItem; + pxi->pExpr = expr; + pxi->ancestryOp = ancestryOp; + expressions.insert(index, pxi); + } +} //-- addPattenExpr + +/** + * Adds the PatternExpr to this PathExpr + * @param expr the Expr to add to this PathExpr +**/ +void PathExpr::addPatternExpr(PatternExpr* expr, short ancestryOp) { + if (expr) { + PathExprItem* pxi = new PathExprItem; + pxi->pExpr = expr; + pxi->ancestryOp = ancestryOp; + expressions.add(pxi); + } +} //-- addPattenExpr + +MBool PathExpr::isAbsolute() { + if ( expressions.getLength() > 0 ) { + ListIterator* iter = expressions.iterator(); + PathExprItem* pxi = (PathExprItem*)iter->next(); + delete iter; + return (pxi->ancestryOp != RELATIVE_OP); + } + return MB_FALSE; +} //-- isAbsolute + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ +//------------------------------------/ + +/** + * 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* PathExpr::evaluate(Node* context, ContextState* cs) { + //-- add selectExpr functionality here + + if ( (!context) || (expressions.getLength() == 0)) + return new NodeSet(0); + + NodeSet* nodes = new NodeSet(); + + if ((isAbsolute()) && (context->getNodeType() != Node::DOCUMENT_NODE)) + nodes->add(context->getOwnerDocument()); + else + nodes->add(context); + + + ListIterator* iter = expressions.iterator(); + + MBool ancestorMode = MB_FALSE; + while ( iter->hasNext() ) { + + PathExprItem* pxi = (PathExprItem*)iter->next(); + ancestorMode = (ancestorMode || (pxi->ancestryOp == ANCESTOR_OP)); + NodeSet* tmpNodes = 0; + cs->getNodeSetStack()->push(nodes); + for (int i = 0; i < nodes->size(); i++) { + Node* node = nodes->get(i); +#if 0 + NodeSet* xNodes = (NodeSet*) pxi->pExpr->evaluate(node, cs); +#else + ExprResult *res = pxi->pExpr->evaluate(node, cs); + if (!res || res->getResultType() != ExprResult::NODESET) + continue; + NodeSet* xNodes = (NodeSet *) res; +#endif + if ( tmpNodes ) { + xNodes->copyInto(*tmpNodes); + } + else { + tmpNodes = xNodes; + xNodes = 0; + } + delete xNodes; + //-- handle ancestorMode + if ( ancestorMode ) fromDescendants(pxi->pExpr, node, cs, tmpNodes); + } + delete (NodeSet*) cs->getNodeSetStack()->pop(); + nodes = tmpNodes; + if ( nodes->size() == 0 ) break; + } + delete iter; + + return nodes; +} //-- evaluate + +/** + * Selects from the descendants of the context node + * all nodes that match the PatternExpr + * -- this will be moving to a Utility class +**/ +void PathExpr::fromDescendants + (PatternExpr* pExpr, Node* context, ContextState* cs, NodeSet* nodes) +{ + + if (( !context ) || (! pExpr )) return; + + NodeList* nl = context->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++) { + Node* child = nl->item(i); + if (pExpr->matches(child, context, cs)) + nodes->add(child); + //-- check childs descendants + if (child->hasChildNodes()) + fromDescendants(pExpr, child, cs, nodes); + } +} //-- fromDescendants + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double PathExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + + if ( matches(node, context, cs) ) { + int size = expressions.getLength(); + if ( size == 1) { + ListIterator* iter = expressions.iterator(); + PathExprItem* pxi = (PathExprItem*)iter->next(); + delete iter; + return pxi->pExpr->getDefaultPriority(node, context, cs); + } + else if ( size > 1 ) { + return 0.5; + } + } + return Double::NEGATIVE_INFINITY; +} //-- getDefaultPriority + +/** + * Determines whether this PatternExpr matches the given node within + * the given context +**/ +MBool PathExpr::matches(Node* node, Node* context, ContextState* cs) { + + if ( (!node) || (expressions.getLength() == 0)) + return MB_FALSE; + + NodeSet nodes; + nodes.add(node); + + + ListIterator* iter = expressions.iterator(); + iter->reverse(); + + NodeSet tmpNodes; + MBool result = MB_FALSE; + while ( iter->hasNext() ) { + + PathExprItem* pxi = (PathExprItem*)iter->next(); + for (int i = 0; i < nodes.size(); i++) { + + Node* tnode = nodes.get(i); + + //-- select node's parent or ancestors + switch (pxi->ancestryOp) { + case ANCESTOR_OP: + { + Node* parent = tnode; + while (parent = cs->getParentNode(parent)) { + if (pxi->pExpr->matches(tnode, parent, cs)) + tmpNodes.add(parent); + } + break; + } + case PARENT_OP: + { + Node* parent = cs->getParentNode(tnode); + if (parent) { + if (pxi->pExpr->matches(tnode, parent, cs)) + tmpNodes.add(parent); + } + break; + } + default: + if ( !iter->hasNext() ) { + result = pxi->pExpr->matches(tnode, context, cs); + } + else { + //-- error in expression + tmpNodes.clear(); + nodes.clear(); + delete iter; + return MB_FALSE; + } + break; + } + } //-- for + nodes.clear(); + tmpNodes.copyInto(nodes); + tmpNodes.clear(); + } + + delete iter; + + if ( this->isAbsolute()) { + Node* doc = node->getOwnerDocument(); + return (MBool) nodes.contains(doc); + } + + return (MBool) (result || (nodes.size() > 0)); + +} //-- matches + + +/** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. +**/ +void PathExpr::toString(String& dest) { + ListIterator* iter = expressions.iterator(); + while ( iter->hasNext() ) { + //-- set operator + PathExprItem* pxi = (PathExprItem*)iter->next(); + switch ( pxi->ancestryOp ) { + case ANCESTOR_OP: + dest.append("//"); + break; + case PARENT_OP: + dest.append('/'); + break; + default: + break; + } + pxi->pExpr->toString(dest); + } + delete iter; +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp new file mode 100644 index 00000000000..89f577deae1 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/PredicateList.cpp @@ -0,0 +1,143 @@ +/* + * 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. + * + * $Id: PredicateList.cpp,v 1.1 2000-04-06 07:45:37 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * Represents an ordered list of Predicates, + * for use with Step and Filter Expressions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:37 $ +**/ +//-- PredicateList Implementation --/ + +PredicateList::PredicateList() { +} //-- PredicateList + +/** + * Destructor, will delete all Expressions in the list, so remove + * any you may need +**/ +PredicateList::~PredicateList() { + //cout << "-PredicateList() - start"<hasNext() ) { + iter->next(); + Expr* expr = (Expr*) iter->remove(); + delete expr; + } + delete iter; + //cout << "~PredicateList() - end"<size()); + + Stack* nsStack = cs->getNodeSetStack(); + nsStack->push(nodes); + while ( iter->hasNext() ) { + int nIdx = 0; + + Expr* expr = (Expr*) iter->next(); + //-- filter each node currently in the NodeSet + for (nIdx = 0; nIdx < nodes->size(); nIdx++) { + + Node* node = nodes->get(nIdx); + + //-- if expr evaluates to true using the node as it's context, + //-- then we can keep it, otherwise add to remove list + ExprResult* exprResult = expr->evaluate(node,cs); + if ( !exprResult ) { + cout << "ExprResult == null" << endl; + } + else { + switch(exprResult->getResultType()) { + case ExprResult::NUMBER : + { + //-- handle default position() + int position = nodes->indexOf(node)+1; + if (( position <= 0 ) || + ( ((double)position) != exprResult->numberValue())) + remNodes.add(node); + + break; + } + default: + if (! exprResult->booleanValue() ) remNodes.add(node); + break; + } + } + } + //-- remove unmatched nodes + for (nIdx = 0; nIdx < remNodes.size(); nIdx++) + nodes->remove(remNodes.get(nIdx)); + //-- clear remove list + remNodes.clear(); + } + nsStack->pop(); + delete iter; +} //-- evaluatePredicates + +/** + * returns true if this predicate list is empty +**/ +MBool PredicateList::isEmpty() { + return (MBool)(predicates.getLength() == 0); +} //-- isEmpty + +/** + * Removes the given Expr from the list + * @param expr the Expr to remove from the list +**/ +Expr* PredicateList::remove(Expr* expr) { + return (Expr*)predicates.remove(expr); +} //-- remove + +void PredicateList::toString(String& dest) { + + ListIterator* iter = predicates.iterator(); + + while ( iter->hasNext() ) { + Expr* expr = (Expr*) iter->next(); + dest.append("["); + expr->toString(dest); + dest.append("]"); + } + delete iter; + +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp new file mode 100644 index 00000000000..be40ac9e66e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/RelationalExpr.cpp @@ -0,0 +1,208 @@ +/* + * 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. + * + * $Id: RelationalExpr.cpp,v 1.1 2000-04-06 07:45:38 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + + //------------------/ + //- RelationalExpr -/ +//------------------/ + +RelationalExpr::RelationalExpr() { + this->op = EQUAL; + this->leftExpr = 0; + this->rightExpr = 0; +} //-- RelationalExpr + +RelationalExpr::RelationalExpr(Expr* leftExpr, Expr* rightExpr, short op) { + this->op = op; + this->leftExpr = leftExpr; + this->rightExpr = rightExpr; +} //-- RelationalExpr + +RelationalExpr::~RelationalExpr() { + delete leftExpr; + delete rightExpr; +} //-- ~RelationalExpr + +/** + * Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4) +**/ +MBool RelationalExpr::compareResults(ExprResult* left, ExprResult* right) { + + + short ltype = left->getResultType(); + short rtype = right->getResultType(); + + MBool result = MB_FALSE; + + //-- handle case for just Left NodeSet or Both NodeSets + if (ltype == ExprResult::NODESET) { + NodeSet* nodeSet = (NodeSet*)left; + for ( int i = 0; i < nodeSet->size(); i++) { + String str; + Node* node = nodeSet->get(i); + XMLDOMUtils::getNodeValue(node, &str); + StringResult strResult(str); + result = compareResults(&strResult, right); + if ( result ) break; + } + } + //-- handle case for Just Right NodeSet + else if ( rtype == ExprResult::NODESET) { + NodeSet* nodeSet = (NodeSet*)right; + for ( int i = 0; i < nodeSet->size(); i++) { + String str; + Node* node = nodeSet->get(i); + XMLDOMUtils::getNodeValue(node, &str); + StringResult strResult(str); + result = compareResults(left, &strResult); + if ( result ) break; + } + } + //-- neither NodeSet + else { + if ( op == NOT_EQUAL) { + + if ((ltype == ExprResult::BOOLEAN) + || (rtype == ExprResult::BOOLEAN)) { + result = (left->booleanValue() != right->booleanValue()); + } + else if ((ltype == ExprResult::NUMBER) || + (rtype == ExprResult::NUMBER)) { + result = (left->numberValue() != right->numberValue()); + } + else { + String lStr; + left->stringValue(lStr); + String rStr; + right->stringValue(rStr); + result = !lStr.isEqual(rStr); + } + } + else if ( op == EQUAL) { + + if ((ltype == ExprResult::BOOLEAN) + || (rtype == ExprResult::BOOLEAN)) { + result = (left->booleanValue() == right->booleanValue()); + } + else if ((ltype == ExprResult::NUMBER) || + (rtype == ExprResult::NUMBER)) { + result = (left->numberValue() == right->numberValue()); + } + else { + String lStr; + left->stringValue(lStr); + String rStr; + right->stringValue(rStr); + result = lStr.isEqual(rStr); + } + + } + else { + double leftDbl = left->numberValue(); + double rightDbl = right->numberValue(); + switch( op ) { + case LESS_THAN: + result = (MBool) (leftDbl < rightDbl); + break; + case LESS_OR_EQUAL: + result = (MBool) (leftDbl <= rightDbl); + break; + case GREATER_THAN : + result = (MBool) (leftDbl > rightDbl); + break; + case GREATER_OR_EQUAL: + result = (MBool) (leftDbl >= rightDbl); + break; + } + } + } + return result; +} //-- compareResult + +/** + * 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* RelationalExpr::evaluate(Node* context, ContextState* cs) { + + //-- get result of left expression + ExprResult* lResult = 0; + if ( leftExpr ) lResult = leftExpr->evaluate(context, cs); + else return new BooleanResult(); + + //-- get result of right expr + ExprResult* rResult = 0; + if ( rightExpr ) rResult = rightExpr->evaluate(context, cs); + else { + delete lResult; + return new BooleanResult(); + } + return new BooleanResult(compareResults(lResult, rResult)); +} //-- 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 RelationalExpr::toString(String& str) { + + if ( leftExpr ) leftExpr->toString(str); + else str.append("null"); + + switch ( op ) { + case NOT_EQUAL: + str.append("!="); + break; + case LESS_THAN: + str.append("<"); + break; + case LESS_OR_EQUAL: + str.append("<="); + break; + case GREATER_THAN : + str.append(">"); + break; + case GREATER_OR_EQUAL: + str.append(">="); + break; + default: + str.append("="); + break; + } + + if ( rightExpr ) rightExpr->toString(str); + else str.append("null"); + +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp new file mode 100644 index 00000000000..c3b214e1c99 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/RootExpr.cpp @@ -0,0 +1,82 @@ +/* + * 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. + * + * $Id: RootExpr.cpp,v 1.1 2000-04-06 07:45:39 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +MBool RootExpr::isAbsolute() { + return MB_TRUE; +} //-- isAbsolute + +/** + * 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* RootExpr::evaluate(Node* context, ContextState* cs) { + NodeSet* nodeSet = new NodeSet(); + if ( !context ) return nodeSet; + nodeSet->add(context->getOwnerDocument()); + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double RootExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + if ( matches(node, context, cs) ) { + return 0.5; + } + else return Double::NEGATIVE_INFINITY; +} //-- getDefaultPriority + +/** + * Determines whether this NodeExpr matches the given node within + * the given context +**/ +MBool RootExpr::matches(Node* node, Node* context, ContextState* cs) { + if ( node ) { + return (MBool) (node->getNodeType() == Node::DOCUMENT_NODE); + } + return MB_FALSE; +} //-- matches + +/** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. +**/ +void RootExpr::toString(String& dest) { + dest.append('/'); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp b/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp new file mode 100644 index 00000000000..e0105ebbf2e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/StringExpr.cpp @@ -0,0 +1,79 @@ +/* + * 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. + * + * $Id: StringExpr.cpp,v 1.1 2000-04-06 07:45:39 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * StringExpr + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:39 $ +**/ + +/** + * Creates a new StringExpr +**/ +StringExpr::StringExpr() {}; + +StringExpr::StringExpr(String& value) { + //-- copy value + this->value = value; +} //-- StringExpr + +StringExpr::StringExpr(const String& value) { + //-- copy value + this->value.append(value); +} //-- StringExpr + +/** + * Default Destructor +**/ +StringExpr::~StringExpr() {}; + +/** + * 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* StringExpr::evaluate(Node* context, ContextState* cs) { + return new StringResult(value); +} //-- 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 StringExpr::toString(String& str) { + str.append('\''); + str.append(value); + str.append('\''); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp new file mode 100644 index 00000000000..4111018e1db --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/StringFunctionCall.cpp @@ -0,0 +1,243 @@ +/* + * 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. + * + * $Id: StringFunctionCall.cpp,v 1.1 2000-04-06 07:45:41 kvisco%ziplink.net Exp $ + */ + +/** + * StringFunctionCall + * A representation of the XPath String funtions + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:41 $ +**/ + +#include "FunctionLib.h" + +/** + * Creates a default StringFunctionCall. The string() function + * is the default +**/ +StringFunctionCall::StringFunctionCall() : FunctionCall(XPathNames::STRING_FN) { + type = STRING; +} //-- StringFunctionCall + +/** + * Creates a StringFunctionCall of the given type +**/ +StringFunctionCall::StringFunctionCall(short type) : FunctionCall() { + this->type = type; + switch ( type ) { + case CONCAT: + FunctionCall::setName(XPathNames::CONCAT_FN); + break; + case CONTAINS: + FunctionCall::setName(XPathNames::CONTAINS_FN); + break; + case STARTS_WITH: + FunctionCall::setName(XPathNames::STARTS_WITH_FN); + break; + case STRING_LENGTH: + FunctionCall::setName(XPathNames::STRING_LENGTH_FN); + break; + case SUBSTRING: + FunctionCall::setName(XPathNames::SUBSTRING_FN); + break; + case SUBSTRING_AFTER: + FunctionCall::setName(XPathNames::SUBSTRING_AFTER_FN); + break; + case SUBSTRING_BEFORE: + FunctionCall::setName(XPathNames::SUBSTRING_BEFORE_FN); + break; + case TRANSLATE: + FunctionCall::setName(XPathNames::TRANSLATE_FN); + break; + default: + FunctionCall::setName(XPathNames::STRING_FN); + break; + } +} //-- StringFunctionCall + +/** + * 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* StringFunctionCall::evaluate(Node* context, ContextState* cs) { + ListIterator* iter = params.iterator(); + Int32 argc = params.getLength(); + String err; + ExprResult* result = 0; + switch ( type ) { + case CONCAT : + if ( requireParams(2, cs) ) { + String resultStr; + while(iter->hasNext()) { + evaluateToString((Expr*)iter->next(),context, cs, resultStr); + } + result = new StringResult(resultStr); + } + else result = new StringResult(""); + break; + case CONTAINS : + if ( requireParams(2, 2, cs) ) { + String arg1, arg2; + evaluateToString((Expr*)iter->next(),context, cs, arg1); + evaluateToString((Expr*)iter->next(),context, cs, arg2); + result = new BooleanResult((MBool)(arg1.indexOf(arg2) >= 0)); + } + else result = new BooleanResult(MB_FALSE); + break; + + case STARTS_WITH : + if ( requireParams(2, 2, cs) ) { + String arg1, arg2; + evaluateToString((Expr*)iter->next(),context, cs, arg1); + evaluateToString((Expr*)iter->next(),context, cs, arg2); + result = new BooleanResult((MBool)(arg1.indexOf(arg2) == 0)); + } + else result = new BooleanResult(MB_FALSE); + break; + case STRING_LENGTH: + if ( requireParams(0, 1, cs) ) { + String resultStr; + if ( argc == 1) { + evaluateToString((Expr*)iter->next(),context, cs, resultStr); + } + else XMLDOMUtils::getNodeValue(context, &resultStr); + result = new NumberResult( (double) resultStr.length()); + } + else result = new NumberResult(0.0); + break; + case SUBSTRING: + if ( requireParams(2, 3, cs) ) { + String src; + evaluateToString((Expr*)iter->next(),context, cs, src); + double dbl = evaluateToNumber((Expr*)iter->next(), context, cs); + + //-- check for NaN + if ( Double::isNaN(dbl)) { + result = new StringResult(""); + break; + } + + Int32 startIdx = (Int32)ceil(dbl); + Int32 endIdx = src.length(); + if ( argc == 3) { + dbl += evaluateToNumber((Expr*)iter->next(),context, cs); + if (dbl == Double::POSITIVE_INFINITY) endIdx++; + else if ( dbl == Double::NEGATIVE_INFINITY ) endIdx = 0; + else endIdx = (Int32)floor(dbl); + } + String resultStr; + //-- strings are indexed starting at 1 for XSL + //-- adjust to a 0-based index + if (startIdx > 0) startIdx--; + else if (startIdx == 0 ) endIdx--; + else startIdx=0; + src.subString(startIdx,endIdx,resultStr); + result = new StringResult(resultStr); + } + else result = new StringResult(""); + break; + + case SUBSTRING_AFTER: + if ( requireParams(2, 2, cs) ) { + String arg1, arg2; + evaluateToString((Expr*)iter->next(),context, cs, arg1); + evaluateToString((Expr*)iter->next(),context, cs, arg2); + Int32 idx = arg1.indexOf(arg2); + if ((idx >= 0)&&(idxnext(),context, cs, arg1); + evaluateToString((Expr*)iter->next(),context, cs, arg2); + Int32 idx = arg1.indexOf(arg2); + if ((idx >= 0)&&(idxnext(),context, cs, src); + evaluateToString((Expr*)iter->next(),context, cs, oldChars); + evaluateToString((Expr*)iter->next(),context, cs, newChars); + Int32 size = src.length(); + UNICODE_CHAR* chars = src.toUnicode(new UNICODE_CHAR[size]); + src.clear(); + Int32 newIdx = 0; + Int32 i; + for (i = 0; i < size; i++) { + Int32 idx = oldChars.indexOf(chars[i]); + if (idx >= 0) { + char nchar = newChars.charAt(idx); + if (nchar != -1) src.append(nchar); + } + else src.append(chars[i]); + } + delete chars; + return new StringResult(src); + } + result = new StringResult(""); + break; + + default : //-- string( object? ) + if ( requireParams(0, 1, cs) ) { + String resultStr; + if (iter->hasNext()) { + evaluateToString((Expr*)iter->next(),context, cs, resultStr); + } + else { + String temp; + XMLDOMUtils::getNodeValue(context, &temp); + if ( cs->isStripSpaceAllowed(context) ) { + XMLUtils::stripSpace(temp, resultStr); + } + else resultStr.append(temp); + } + result = new StringResult(resultStr); + } + else result = new StringResult(""); + break; + } + delete iter; + return result; +} //-- evaluate + diff --git a/mozilla/extensions/transformiix/source/xpath/StringResult.cpp b/mozilla/extensions/transformiix/source/xpath/StringResult.cpp new file mode 100644 index 00000000000..043018c386b --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/StringResult.cpp @@ -0,0 +1,96 @@ +/* + * 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. + * + * $Id: StringResult.cpp,v 1.1 2000-04-06 07:45:44 kvisco%ziplink.net Exp $ + */ + +/** + * StringResult + * Represents a String as a Result of evaluating an Expr + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:45:44 $ +**/ +#include "ExprResult.h" + + +/** + * Default Constructor +**/ +StringResult::StringResult() { +} //-- StringResult + +/** + * Creates a new StringResult with the value of the given String parameter + * @param str the String to use for initialization of this StringResult's value +**/ +StringResult::StringResult(String& str) { + //-- copy str + this->value = str; +} //-- StringResult + +/** + * Creates a new StringResult with the value of the given String parameter + * @param str the String to use for initialization of this StringResult's value +**/ +StringResult::StringResult(const String& str) { + //-- copy str + this->value = str; +} //-- StringResult + +/** + * Returns the value of this StringResult +**/ +String& StringResult::getValue() { + return this->value; +} //-- getValue + +/** + * Sets the value of this StringResult + * @param str the String to use for this StringResult's value +**/ +void StringResult::setValue(const String& str){ + // copy str + this->value = str; +} //-- setValue + +/* + * Virtual Methods from ExprResult +*/ + +short StringResult::getResultType() { + return ExprResult::STRING; +} //-- getResultType + +void StringResult::stringValue(String& str) { + str.append(this->value); +} //-- stringValue + +MBool StringResult::booleanValue() { + return (MBool)(this->value.length()); +} //-- booleanValue + +double StringResult::numberValue() { + Double dbl(value); + return dbl.doubleValue(); +} //-- numberValue + diff --git a/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp b/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp new file mode 100644 index 00000000000..a3aa8ecee05 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/TextExpr.cpp @@ -0,0 +1,94 @@ +/* + * 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. + * + * $Id: TextExpr.cpp,v 1.1 2000-04-06 07:45:49 kvisco%ziplink.net Exp $ + */ + +#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) { + + NodeSet* nodeSet = new NodeSet(); + + if ( !context ) return nodeSet; + + NodeList* nl = context->getChildNodes(); + + for (int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + if ( node->getNodeType() == Node::TEXT_NODE ) + nodeSet->add(node); + } + + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double TextExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + return -0.5; +} //-- getDefaultPriority + +/** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr +**/ +short TextExpr::getType() { + return NodeExpr::TEXT_EXPR; +} //-- getType + +/** + * Determines whether this NodeExpr matches the given node within + * the given context +**/ +MBool TextExpr::matches(Node* node, Node* context, ContextState* cs) { + if ( node ) { + return (MBool) (node->getNodeType() == Node::TEXT_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/UnionExpr.cpp b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp new file mode 100644 index 00000000000..c4883e8fa63 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/UnionExpr.cpp @@ -0,0 +1,166 @@ +/* + * 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. + * + * $Id: UnionExpr.cpp,v 1.1 2000-04-06 07:45:52 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + + //-------------/ + //- UnionExpr -/ +//-------------/ + + +/** + * Creates a new UnionExpr +**/ +UnionExpr::UnionExpr() { + //-- do nothing +} + +/** + * Destructor, will delete all Path Expressions +**/ +UnionExpr::~UnionExpr() { + ListIterator* iter = expressions.iterator(); + while ( iter->hasNext() ) { + iter->next(); + delete (PathExpr*)iter->remove(); + } + delete iter; +} //-- ~UnionExpr + +/** + * Adds the PathExpr to this UnionExpr + * @param pathExpr the PathExpr to add to this UnionExpr +**/ +void UnionExpr::addPathExpr(PathExpr* pathExpr) { + if (pathExpr) expressions.add(pathExpr); +} //-- addPathExpr + +/** + * Adds the PathExpr to this UnionExpr + * @param pathExpr the PathExpr to add to this UnionExpr +**/ +void UnionExpr::addPathExpr(int index, PathExpr* pathExpr) { + if (pathExpr) expressions.insert(index, pathExpr); +} //-- addPathExpr + + //------------------------------------/ + //- Virtual methods from PatternExpr -/ +//------------------------------------/ + +/** + * 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* UnionExpr::evaluate(Node* context, ContextState* cs) { + + if ( (!context) || (expressions.getLength() == 0)) + return new NodeSet(0); + + NodeSet* nodes = new NodeSet(); + + ListIterator* iter = expressions.iterator(); + + while ( iter->hasNext() ) { + + PathExpr* pExpr = (PathExpr*)iter->next(); + NodeSet* tmpNodes = (NodeSet*)pExpr->evaluate(context, cs); + for (int j = 0; j < tmpNodes->size(); j++) { + nodes->add(tmpNodes->get(j)); + } + delete tmpNodes; + } + + delete iter; + return nodes; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double UnionExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + + //-- find highest priority + double priority = Double::NEGATIVE_INFINITY; + ListIterator* iter = expressions.iterator(); + while ( iter->hasNext() ) { + PathExpr* pExpr = (PathExpr*)iter->next(); + if ( pExpr->matches(node, context, cs) ) { + double tmpPriority = pExpr->getDefaultPriority(node, context, cs); + priority = (tmpPriority > priority) ? tmpPriority : priority; + } + } + delete iter; + 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() ) { + PathExpr* pExpr = (PathExpr*)iter->next(); + if ( pExpr->matches(node, context, cs) ) { + delete iter; + return MB_TRUE; + } + } + delete iter; + return MB_FALSE; +} //-- matches + + +/** + * Returns the String representation of this PatternExpr. + * @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 PatternExpr. +**/ +void UnionExpr::toString(String& dest) { + ListIterator* iter = expressions.iterator(); + + short count = 0; + while ( iter->hasNext() ) { + //-- set operator + if (count > 0) dest.append(" | "); + ((PathExpr*)iter->next())->toString(dest); + ++count; + } + delete iter; +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp new file mode 100644 index 00000000000..297989ac235 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/VariableRefExpr.cpp @@ -0,0 +1,118 @@ +/* + * 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. + * + * $Id: VariableRefExpr.cpp,v 1.1 2000-04-06 07:45:55 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + + //-------------------/ + //- VariableRefExpr -/ +//-------------------/ + +/** + * Default constructor +**/ +VariableRefExpr::VariableRefExpr() { +} //-- VariableRefExpr + +/** + * Creates a VariableRefExpr with the given variable name +**/ +VariableRefExpr::VariableRefExpr(const String& name) { + this->name = name; +} //-- VariableRefExpr + +/** + * Creates a VariableRefExpr with the given variable name +**/ +VariableRefExpr::VariableRefExpr(String& name) { + this->name = name; +} //-- VariableRefExpr + +/** + * Default destructor +**/ +VariableRefExpr::~VariableRefExpr() { +} //-- ~VariableRefExpr + +/** + * 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* VariableRefExpr::evaluate(Node* context, ContextState* cs) { + + ExprResult* exprResult = cs->getVariable(name); + //-- make copy to prevent deletetion + //-- I know, I should add a #copy method to ExprResult, I will + ExprResult* copyOfResult = 0; + + if ( exprResult ) { + switch ( exprResult->getResultType() ) { + //-- BooleanResult + case ExprResult::BOOLEAN : + copyOfResult = new BooleanResult(exprResult->booleanValue()); + break; + //-- NodeSet + case ExprResult::NODESET : + { + NodeSet* src = (NodeSet*)exprResult; + NodeSet* dest = new NodeSet(src->size()); + for ( int i = 0; i < src->size(); i++) + dest->add(src->get(i)); + copyOfResult = dest; + break; + } + //-- NumberResult + case ExprResult::NUMBER : + copyOfResult = new NumberResult(exprResult->numberValue()); + break; + //-- StringResult + default: + StringResult* strResult = new StringResult(); + exprResult->stringValue(strResult->getValue()); + copyOfResult = strResult; + break; + } + } + else copyOfResult = new StringResult(); + + return copyOfResult; +} //-- 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 VariableRefExpr::toString(String& str) { + str.append('$'); + str.append(name); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/WildCardExpr.cpp b/mozilla/extensions/transformiix/source/xpath/WildCardExpr.cpp new file mode 100644 index 00000000000..6752686a0b0 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/WildCardExpr.cpp @@ -0,0 +1,100 @@ +/* + * 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. + * + * $Id: WildCardExpr.cpp,v 1.1 2000-04-06 07:46:00 kvisco%ziplink.net Exp $ + */ + +#include "Expr.h" + +/** + * This class represents a WildCardExpr as defined by the XSL + * Working Draft + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:00 $ +**/ + +/** + * 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* WildCardExpr::evaluate(Node* context, ContextState* cs) { + + NodeSet* nodeSet = new NodeSet(); + + if ( !context ) return nodeSet; + + NodeList* nl = context->getChildNodes(); + + for (int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + if ( node->getNodeType() == Node::ELEMENT_NODE ) + nodeSet->add(node); + } + return nodeSet; +} //-- evaluate + +/** + * Returns the default priority of this Pattern based on the given Node, + * context Node, and ContextState. + * If this pattern does not match the given Node under the current context Node and + * ContextState then Negative Infinity is returned. +**/ +double WildCardExpr::getDefaultPriority(Node* node, Node* context, ContextState* cs) { + return -0.5; +} //-- getDefaultPriority + +/** + * Returns the type of this NodeExpr + * @return the type of this NodeExpr +**/ +short WildCardExpr::getType() { + return NodeExpr::WILD_CARD; +} //-- getType + +/** + * Determines whether this NodeExpr matches the given node within + * the given context +**/ +MBool WildCardExpr::matches(Node* node, Node* context, ContextState* cs) { + if ( node ) { + return (MBool) (node->getNodeType() == Node::ELEMENT_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 WildCardExpr::toString(String& dest) { + dest.append("*"); +} //-- toString + diff --git a/mozilla/extensions/transformiix/source/xpath/XPathNames.cpp b/mozilla/extensions/transformiix/source/xpath/XPathNames.cpp new file mode 100644 index 00000000000..4e164b04908 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/XPathNames.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * + * $Id: XPathNames.cpp,v 1.1 2000-04-06 07:46:08 kvisco%ziplink.net Exp $ + */ + +/** + * XPath names + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:08 $ +**/ + +#include "FunctionLib.h" + +//-- Function Names +const String XPathNames::BOOLEAN_FN = "boolean"; +const String XPathNames::CONCAT_FN = "concat"; +const String XPathNames::CONTAINS_FN = "contains"; +const String XPathNames::COUNT_FN = "count"; +const String XPathNames::FALSE_FN = "false"; +const String XPathNames::LAST_FN = "last"; +const String XPathNames::LOCAL_NAME_FN = "local-name"; +const String XPathNames::NAME_FN = "name"; +const String XPathNames::NAMESPACE_URI_FN = "namespace-uri"; +const String XPathNames::NOT_FN = "not"; +const String XPathNames::POSITION_FN = "position"; +const String XPathNames::STARTS_WITH_FN = "starts-with"; +const String XPathNames::STRING_FN = "string"; +const String XPathNames::STRING_LENGTH_FN = "string-length"; +const String XPathNames::SUBSTRING_FN = "substring"; +const String XPathNames::SUBSTRING_AFTER_FN = "substring-after"; +const String XPathNames::SUBSTRING_BEFORE_FN = "substring-before"; +const String XPathNames::TRANSLATE_FN = "translate"; +const String XPathNames::TRUE_FN = "true"; +// OG+ +const String XPathNames::NUMBER_FN = "number"; +const String XPathNames::ROUND_FN = "round"; +const String XPathNames::CEILING_FN = "ceiling"; +const String XPathNames::FLOOR_FN = "floor"; +// OG- + +//-- internal XSL processor functions +const String XPathNames::ERROR_FN = "error"; + diff --git a/mozilla/extensions/transformiix/source/xpath/makefile.win b/mozilla/extensions/transformiix/source/xpath/makefile.win new file mode 100644 index 00000000000..72a201e66c7 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xpath/makefile.win @@ -0,0 +1,115 @@ +#!nmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH=..\..\..\..\.. + +LIBRARY_NAME=transformix_xpath +MODULE=transformix +REQUIRES=xpcom raptor + +CPPSRCS= \ + AdditiveExpr.cpp \ + AttributeExpr.cpp \ + AttributeValueTemplate.cpp \ + BasicNodeExpr.cpp \ + BooleanFunctionCall.cpp \ + BooleanResult.cpp \ + ElementExpr.cpp \ + ErrorFunctionCall.cpp \ + ExprLexer.cpp \ + ExprParser.cpp \ + FilterExpr.cpp \ + FunctionCall.cpp \ + IdentityExpr.cpp \ + LocationStep.cpp \ + MultiplicativeExpr.cpp \ + NodeSet.cpp \ + NodeSetFunctionCall.cpp \ + NumberExpr.cpp \ + NumberFunctionCall.cpp \ + NumberResult.cpp \ + ParentExpr.cpp \ + PathExpr.cpp \ + PredicateList.cpp \ + RelationalExpr.cpp \ + RootExpr.cpp \ + StringExpr.cpp \ + StringFunctionCall.cpp \ + StringResult.cpp \ + TextExpr.cpp \ + UnionExpr.cpp \ + VariableRefExpr.cpp \ + WildCardExpr.cpp \ + $(NULL) + +CPP_OBJS= \ + .\$(OBJDIR)\AdditiveExpr.obj \ + .\$(OBJDIR)\AttributeExpr.obj \ + .\$(OBJDIR)\AttributeValueTemplate.obj \ + .\$(OBJDIR)\BasicNodeExpr.obj \ + .\$(OBJDIR)\BooleanFunctionCall.obj \ + .\$(OBJDIR)\BooleanResult.obj \ + .\$(OBJDIR)\ElementExpr.obj \ + .\$(OBJDIR)\ErrorFunctionCall.obj \ + .\$(OBJDIR)\ExprLexer.obj \ + .\$(OBJDIR)\ExprParser.obj \ + .\$(OBJDIR)\FilterExpr.obj \ + .\$(OBJDIR)\FunctionCall.obj \ + .\$(OBJDIR)\IdentityExpr.obj \ + .\$(OBJDIR)\LocationStep.obj \ + .\$(OBJDIR)\MultiplicativeExpr.obj \ + .\$(OBJDIR)\NodeSet.obj \ + .\$(OBJDIR)\NodeSetFunctionCall.obj \ + .\$(OBJDIR)\NumberExpr.obj \ + .\$(OBJDIR)\NumberFunctionCall.obj \ + .\$(OBJDIR)\NumberResult.obj \ + .\$(OBJDIR)\ParentExpr.obj \ + .\$(OBJDIR)\PathExpr.obj \ + .\$(OBJDIR)\PredicateList.obj \ + .\$(OBJDIR)\RelationalExpr.obj \ + .\$(OBJDIR)\RootExpr.obj \ + .\$(OBJDIR)\StringExpr.obj \ + .\$(OBJDIR)\StringFunctionCall.obj \ + .\$(OBJDIR)\StringResult.obj \ + .\$(OBJDIR)\TextExpr.obj \ + .\$(OBJDIR)\UnionExpr.obj \ + .\$(OBJDIR)\VariableRefExpr.obj \ + .\$(OBJDIR)\WildCardExpr.obj \ + $(NULL) + +EXPORTS = \ + $(NULL) + +LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I..\..\base -I..\util -I..\..\xml\dom \ + -I..\..\xml -I ..\..\xsl + +LCFLAGS = \ + $(LCFLAGS) \ + $(DEFINES) \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(LIBRARY) + $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib + +clobber:: + rm -f $(DIST)\lib\$(LIBRARY_NAME).lib diff --git a/mozilla/extensions/transformiix/source/xpath/parser.exe b/mozilla/extensions/transformiix/source/xpath/parser.exe new file mode 100755 index 0000000000000000000000000000000000000000..01e32a82aa1e101f60c1010f3452df795d0e7366 GIT binary patch literal 2326 zcmeHHO=ufO6n>J{&c@zEYH-1&e+o@aNP}_QLvtw+w#V%uZj4nqrA2MzSZeIzAMD)_ zNSzwChYrJn4msptf)6_6kV6ilh+wGdimVR_q&<{`T18N|EJ%SIRM&@K^}X3$TPn22 z(nAM!X5P&E`QG>D?Z}5&2myeCU!ws~z?DW!&i_0uezJFUW98yz|qkIu|Zrh5-{9P>PnGJvyzcDTtar{RMz z{PYSy1r7u{1HreT3qkdwqK03@`}zoI%$0*K>;Rt7sT`}}J%Q4~5tOzxkq;c+;tKN$ z#V3$6EbPGgz$rd)?IXUtv39B9>#k=~-7nn0V+PvPA%e*O3jx9SChFeddD^@U%4 zZbvH>i-+qKT$={zHHrUk|3eHU_^)OyV!jQ1LjZc<{^O^I{;}PJ3k(GW|#4-$k+Kp&PpPw#+`Tn2!UBr1S^?EMMQYQ zv006Bw-QhJ341{KDiQ-ep`QAodXPW4OKn^|VekU$=HKRfHwA^d{%Nt ze+2Lyiw>>|rdBUjQ(6CvCpK($pR}yRLmBM%yYXZ|VF;AAdr*^KF^?DCRC$7t!NP(?wO0 zsIt%b6g;1`^d9h`z2nDAK5C+aN`rngd=OdHaK{G`ZbWW0!Q3D|9h21wzU?3KM8Rfj zZsekj+;+r|+{#B`j}NGMeC+#m>erBuPMmyv>0B!x5#qxypLtaU{WXCg`^E@f0!b(YTYTN@P}g z%L|^xTHq5935}1cRGlVS^JKF&Pw({J(teS$<+jcKAt)zzY*r_7grS<(Gzfp0a|JQ1 z5%dT*O33plMHfa%rh%%VaRi7rmlbXlg;8w$XqGg50IY5<)j@wlusT^E=f;{a*4*S1 zbu?L%CIw*>$V9>T(xBfnP`Qzx4hbXQWRjOAcZ6|=Ow?+-^)&(Z6L2JQ6_MZckxSAM z`R#q=xA&1_4e*AL-x9{Hzek=EMy?4)PMWL=W7R|MNaQE?k*^T)l_rxFX>vmtH(cak zvkF1C*%mDbJR^pcjJXrkgVk`EIh*O7aowM2 x+kLCcf8LtkQ*TKeith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:29 $ +**/ +#include "Names.h" + +//-- Global Strings +const String HTML = "html"; +const String HTML_NS = "http://www.w3.org/TR/REC-html"; +const String STYLESHEET_PI = "xml-stylesheet"; +const String STYLESHEET_PI_OLD = "xml:stylesheet"; +const String XML_SPACE = "xml:space"; +const String XSL_MIME_TYPE = "text/xsl"; +const String XSLT_NS = "http://www.w3.org/1999/XSL/Transform"; + +//-- Elements +const String APPLY_IMPORTS = "apply-imports"; +const String APPLY_TEMPLATES = "apply-templates"; +const String ATTRIBUTE = "attribute"; +const String ATTRIBUTE_SET = "attribute-set"; +const String CALL_TEMPLATE = "call-template"; +const String CHOOSE = "choose"; +const String COMMENT = "comment"; +const String COPY = "copy"; +const String COPY_OF = "copy-of"; +const String ELEMENT = "element"; +const String FOR_EACH = "for-each"; +const String IF = "if"; +const String IMPORT = "import"; +const String INCLUDE = "include"; +const String MESSAGE = "message"; +const String NUMBER = "number"; +const String OTHERWISE = "otherwise"; +const String OUTPUT = "output"; +const String PARAM = "param"; +const String PI = "processing-instruction"; +const String PRESERVE_SPACE = "preserve-space"; +const String STRIP_SPACE = "strip-space"; +const String TEMPLATE = "template"; +const String TEXT = "text"; +const String VALUE_OF = "value-of"; +const String VARIABLE = "variable"; +const String WHEN = "when"; +const String WITH_PARAM = "with-param"; + + +//-- Attributes +const String CDATA_ELEMENTS_ATTR = "cdata-section-elements"; +const String COUNT_ATTR = "count"; +const String DEFAULT_SPACE_ATTR = "default-space"; +const String DOCTYPE_PUBLIC_ATTR = "doctype-public"; +const String DOCTYPE_SYSTEM_ATTR = "doctype-system"; +const String ELEMENTS_ATTR = "elements"; +const String ENCODING_ATTR = "encoding"; +const String EXPR_ATTR = "expr"; +const String FORMAT_ATTR = "format"; +const String FROM_ATTR = "from"; +const String HREF_ATTR = "href"; +const String INDENT_ATTR = "indent"; +const String LEVEL_ATTR = "level"; +const String MATCH_ATTR = "match"; +const String METHOD_ATTR = "method"; +const String MEDIA_TYPE_ATTR = "media-type"; +const String MODE_ATTR = "mode"; +const String NAME_ATTR = "name"; +const String NAMESPACE_ATTR = "namespace"; +const String OMIT_XMLDECL_ATTR = "omit-xml-declaration"; +const String PRIORITY_ATTR = "priority"; +const String SELECT_ATTR = "select"; +const String STANDALONE = "standalone"; +const String TEST_ATTR = "test"; +const String USE_ATTRIBUTE_SETS_ATTR = "use-attribute-sets"; +const String VALUE_ATTR = "value"; +const String VERSION_ATTR = "version"; + + +//-- Attribute Values +const String ANY_VALUE = "any"; +const String MULTIPLE_VALUE = "multiple"; +const String NO_VALUE = "no"; +const String PRESERVE_VALUE = "preserve"; +const String SINGLE_VALUE = "single"; +const String STRIP_VALUE = "strip"; +const String YES_VALUE = "yes"; + +//-- Stylesheet attributes +const String INDENT_RESULT_ATTR = "indent-result"; +const String RESULT_NS_ATTR = "result-ns"; + +const String ANCESTOR_AXIS = "ancestor"; +const String ANCESTOR_OR_SELF_AXIS = "ancestor-or-self"; +const String ATTRIBUTE_AXIS = "attribute"; +const String CHILD_AXIS = "child"; +const String DESCENDANT_AXIS = "descendant"; +const String DESCENDANT_OR_SELF_AXIS = "descendant-or-self"; +const String FOLLOWING_AXIS = "following"; +const String FOLLOWING_SIBLING_AXIS = "following-siblings"; +const String NAMESPACE_AXIS = "namespace"; +const String PARENT_AXIS = "parent"; +const String PRECEDING_AXIS = "preceding"; +const String PRECEDING_SIBLING_AXIS = "preceding-siblings"; +const String SELF_AXIS = "self"; + + +//-- NodeTest Operators +const String ATTRIBUTE_FNAME = "@"; +const String COMMENT_FNAME = "comment"; +const String PI_FNAME = "pi"; +const String TEXT_FNAME = "text"; +const String NODE_FNAME = "node"; +const String IDENTITY_OP = "."; +const String PARENT_OP = ".."; + +//-- XSL extension functions + +const String WILD_CARD = "*"; + diff --git a/mozilla/extensions/transformiix/source/xslt/Names.h b/mozilla/extensions/transformiix/source/xslt/Names.h new file mode 100644 index 00000000000..ac5f8c054f8 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/Names.h @@ -0,0 +1,142 @@ +/* + * 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. + * + * $Id: Names.h,v 1.1 2000-04-06 07:46:31 kvisco%ziplink.net Exp $ + */ + +#include "String.h" + +#ifndef TRANSFRMX_NAMES_H +#define TRANSFRMX_NAMES_H + +//-- Global Strings +extern const String HTML; +extern const String HTML_NS; +extern const String STYLESHEET_PI; +extern const String STYLESHEET_PI_OLD; +extern const String XML_SPACE; +extern const String XSL_MIME_TYPE; +extern const String XSLT_NS; + +//-- Elements +extern const String APPLY_IMPORTS; +extern const String APPLY_TEMPLATES; +extern const String ATTRIBUTE; +extern const String ATTRIBUTE_SET; +extern const String CALL_TEMPLATE; +extern const String CHOOSE; +extern const String COMMENT; +extern const String COPY; +extern const String COPY_OF; +extern const String ELEMENT; +extern const String FOR_EACH; +extern const String IF; +extern const String IMPORT; +extern const String INCLUDE; +extern const String MESSAGE; +extern const String NUMBER; +extern const String OTHERWISE; +extern const String OUTPUT; +extern const String PARAM; +extern const String PI; +extern const String PRESERVE_SPACE; +extern const String STRIP_SPACE; +extern const String TEMPLATE; +extern const String TEXT; +extern const String VALUE_OF; +extern const String VARIABLE; +extern const String WHEN; +extern const String WITH_PARAM; + + +//-- Attributes +extern const String CDATA_ELEMENTS; +extern const String COUNT_ATTR; +extern const String DEFAULT_SPACE_ATTR; +extern const String DOCTYPE_PUBLIC_ATTR; +extern const String DOCTYPE_SYSTEM_ATTR; +extern const String ELEMENTS_ATTR; +extern const String ENCODING_ATTR; +extern const String EXPR_ATTR; +extern const String FORMAT_ATTR; +extern const String FROM_ATTR; +extern const String HREF_ATTR; +extern const String INDENT_ATTR; +extern const String LEVEL_ATTR; +extern const String MATCH_ATTR; +extern const String MEDIA_TYPE_ATTR; +extern const String METHOD_ATTR; +extern const String MODE_ATTR; +extern const String NAME_ATTR; +extern const String NAMESPACE_ATTR; +extern const String OMIT_XMLDECL_ATTR; +extern const String PRIORITY_ATTR; +extern const String SELECT_ATTR; +extern const String STANDALONE; +extern const String TEST_ATTR; +extern const String USE_ATTRIBUTE_SETS_ATTR; +extern const String VALUE_ATTR; +extern const String VERSION_ATTR; + +//-- Attribute Values +extern const String ANY_VALUE; +extern const String MULTIPLE_VALUE; +extern const String NO_VALUE; +extern const String PRESERVE_VALUE; +extern const String SINGLE_VALUE; +extern const String STRIP_VALUE; +extern const String YES_VALUE; + +//-- Stylesheet attributes +extern const String INDENT_RESULT_ATTR; +extern const String RESULT_NS_ATTR; + +extern const String ANCESTOR_AXIS; +extern const String ANCESTOR_OR_SELF_AXIS; +extern const String ATTRIBUTE_AXIS; +extern const String CHILD_AXIS; +extern const String DESCENDANT_AXIS; +extern const String DESCENDANT_OR_SELF_AXIS; +extern const String FOLLOWING_AXIS; +extern const String FOLLOWING_SIBLING_AXIS; +extern const String NAMESPACE_AXIS; +extern const String PARENT_AXIS; +extern const String PRECEDING_AXIS; +extern const String PRECEDING_SIBLING_AXIS; +extern const String SELF_AXIS; + + +//-- NodeTest Operators +extern const String ATTRIBUTE_FNAME; +extern const String COMMENT_FNAME; +extern const String PI_FNAME; +extern const String TEXT_FNAME; +extern const String NODE_FNAME; +extern const String IDENTITY_OP; +extern const String PARENT_OP; + +//-- XSL extension functions + +extern const String WILD_CARD; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/Numbering.cpp b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp new file mode 100644 index 00000000000..dabb0191397 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/Numbering.cpp @@ -0,0 +1,195 @@ +/* + * 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. + * + * $Id: Numbering.cpp,v 1.1 2000-04-06 07:46:33 kvisco%ziplink.net Exp $ + */ + +/** + * Numbering methods + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:33 $ +**/ + +#include "Numbering.h" + +void Numbering::doNumbering + (Element* xslNumber, String& dest, Node* context, ProcessorState* ps) +{ + + if ( !xslNumber ) return; + + int* counts = 0; + int nbrOfCounts = 0; + + String valueAttr = xslNumber->getAttribute(VALUE_ATTR); + //-- check for expr + if (valueAttr.length() > 0) { + Expr* expr = ps->getExpr(valueAttr); + 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 + + String countAttr = xslNumber->getAttribute(COUNT_ATTR); + + PatternExpr* countExpr = 0; + if (countAttr.length() > 0) countExpr = ps->getPatternExpr(countAttr); + else { + switch(context->getNodeType()) { + case Node::ATTRIBUTE_NODE: + countAttr.append('@'); + countAttr.append(context->getNodeName()); + break; + case Node::ELEMENT_NODE: + countAttr.append(context->getNodeName()); + break; + case Node::CDATA_SECTION_NODE : + case Node::TEXT_NODE : + countAttr.append("text()"); + break; + case Node::COMMENT_NODE : + countAttr.append("comment()"); + break; + case Node::PROCESSING_INSTRUCTION_NODE : + countAttr.append("processing-instruction()"); + break; + default: + countAttr.append("node()[false()]"); //-- for now + break; + } + countExpr = ps->getPatternExpr(countAttr); + } + NodeSet* nodes = 0; + int cnum = 0; + + String level = xslNumber->getAttribute(LEVEL_ATTR); + String fromAttr = xslNumber->getAttribute(FROM_ATTR); + PatternExpr* from = 0; + + if (MULTIPLE_VALUE.isEqual(level)) + nodes = getAncestorsOrSelf(countExpr, from, context, ps, MB_FALSE); + //else if (ANY_VALUE.isEqual(level)) + // nodes = getAnyPreviousNodes(countExpr, context, ps); + else + nodes = getAncestorsOrSelf(countExpr, from, context, ps, MB_TRUE); + + nbrOfCounts = nodes->size(); + counts = new int[nbrOfCounts]; + cnum = 0; + for (int i = nodes->size()-1; i >= 0; i--) { + counts[cnum++] = + countPreceedingSiblings(countExpr, nodes->get(i), ps); + } + delete nodes; + } + //-- format counts + for ( int i = 0; i < nbrOfCounts; i++) { + Integer::toString(counts[i], dest); + } + delete counts; +} //-- doNumbering + +int Numbering::countPreceedingSiblings + (PatternExpr* patternExpr, Node* context, ProcessorState* ps) +{ + int count = 1; + + if (!context) return 0; + + Node* sibling = context; + while ((sibling = sibling->getPreviousSibling())) { + if (patternExpr->matches(sibling, sibling, ps)) + ++count; + } + return count; +} //-- countPreceedingSiblings + +NodeSet* Numbering::getAncestorsOrSelf + ( PatternExpr* countExpr, + PatternExpr* 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 (countExpr->matches(parent, parent->getParentNode(), ps)) { + nodeSet->add(parent); + if (findNearest) break; + } + parent = parent->getParentNode(); + } + return nodeSet; +} //-- fromAncestorsOrSelf + +/** + * Retrieves all nodes that come before the given element + * at any level in the document that match the count pattern of + * this XSLNumber starting from the closest element that matches + * the from pattern + * @param element the element to find the nearest ancestor of + * @return a List of all matching nodes +** +NodeSet* Numbering::getAnyPreviousNodes + ( PatternExpr* patternExpr, Node* context, ProcessorState* ps) +{ + + NodeSet* nodes = new NodeSet(); + + Node* current = context; + + while (current) { + + // Check from MatchExpr + if ((from != null) && from.matches(element,element,ps)) + return nodes; + + // Check count MatchExpr + if (matchExpr.matches(element, element, ps)) + nodes.add(element); + + Node sibling = element; + while ( (sibling = sibling.getPreviousSibling()) != null) { + if (sibling.getNodeType() == Node.ELEMENT_NODE) break; + } + if (sibling == null) { + Node parent = element.getParentNode(); + if (parent.getNodeType() != Node.ELEMENT_NODE) break; + element = (Element)parent; + } + else element = (Element)sibling; + } + return nodes; +} //-- getAnyPreviousNodes + +/* */ diff --git a/mozilla/extensions/transformiix/source/xslt/Numbering.h b/mozilla/extensions/transformiix/source/xslt/Numbering.h new file mode 100644 index 00000000000..fac6267ed75 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/Numbering.h @@ -0,0 +1,64 @@ +/* + * 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. + * + * $Id: Numbering.h,v 1.1 2000-04-06 07:46:34 kvisco%ziplink.net Exp $ + */ + +/** + * Numbering methods + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:34 $ +**/ + +#ifndef MITREXSL_NUMBERING_H +#define MITREXSL_NUMBERING_H + +#include "baseutils.h" +#include "String.h" +#include "dom.h" +#include "ProcessorState.h" +#include "Expr.h" +#include "primitives.h" +#include "ExprResult.h" +#include "Names.h" + +class Numbering { + +public: + + static void doNumbering + (Element* xslNumber, String& dest, Node* context, ProcessorState* ps); + +private: + static int countPreceedingSiblings + (PatternExpr* patternExpr, Node* context, ProcessorState* ps); + + static NodeSet* getAncestorsOrSelf + ( PatternExpr* countExpr, + PatternExpr* from, + Node* context, + ProcessorState* ps, + MBool findNearest ); +}; +#endif + diff --git a/mozilla/extensions/transformiix/source/xslt/OutputFormat.cpp b/mozilla/extensions/transformiix/source/xslt/OutputFormat.cpp new file mode 100644 index 00000000000..039163728cc --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/OutputFormat.cpp @@ -0,0 +1,227 @@ +/* + * 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 (C) 1999 Keith Visco. + * All Rights Reserved.. + * + * Contributor(s): + * Keith Visco, kvisco@ziplink.net + * -- original author. + * + * $Id: OutputFormat.cpp,v 1.1 2000-04-06 07:46:36 kvisco%ziplink.net Exp $ + */ + + +#include "OutputFormat.h" + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:36 $ +**/ + + +/** + * Creates a new OutputFormat with the default values. +**/ +OutputFormat::OutputFormat() { + method.append("xml"); + explicitMethod = MB_FALSE; + explicitIndent = MB_FALSE; + indent = MB_FALSE; +} //-- OutputFormat + + +/** + * Deletes this OutputFormat +**/ +OutputFormat::~OutputFormat() {}; + + +/** + * Returns the publicId for use when creating a DOCTYPE in the output. + * @param dest the destination String to set equal to the value of the + * public identifier. + * @return the dest String containing the public identifier +**/ +String& OutputFormat::getDoctypePublic(String& dest) { + dest.clear(); + dest.append(publicId); + return dest; +} //-- getDoctypePublic + +/** + * Returns the systemId for use when creating a DOCTYPE in the output. + * @param dest the destination String to set equal to the value of the + * system identifier. + * @return the dest String containing the system identifier +**/ +String& OutputFormat::getDoctypeSystem(String& dest) { + dest.clear(); + dest.append(systemId); + return dest; +} //-- getDoctypeSystem + +/** + * Gets the XML output encoding that should be use when serializing + * XML documents,and appends it to the destination String. + * The destination String will be cleared before the encoding is + * appended. + * @param dest the String to append the output encoding to + * @return the given dest String now containing the output encoding +**/ +String& OutputFormat::getEncoding(String& dest) { + dest.clear(); + dest.append(encoding); + return dest; +} //-- getEncoding + +/** + * @return whether or not indentation is allowed during serialization of + * XML or HTML documents. If this value is not explicitly set using + * ::setIndent, then a default indent flag is calculated based on + * the value of the output method. By default "xml" output method will + * return a value of MB_FALSE, while "html" output is MB_TRUE. +**/ +MBool OutputFormat::getIndent() { + if (explicitIndent) return indent; + if (method.isEqual("html")) return MB_TRUE; + return MB_FALSE; +} //-- getIndent + + /** + * Gets the output method and appends it to the destination String. + * The destination String will be cleared before the method is + * appended. + * @param dest the String to append the output method to + * @return the given dest String now containing the output method + **/ +String& OutputFormat::getMethod(String& dest) { + dest.clear(); + dest.append(method); + return dest; +} //-- getMethod + +/** + * Gets the XML output version that should be used when serializing + * XML documents,and appends it to the destination String. + * The destination String will be cleared before the version is + * appended. + * @param dest the String to append the output version to + * @return the given dest String now containing the output version +**/ +String& OutputFormat::getVersion(String& dest) { + dest.clear(); + dest.append(version); + return dest; +} + +/** + * @return true if the output method is equal to "html". +**/ +MBool OutputFormat::isHTMLOutput() { + return (MBool) method.isEqual("html"); +} //-- isHTMLOutput + + +/** + * @return true if allowing indentation was explicitly specified. +**/ +MBool OutputFormat::isIndentExplicit() { + return explicitIndent; +} //-- isIndentExplicit + + +/** + * @return true if the output method was explicitly specified. +**/ +MBool OutputFormat::isMethodExplicit() { + return explicitMethod; +} //-- isMethodExplicit + +/** + * @return true if the output method is equal to "text". +**/ +MBool OutputFormat::isTextOutput() { + return (MBool) method.isEqual("text"); +} //-- isTextOuput + +/** + * @return true if the output method is equal to "xml". +**/ +MBool OutputFormat::isXMLOutput() { + return (MBool) method.isEqual("xml"); +} //-- isXMLOutput + + + +/** + * Sets the publicId for use when creating a DOCTYPE in the output. + * @param publicId the value of the DOCTYPE's public identifier.. +**/ +void OutputFormat::setDoctypePublic(const String& publicId) { + this->publicId = publicId; +} //-- setDoctypePublic + +/** + * Sets the systemId for use when creating a DOCTYPE in the output. + * @param systemId the value of the DOCTYPE's system identifier.. +**/ +void OutputFormat::setDoctypeSystem(const String& systemId) { + this->systemId = systemId; +} //-- setDoctypeSystem + +/** + * Sets the xml output encoding that should be used when serializing + * XML documents. + * @param encoding the value to set the XML output encoding to. +**/ +void OutputFormat::setEncoding(const String& encoding) { + this->encoding = encoding; +} //-- setEncoding + +/** + * Sets whether or not indentation is allowed during serialization + * @param allowIndentation the flag that specifies whether or not + * indentation is allowed during serialization +**/ +void OutputFormat::setIndent(MBool allowIndentation) { + explicitIndent = MB_TRUE; + indent = allowIndentation; +} //-- setIndent + +/** + * Sets the output method. Valid output method options are, + * "xml", "html", or "text". + * @param method the value to set the XML output method to. If + * the given String is not a valid method, the method will be + * set to "xml". +**/ +void OutputFormat::setMethod(const String& method) { + + explicitMethod = MB_TRUE; + if (method.isEqual("html")) this->method = method; + else if (method.isEqual("text")) this->method = method; + else this->method = "xml"; + +} //-- setMethod + +/** + * Sets the xml output version that should be used when serializing + * XML documents. + * @param version the value to set the XML output version to. +**/ +void OutputFormat::setVersion(const String& version) { + this->version = version; +} //-- setVersion + diff --git a/mozilla/extensions/transformiix/source/xslt/OutputFormat.h b/mozilla/extensions/transformiix/source/xslt/OutputFormat.h new file mode 100644 index 00000000000..fbd252b21fe --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/OutputFormat.h @@ -0,0 +1,203 @@ +/* + * 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 (C) 1999 Keith Visco. + * All Rights Reserved.. + * + * Contributor(s): + * Keith Visco, kvisco@ziplink.net + * -- original author. + * + * $Id: OutputFormat.h,v 1.1 2000-04-06 07:46:40 kvisco%ziplink.net Exp $ + */ + + +#ifndef TRANSFRMX_OUTPUTFORMAT_H +#define TRANSFRMX_OUTPUTFORMAT_H + +#include "String.h" +#include "baseutils.h" + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:40 $ +**/ +class OutputFormat { + + public: + + /** + * Creates a new OutputFormat with the default values. + **/ + OutputFormat(); + + + /** + * Deletes this OutputFormat + **/ + virtual ~OutputFormat(); + + + /** + * Returns the publicId for use when creating a DOCTYPE in the output. + * @param dest the destination String to set equal to the value of the + * public identifier. + * @return the dest String containing the public identifier + **/ + String& getDoctypePublic(String& dest); + + /** + * Returns the systemId for use when creating a DOCTYPE in the output. + * @param dest the destination String to set equal to the value of the + * system identifier. + * @return the dest String containing the system identifier + **/ + String& getDoctypeSystem(String& dest); + + /** + * Gets the XML output encoding that should be use when serializing + * XML documents,and appends it to the destination String. + * The destination String will be cleared before the encoding is + * appended. + * @param dest the String to append the output encoding to + * @return the given dest String now containing the output encoding + **/ + String& getEncoding(String& dest); + + /** + * @return whether or not indentation is allowed during serialization of + * XML or HTML documents. If this value is not explicitly set using + * ::setIndent, then a default indent flag is calculated based on + * the value of the output method. By default "xml" output method will + * return a value of MB_FALSE, while "html" output is MB_TRUE. + **/ + MBool getIndent(); + + /** + * Gets the output method and appends it to the destination String. + * The destination String will be cleared before the method is + * appended. + * @param dest the String to append the output method to + * @return the given dest String now containing the output method + **/ + String& getMethod(String& dest); + + /** + * Gets the XML output version that should be used when serializing + * XML documents,and appends it to the destination String. + * The destination String will be cleared before the version is + * appended. + * @param dest the String to append the output version to + * @return the given dest String now containing the output version + **/ + String& getVersion(String& dest); + + /** + * @return true if the output method is equal to "html". + **/ + MBool isHTMLOutput(); + + + /** + * @return true if allowing indentation was explicitly specified. + **/ + MBool isIndentExplicit(); + + /** + * @return true if the output method was explicitly specified. + **/ + MBool isMethodExplicit(); + + /** + * @return true if the output method is equal to "xml". + **/ + MBool isXMLOutput(); + + /** + * @return true if the output method is equal to "text". + **/ + MBool isTextOutput(); + + + /** + * Sets the publicId for use when creating a DOCTYPE in the output. + * @param publicId the value of the DOCTYPE's public identifier.. + **/ + void setDoctypePublic(const String& publicId); + + /** + * Sets the systemId for use when creating a DOCTYPE in the output. + * @param systemId the value of the DOCTYPE's system identifier.. + **/ + void setDoctypeSystem(const String& publicId); + + /** + * Sets the xml output encoding that should be used when serializing + * XML documents. + * @param encoding the value to set the XML output encoding to. + **/ + void setEncoding(const String& encoding); + + /** + * Sets whether or not indentation is allowed during serialization + * @param allowIndentation the flag that specifies whether or not + * indentation is allowed during serialization + **/ + void setIndent(MBool allowIndentation); + + /** + * Sets the output method. Valid output method options are, + * "xml", "html", or "text". + * @param method the value to set the XML output method to. If + * the given String is not a valid method, the method will be + * set to "xml". + **/ + void setMethod(const String& method); + + /** + * Sets the xml output version that should be used when serializing + * XML documents. + * @param version the value to set the XML output version to. + **/ + void setVersion(const String& version); + + private: + + //-- The xml character encoding that should be used when serializing + //-- xml documents + String encoding; + + MBool explicitIndent; + MBool indent; + + //-- The XSL output method, which can be "xml", "html", or "text" + String method; + + MBool explicitMethod; + + //-- The public Id for creating a DOCTYPE + String publicId; + + //-- The System Id for creating a DOCTYPE + String systemId; + + //-- The xml version number that should be used when serializing + //-- xml documents + String version; + + + +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp new file mode 100644 index 00000000000..7349c3e1d77 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -0,0 +1,760 @@ +/* + * 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. + * + * $Id: ProcessorState.cpp,v 1.1 2000-04-06 07:46:41 kvisco%ziplink.net Exp $ + */ + +/** + * Implementation of ProcessorState + * This code was ported from XSL:P + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:41 $ +**/ + +#include "ProcessorState.h" + + //-------------/ + //- Constants -/ +//-------------/ +const String ProcessorState::wrapperNSPrefix = "transformiix"; +const String ProcessorState::wrapperName = "transformiix:result"; +const String ProcessorState::wrapperNS = "http://www.mitre.org/TransforMiix"; + +/** + * Creates a new ProcessorState for the given XSL document + * and resultDocument +**/ +ProcessorState::ProcessorState(Document& xslDocument, Document& resultDocument) { + this->xslDocument = &xslDocument; + this->resultDocument = &resultDocument; + initialize(); +} //-- ProcessorState + +/** + * Destroys this ProcessorState +**/ +ProcessorState::~ProcessorState() { + delete dfWildCardTemplate; + delete dfTextTemplate; + delete nodeStack; + + while ( ! variableSets.empty() ) { + delete (NamedMap*) variableSets.pop(); + } + + //-- delete includes + StringList* keys = includes.keys(); + StringListIterator* iter = keys->iterator(); + while (iter->hasNext()) { + String* key = iter->next(); + MITREObjectWrapper* objWrapper + = (MITREObjectWrapper*)includes.remove(*key); + delete (Document*)objWrapper->object; + delete objWrapper; + } + delete iter; + delete keys; + +} //-- ~ProcessorState + + +/** + * Adds the given attribute set to the list of available named attribute sets + * @param attributeSet the Element to add as a named attribute set +**/ +void ProcessorState::addAttributeSet(Element* attributeSet) { + if ( !attributeSet ) return; + String name = attributeSet->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + cout << "missing required name attribute for xsl:" << ATTRIBUTE_SET <getChildNodes(); + for ( int i = 0; i < nl->getLength(); i++) { + Node* node = nl->item(i); + if ( node->getNodeType() == Node::ELEMENT_NODE) { + String nodeName = node->getNodeName(); + String ns; + XMLUtils::getNameSpace(nodeName, ns); + if ( !xsltNameSpace.isEqual(ns)) continue; + String localPart; + XMLUtils::getLocalPart(nodeName, localPart); + if ( ATTRIBUTE.isEqual(localPart) ) attSet->add(node); + } + } + +} //-- addAttributeSet + +/** + * Registers the given ErrorObserver with this ProcessorState +**/ +void ProcessorState::addErrorObserver(ErrorObserver& errorObserver) { + errorObservers.add(&errorObserver); +} //-- addErrorObserver + +/** + * Adds the given XSL document to the list of includes + * The href is used as a key for the include, to prevent + * including the same document more than once +**/ +void ProcessorState::addInclude(const String& href, Document* xslDocument) { + MITREObjectWrapper* objWrapper = new MITREObjectWrapper(); + objWrapper->object = xslDocument; + includes.put(href, objWrapper); +} //-- addInclude + + +/** + * Adds the given template to the list of templates to process + * @param xslTemplate, the Element to add as a template +**/ +void ProcessorState::addTemplate(Element* xslTemplate) { + if ( !xslTemplate ) return; + const String match = xslTemplate->getAttribute(MATCH_ATTR); + String name = xslTemplate->getAttribute(NAME_ATTR); + if ( name.length() > 0 ) { + //-- check for duplicates + MITREObjectWrapper* mObj = (MITREObjectWrapper*)namedTemplates.get(name); + if ( mObj ) { + String warn("error duplicate template name: "); + warn.append(name); + warn.append("\n -- using template closest to end of document"); + recieveError(warn,ErrorObserver::WARNING); + delete mObj; + } + MITREObjectWrapper* oldObj = mObj; + mObj= new MITREObjectWrapper(); + mObj->object = xslTemplate; + namedTemplates.put(name,mObj); + if ( oldObj ) delete oldObj; + } + patternExprHash.put(match, exprParser.createPatternExpr(match)); + templates.add(xslTemplate); +} //-- addTempalte + +/** + * Adds the given node to the result tree + * @param node the Node to add to the result tree +**/ +MBool ProcessorState::addToResultTree(Node* node) { + + Node* current = nodeStack->peek(); + + switch (node->getNodeType()) { + + case Node::ATTRIBUTE_NODE: + { + if (current->getNodeType() != Node::ELEMENT_NODE) return MB_FALSE; + Element* element = (Element*)current; + Attr* attr = (Attr*)node; + element->setAttribute(attr->getName(),attr->getValue()); + delete node; + break; + } + case Node::ELEMENT_NODE: + //-- if current node is the document, make sure + //-- we don't already have a document element. + //-- if we do, create a wrapper element + if ( current == resultDocument ) { + Element* docElement = resultDocument->getDocumentElement(); + if ( docElement ) { + String nodeName(wrapperName); + Element* wrapper = resultDocument->createElement(nodeName); + nodeStack->push(wrapper); + current->appendChild(wrapper); + current = wrapper; + } + } + current->appendChild(node); + break; + case Node::TEXT_NODE : + //-- if current node is the document, create wrapper element + if ( current == resultDocument ) { + String nodeName(wrapperName); + Element* wrapper = resultDocument->createElement(nodeName); + nodeStack->push(wrapper); + current->appendChild(wrapper); + current = wrapper; + } + current->appendChild(node); + break; + case Node::PROCESSING_INSTRUCTION_NODE: + case Node::COMMENT_NODE : + current->appendChild(node); + break; + case Node::DOCUMENT_FRAGMENT_NODE: + { + current->appendChild(node); + delete node; //-- DOM Implementation does not clean up DocumentFragments + break; + + } + //-- only add if not adding to document Node + default: + if (current != resultDocument) current->appendChild(node); + else return MB_FALSE; + break; + } + return MB_TRUE; + +} //-- addToResultTree + +/** + * Copies the node using the rules defined in the XSL specification +**/ +Node* copyNode(Node* node) { + return 0; +} //-- copyNode + +/** + * Finds a template for the given Node. Only templates with + * a mode attribute equal to the given mode will be searched. +**/ +Element* ProcessorState::findTemplate(Node* node, Node* context) { + return findTemplate(node, context, 0); +} //-- findTemplate + +/** + * Finds a template for the given Node. Only templates with + * a mode attribute equal to the given mode will be searched. +**/ +Element* ProcessorState::findTemplate(Node* node, Node* context, String* mode) { + + if (!node) return 0; + Element* matchTemplate = 0; + double currentPriority = 0.5; + + for (int i = 0; i < templates.size(); i++) { + + //cout << "looking at template: " << i << endl; + Element* xslTemplate = (Element*) templates.get(i); + + //-- check mode attribute + Attr* modeAttr = xslTemplate->getAttributeNode(MODE_ATTR); + if (( mode ) && (!modeAttr)) continue; + else if (( !mode ) && (modeAttr)) continue; + else if ( mode ) { + if ( ! mode->isEqual( modeAttr->getValue() ) ) continue; + } + //-- get templates match expr + String match = xslTemplate->getAttribute(MATCH_ATTR); + //cout << "match attr: " << match << endl; + + //-- get Expr from expression hash table + PatternExpr* pExpr = getPatternExpr(match); + if ( !pExpr ) continue; + + if (pExpr->matches(node, context, this)) { + String priorityAttr = xslTemplate->getAttribute(PRIORITY_ATTR); + double tmpPriority = 0; + if ( priorityAttr.length() > 0 ) { + Double dbl(priorityAttr); + tmpPriority = dbl.doubleValue(); + } + else tmpPriority = pExpr->getDefaultPriority(node,context,this); + + if (( !matchTemplate ) || ( tmpPriority >= currentPriority )) + matchTemplate = xslTemplate; + currentPriority = tmpPriority; + } + } + //cout << "findTemplate:end"<iterator(); + while (iter->hasNext()) { + String* key = iter->next(); + MITREObjectWrapper* objWrapper + = (MITREObjectWrapper*)includes.get(*key); + if (xslDocument == objWrapper->object) { + documentBase.append(*key); + break; + } + } + delete iter; + delete keys; +} //-- getDocumentBase + +/** + * @return the included xsl document that was associated with the + * given href, or null if no document is found +**/ +Document* ProcessorState::getInclude(const String& href) { + MITREObjectWrapper* objWrapper = (MITREObjectWrapper*)includes.get(href); + Document* doc = 0; + if (objWrapper) { + doc = (Document*) objWrapper->object; + } + return doc; +} //-- getInclude(String) + +Expr* ProcessorState::getExpr(const String& pattern) { + Expr* expr = (Expr*)exprHash.get(pattern); + if ( !expr ) { + expr = exprParser.createExpr(pattern); + if ( !expr ) { + String err = "invalid expression: "; + err.append(pattern); + expr = new ErrorFunctionCall(err); + } + exprHash.put(pattern, expr); + } + return expr; +} //-- getExpr + +/** + * Returns the template associated with the given name, or + * null if not template is found +**/ +Element* ProcessorState::getNamedTemplate(String& name) { + MITREObjectWrapper* mObj = (MITREObjectWrapper*)namedTemplates.get(name); + if ( mObj ) { + return (Element*)mObj->object; + } + return 0; +} //-- getNamedTemplate + + +/** + * 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* ProcessorState::getNodeStack() { + return nodeStack; +} //-- getNodeStack + +/** + * Returns the OutputFormat which contains information on how + * to serialize the output. I will be removing this soon, when + * change to an event based printer, so that I can serialize + * as I go +**/ +OutputFormat* ProcessorState::getOutputFormat() { + return &format; +} //-- getOutputFormat + +PatternExpr* ProcessorState::getPatternExpr(const String& pattern) { + PatternExpr* pExpr = (PatternExpr*)patternExprHash.get(pattern); + if ( !pExpr ) { + pExpr = exprParser.createPatternExpr(pattern); + patternExprHash.put(pattern, pExpr); + } + return pExpr; +} //-- getPatternExpr + +Document* ProcessorState::getResultDocument() { + return resultDocument; +} //-- getResultDocument + +NodeSet* ProcessorState::getTemplates() { + return &templates; +} //-- getTemplates + + +Stack* ProcessorState::getVariableSetStack() { + return &variableSets; +} //-- getVariableSetStack + +String& ProcessorState::getXSLNamespace() { + return xsltNameSpace; +} //-- getXSLNamespace + +/** + * Determines if the given XSL node allows Whitespace stripping +**/ +MBool ProcessorState::isXSLStripSpaceAllowed(Node* node) { + + if ( !node ) return MB_FALSE; + return (MBool)(PRESERVE != getXMLSpaceMode(node)); + +} //--isXSLStripSpaceAllowed + +/** + * Adds the set of names to the Whitespace preserving element set +**/ +void ProcessorState::preserveSpace(String& names) { + + //-- split names on whitespace + Tokenizer tokenizer(names); + String name; + while ( tokenizer.hasMoreTokens() ) { + tokenizer.nextToken(name); + wsPreserve.add(new String(name)); + wsStrip.remove(name); + } + +} //-- preserveSpace +/** + * Sets the document base for use when resolving relative URIs +**/ +void ProcessorState::setDocumentBase(const String& documentBase) { + this->documentBase = documentBase; +} //-- setDocumentBase + +/** + * Adds the set of names to the Whitespace stripping element set +**/ +void ProcessorState::stripSpace(String& names) { + //-- split names on whitespace + Tokenizer tokenizer(names); + String name; + while ( tokenizer.hasMoreTokens() ) { + tokenizer.nextToken(name); + wsStrip.add(new String(name)); + wsPreserve.remove(name); + } + +} //-- stripSpace + + //--------------------------------------------------/ + //- 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 parent of the given Node. This method is needed + * beacuse with the DOM some nodes such as Attr do not have parents + * @param node the Node to find the parent of + * @return the parent of the given Node, or null if not found +**/ +Node* ProcessorState::getParentNode(Node* node) { + + return domHelper.getParentNode(node); + +} //-- getParentNode + +/** + * 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) { + + StackIterator* iter = variableSets.iterator(); + ExprResult* exprResult = 0; + while ( iter->hasNext() ) { + NamedMap* map = (NamedMap*) iter->next(); + if ( map->get(name)) { + exprResult = ((VariableBinding*)map->get(name))->getValue(); + break; + } + } + delete iter; + return exprResult; +} //-- getVariable + +/** + * Determines if the given XML node allows Whitespace stripping +**/ +MBool ProcessorState::isStripSpaceAllowed(Node* node) { + + if ( !node ) return MB_FALSE; + + switch ( node->getNodeType() ) { + + case Node::ELEMENT_NODE : + { + //-- check Whitespace element names against given Node + String name = node->getNodeName(); + if (wsPreserve.contains(name)) return MB_FALSE; + if (wsStrip.contains(name)) return MB_TRUE; + String method; + if (format.getMethod(method).isEqual("html")) { + String ucName = name; + ucName.toUpperCase(); + if (ucName.isEqual("SCRIPT")) return MB_FALSE; + } + break; + } + case Node::TEXT_NODE: + return isStripSpaceAllowed(node->getParentNode()); + default: + break; + } + XMLSpaceMode mode = getXMLSpaceMode(node); + if (mode == DEFAULT) return (MBool)(defaultSpace == STRIP); + return (MBool)(STRIP == mode); + +} //--isStripSpaceAllowed + + +/** + * 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); + } + delete iter; +} //-- recieveError + + +/** + * Sorts the given NodeSet by DocumentOrder. + * @param nodes the NodeSet to sort + *
+ * Note: I will be moving this functionality elsewhere soon +**/ +void ProcessorState::sortByDocumentOrder(NodeSet* nodes) { + if ((!nodes) || (nodes->size() < 2)) return; + + NodeSet sorted(nodes->size()); + sorted.add(nodes->get(0)); + + int i = 1; + for ( ; i < nodes->size(); i++) { + Node* node = nodes->get(i); + for (int k = 0; k < sorted.size(); k++) { + Node* tmpNode = sorted.get(k); + if (domHelper.appearsFirst(node, tmpNode) == node) { + sorted.add(k, node); + break; + } + else if (k == sorted.size()-1) { + sorted.add(node); + break; + } + } + } + + nodes->clear(); + for (i = 0; i < sorted.size(); i++) + nodes->add(sorted.get(i)); + + sorted.clear(); + +} //-- sortByDocumentOrder + + //-------------------/ + //- Private Methods -/ +//-------------------/ + +/** + * Returns the closest xml:space value for the given Text node +**/ +ProcessorState::XMLSpaceMode ProcessorState::getXMLSpaceMode(Node* node) { + + if (!node) return DEFAULT; //-- we should never see this + + Node* parent = node; + while ( parent ) { + switch ( parent->getNodeType() ) { + case Node::ELEMENT_NODE: + { + String value = ((Element*)parent)->getAttribute(XML_SPACE); + if ( value.isEqual(PRESERVE_VALUE)) { + return PRESERVE; + } + break; + } + case Node::TEXT_NODE: + //-- we will only see this the first time through the loop + //-- if the argument node is a text node + break; + default: + return DEFAULT; + } + parent = parent->getParentNode(); + } + return DEFAULT; + +} //-- getXMLSpaceMode + +/** + * Initializes this ProcessorState +**/ +void ProcessorState::initialize() { + + //-- initialize default-space + defaultSpace = PRESERVE; + + //-- add global variable set + NamedMap* globalVars = new NamedMap(); + globalVars->setObjectDeletion(MB_TRUE); + variableSets.push(globalVars); + + /* turn object deletion on for some of the Maps (NamedMap) */ + exprHash.setObjectDeletion(MB_TRUE); + patternExprHash.setObjectDeletion(MB_TRUE); + nameSpaceMap.setObjectDeletion(MB_TRUE); + namedAttributeSets.setObjectDeletion(MB_TRUE); + + //-- named templates uses deletion, to remove the ObjectWrappers + namedTemplates.setObjectDeletion(MB_TRUE); + //-- do not set ObjectDeletion for templates, since the Document + //-- handles the cleanup + + //-- create NodeStack + nodeStack = new NodeStack(); + nodeStack->push(this->resultDocument); + + //-- determine xsl properties + Element* element = xslDocument->getDocumentElement(); + if ( element ) { + //-- process namespace nodes + NamedNodeMap* atts = element->getAttributes(); + if ( atts ) { + for (int i = 0; i < atts->getLength(); i++) { + Attr* attr = (Attr*)atts->item(i); + String attName = attr->getName(); + String attValue = attr->getValue(); + if ( attName.indexOf(XMLUtils::XMLNS) == 0) { + String ns; + XMLUtils::getLocalPart(attName, ns); + //-- default namespace + if ( attName.isEqual(XMLUtils::XMLNS) ) { + //-- handle default + //-- do nothing for now + } + // namespace declaration + else { + String ns; + XMLUtils::getNameSpace(attName, ns); + nameSpaceMap.put(ns, new String(attValue)); + } + // check for XSL namespace + if ( attValue.indexOf(XSLT_NS) == 0) { + xsltNameSpace = ns; + } + } + else if ( attName.isEqual(DEFAULT_SPACE_ATTR) ) { + if ( attValue.isEqual(STRIP_VALUE) ) { + defaultSpace = STRIP; + } + } + else if ( attName.isEqual(RESULT_NS_ATTR) ) { + if (attValue.length() > 0) { + if ( attValue.indexOf(HTML_NS) == 0 ) { + format.setMethod("html"); + } + else format.setMethod(attValue); + } + } + else if ( attName.isEqual(INDENT_RESULT_ATTR) ) { + if ( attValue.length() > 0 ) { + format.setIndent(attValue.isEqual(YES_VALUE)); + } + } + + } //-- end for each att + } //-- end if atts are not null + } //-- end if document element exists + + /* Create default (built-in) templates */ + + //-- create default template for elements + + + String templateName = xsltNameSpace; + if (templateName.length() > 0) templateName.append(':'); + templateName.append(TEMPLATE); + + String actionName = xsltNameSpace; + if ( actionName.length()>0) actionName.append(':'); + actionName.append(APPLY_TEMPLATES); + + dfWildCardTemplate = xslDocument->createElement(templateName); + dfWildCardTemplate->setAttribute(MATCH_ATTR, "* | /"); + dfWildCardTemplate->appendChild(xslDocument->createElement(actionName)); + templates.add(dfWildCardTemplate); + + //-- create default "built-in" templates for text nodes + dfTextTemplate = xslDocument->createElement(templateName); + dfTextTemplate->setAttribute(MATCH_ATTR, "text()|@*"); + actionName = xsltNameSpace; + if ( actionName.length()>0) actionName.append(':'); + actionName.append(VALUE_OF); + Element* value_of = xslDocument->createElement(actionName); + value_of->setAttribute(SELECT_ATTR, IDENTITY_OP); + dfTextTemplate->appendChild(value_of); + templates.add(dfTextTemplate); + + //-- add PatternExpr hash for default templates + patternExprHash.put("*", new WildCardExpr()); + patternExprHash.put("/", new RootExpr()); + patternExprHash.put("text()", new TextExpr()); + + //cout << "XSLT namespace: " << xsltNameSpace << endl; +} //-- initialize + + diff --git a/mozilla/extensions/transformiix/source/xslt/ProcessorState.h b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h new file mode 100644 index 00000000000..a2f6828d860 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/ProcessorState.h @@ -0,0 +1,350 @@ +/* + * 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. + * + * $Id: ProcessorState.h,v 1.1 2000-04-06 07:46:46 kvisco%ziplink.net Exp $ + */ + + + +#ifndef TRANSFRMX_PROCESSORSTATE_H +#define TRANSFRMX_PROCESSORSTATE_H + +#include "dom.h" +#include "DOMHelper.h" +#include "XMLUtils.h" +#include "Names.h" +#include "NodeSet.h" +#include "NodeStack.h" +#include "Stack.h" +#include "ErrorObserver.h" +#include "List.h" +#include "NamedMap.h" +#include "ExprParser.h" +#include "Expr.h" +#include "StringList.h" +#include "Tokenizer.h" +#include "VariableBinding.h" +#include "OutputFormat.h" + +/** + * Class used for keeping the current state of the XSL Processor + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:46 $ +**/ +class ProcessorState : public ContextState +{ + +public: + + static const String wrapperNSPrefix; + static const String wrapperName; + static const String wrapperNS; + + /** + * Creates a new ProcessorState for the given XSL document + * And result Document + **/ + ProcessorState(Document& xslDocument, Document& resultDocument); + + /** + * Destroys this ProcessorState + **/ + ~ProcessorState(); + + /** + * Adds the given attribute set to the list of available named attribute sets + * @param attributeSet the Element to add as a named attribute set + **/ + void addAttributeSet(Element* attributeSet); + + /** + * Registers the given ErrorObserver with this ProcessorState + **/ + void addErrorObserver(ErrorObserver& errorObserver); + + + /** + * Adds the given XSL document to the list of includes + * The href is used as a key for the include, to prevent + * including the same document more than once + **/ + void addInclude(const String& href, Document* xslDocument); + + /** + * Adds the given template to the list of templates to process + * @param xslTemplate, the Element to add as a template + **/ + void addTemplate(Element* xslTemplate); + + /** + * Adds the given Node to the Result Tree + * + **/ + MBool addToResultTree(Node* node); + + /** + * Copies the node using the rules defined in the XSL specification + **/ + Node* copyNode(Node* node); + + /** + * Returns the AttributeSet associated with the given name + * or null if no AttributeSet is found + **/ + NodeSet* getAttributeSet(const String& name); + + + /** + * Returns the document base for resolving relative URIs + **/ + const String& getDocumentBase(); + + /** + * Returns the href for the given xsl document by returning + * it's reference from the include or import list + **/ + void getDocumentHref(Document* xslDocument, String& documentBase); + + /** + * @return the included xsl document that was associated with the + * given href, or null if no document is found + **/ + Document* getInclude(const String& href); + + /** + * Returns the template associated with the given name, or + * null if not template is found + **/ + Element* getNamedTemplate(String& name); + + /** + * 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 + * change to an event based printer, so that I can serialize + * as I go + **/ + OutputFormat* getOutputFormat(); + + + Stack* getVariableSetStack(); + + Expr* getExpr(const String& pattern); + PatternExpr* getPatternExpr(const String& pattern); + + /** + * Returns a pointer to the result document + **/ + Document* getResultDocument(); + + /** + * Returns a pointer to a list of available templates + **/ + NodeSet* getTemplates(); + + String& getXSLNamespace(); + + /** + * Finds a template for the given Node. Only templates without + * a mode attribute will be searched. + **/ + Element* findTemplate(Node* node, Node* context); + + /** + * Finds a template for the given Node. Only templates with + * a mode attribute equal to the given mode will be searched. + **/ + Element* findTemplate(Node* node, Node* context, String* mode); + + /** + * Determines if the given XSL node allows Whitespace stripping + **/ + MBool isXSLStripSpaceAllowed(Node* node); + + /** + * Adds the set of names to the Whitespace preserving element set + **/ + void preserveSpace(String& names); + + /** + * Sets the document base for including and importing stylesheets + **/ + void setDocumentBase(const String& documentBase); + + /** + * Adds the set of names to the Whitespace stripping element set + **/ + void stripSpace(String& names); + + + //-------------------------------------/ + //- Virtual Methods from ContextState -/ + //-------------------------------------/ + + /** + * Returns the parent of the given Node. This method is needed + * beacuse with the DOM some nodes such as Attr do not have parents + * @param node the Node to find the parent of + * @return the parent of the given Node, or null if not found + **/ + virtual Node* getParentNode(Node* node); + + /** + * 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); + + /** + * Sorts the given NodeSet by DocumentOrder. + * @param nodes the NodeSet to sort + *
+ * Note: I will be moving this functionality elsewhere soon + **/ + virtual void sortByDocumentOrder(NodeSet* nodes); + +private: + + enum XMLSpaceMode {STRIP = 0, DEFAULT, PRESERVE}; + + + /** + * Allows us to overcome some DOM deficiencies + **/ + DOMHelper domHelper; + + /** + * The list of ErrorObservers registered with this ProcessorState + **/ + List errorObservers; + + /** + * A map for included stylesheets + * (used for deletion when processing is done) + **/ + NamedMap includes; + + /** + * A map for named attribute sets + **/ + NamedMap namedAttributeSets; + + /** + * A map for named templates + **/ + NamedMap namedTemplates; + + /** + * Current stack of nodes, where we are in the result document tree + **/ + NodeStack* nodeStack; + + + /** + * The output format used when serializing the result + **/ + OutputFormat format; + + /** + * The set of whitespace preserving elements + **/ + StringList wsPreserve; + + /** + * The set of whitespace stripping elements + **/ + StringList wsStrip; + + /** + * The set of whitespace stripping elements + **/ + XMLSpaceMode defaultSpace; + + /** + * A set of all availabe templates + **/ + NodeSet templates; + + + Stack nodeSetStack; + Document* xslDocument; + Document* resultDocument; + NamedMap exprHash; + NamedMap patternExprHash; + Stack variableSets; + ExprParser exprParser; + String xsltNameSpace; + NamedMap nameSpaceMap; + + //-- default templates + Element* dfWildCardTemplate; + Element* dfTextTemplate; + + String documentBase; + + /** + * Returns the closest xml:space value for the given node + **/ + XMLSpaceMode getXMLSpaceMode(Node* node); + + /** + * Initializes the ProcessorState + **/ + void initialize(); + +}; //-- ProcessorState + + +#endif + diff --git a/mozilla/extensions/transformiix/source/xslt/VariableBinding.cpp b/mozilla/extensions/transformiix/source/xslt/VariableBinding.cpp new file mode 100644 index 00000000000..be48172d2af --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/VariableBinding.cpp @@ -0,0 +1,125 @@ +/* + * 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. + * + * $Id: VariableBinding.cpp,v 1.1 2000-04-06 07:46:52 kvisco%ziplink.net Exp $ + */ + +#include "VariableBinding.h" + + +/** + * Creates a variable binding with no name or value + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:52 $ +**/ +VariableBinding::VariableBinding() { + this->allowShadow = MB_FALSE; + this->value = 0; + this->shadowValue = 0; +} //-- VariableBinding + +/** +* Creates a variable binding with the given name, and not bound to any value +**/ +VariableBinding::VariableBinding(const String& name) { + this->name = name; + this->allowShadow = MB_FALSE; + this->value = 0; + this->shadowValue = 0; +} //-- VariableBinding + +/** +* Creates a variable binding with the given name, and value +**/ +VariableBinding::VariableBinding(const String& name, ExprResult* value) { + this->name.append(name); + this->allowShadow = MB_FALSE; + this->value = value; + this->shadowValue = 0; +} //-- Variable + +/** +* Destroys this VariableBinding +**/ +VariableBinding::~VariableBinding() { + delete shadowValue; + delete value; +} //-- ~Variable + +/** +* Allows this variable to be shadowed by another variable +**/ +void VariableBinding::allowShadowing() { + allowShadow = MB_TRUE; +} //-- allowShadowing + +/** +* Disallows this variable to be shadowed by another variable +**/ +void VariableBinding::disallowShadowing() { + allowShadow = MB_FALSE; +} //-- disallowShadowing + +/** +* Returns the name of this variable +**/ +const String& VariableBinding::getName() { + return (const String&)name; +} //-- getName + +/** +* Returns the value of this variable +**/ +ExprResult* VariableBinding::getValue() { + if (shadowValue) return shadowValue; + return value; +} //-- getValue + +/** +* Returns the flag indicating whether variable shadowing is allowed +**/ +MBool VariableBinding::isShadowingAllowed() { + return allowShadow; +} //-- isShadowingAllowed + +/** +* Sets the name of this variable +**/ +void VariableBinding::setName(const String& name) { + this->name = name; +} //-- setName + +/** + * Sets the shadow value of this binding if shadowing is turned on +**/ +void VariableBinding::setShadowValue(ExprResult* value) { + if (allowShadow) this->shadowValue = value; +} //-- setShadowValue + +/** +* Sets the value of this variable +**/ +void VariableBinding::setValue(ExprResult* value) { + this->value = value; +} //-- setValue + diff --git a/mozilla/extensions/transformiix/source/xslt/VariableBinding.h b/mozilla/extensions/transformiix/source/xslt/VariableBinding.h new file mode 100644 index 00000000000..30649a09412 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/VariableBinding.h @@ -0,0 +1,127 @@ +/* + * 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. + * + * $Id: VariableBinding.h,v 1.1 2000-04-06 07:46:55 kvisco%ziplink.net Exp $ + */ + +#ifndef MITREXSL_VARIABLE_H +#define MITREXSL_VARIABLE_H + +#include "MITREObject.h" +#include "String.h" +#include "baseutils.h" +#include "ExprResult.h" + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:46:55 $ +**/ +class VariableBinding : public MITREObject { + +public: + + /** + * Creates a variable binding with no name or value + **/ + VariableBinding(); + + /** + * Creates a variable binding with the given name, and not bound to any value + **/ + VariableBinding(const String& name); + + /** + * Creates a variable with the given name, and value + **/ + VariableBinding(const String& name, ExprResult* value); + + + /** + * Destroys this variable binding + **/ + virtual ~VariableBinding(); + + /** + * Allows this variable to be shadowed by another variable + **/ + void allowShadowing(); + + /** + * Disallows this variable to be shadowed by another variable + **/ + void disallowShadowing(); + + /** + * Returns the name of this variable + **/ + const String& getName(); + + /** + * Returns the value of this variable, if shadowing is turned on + * and the shadow value is not null, it will be returned + **/ + ExprResult* getValue(); + + /** + * Returns the flag indicating whether variable shadowing is allowed + **/ + MBool isShadowingAllowed(); + + /** + * Sets the name of this variable + **/ + void setName(const String& name); + + /** + * Sets the shadow value of this binding + **/ + void setShadowValue(ExprResult* value); + + /** + * Sets the value of this variable + **/ + void setValue(ExprResult* value); + + + +private: + + /** + * flag to turn on and off shadowing + **/ + MBool allowShadow; + + /** + * The name of this variable + **/ + String name; + + /** + * The value of this variable + **/ + ExprResult* value; + + ExprResult* shadowValue; +}; + +#endif diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp new file mode 100644 index 00000000000..8d7fa0c3f2a --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -0,0 +1,1565 @@ +/* + * 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. + * Bob Miller, kbob@oblix.com + * -- plugged core leak. + * Pierre Phaneuf, pp@ludusdesign.com + * -- fixed some XPCOM usage. + * + * $Id: XSLTProcessor.cpp,v 1.1 2000-04-06 07:47:01 kvisco%ziplink.net Exp $ + */ + +#include "XSLTProcessor.h" + + + //-----------------------------------/ + //- Implementation of XSLTProcessor -/ +//-----------------------------------/ + +/** + * XSLTProcessor is a class for Processing XSL styelsheets + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:47:01 $ +**/ + +/** + * A warning message used by all templates that do not allow non character + * data to be generated +**/ +const String XSLTProcessor::NON_TEXT_TEMPLATE_WARNING = +"templates for the following element are not allowed to generate non character data: "; + +/** + * Creates a new XSLTProcessor +**/ +XSLTProcessor::XSLTProcessor() { + +#ifdef MOZILLA + NS_INIT_ISUPPORTS(); +#endif + + xslVersion.append("1.0"); + appName.append("TransforMiiX"); + appVersion.append("1.0 [beta v20000405]"); + + + //-- create XSL element types + xslTypes.setObjectDeletion(MB_TRUE); + xslTypes.put(APPLY_TEMPLATES, new XSLType(XSLType::APPLY_TEMPLATES)); + xslTypes.put(ATTRIBUTE, new XSLType(XSLType::ATTRIBUTE)); + xslTypes.put(ATTRIBUTE_SET, new XSLType(XSLType::ATTRIBUTE_SET)); + xslTypes.put(CALL_TEMPLATE, new XSLType(XSLType::CALL_TEMPLATE)); + xslTypes.put(CHOOSE, new XSLType(XSLType::CHOOSE)); + xslTypes.put(COMMENT, new XSLType(XSLType::COMMENT)); + xslTypes.put(COPY, new XSLType(XSLType::COPY)); + xslTypes.put(COPY_OF, new XSLType(XSLType::COPY_OF)); + xslTypes.put(ELEMENT, new XSLType(XSLType::ELEMENT)); + xslTypes.put(FOR_EACH, new XSLType(XSLType::FOR_EACH)); + xslTypes.put(IF, new XSLType(XSLType::IF)); + xslTypes.put(INCLUDE, new XSLType(XSLType::INCLUDE)); + xslTypes.put(MESSAGE, new XSLType(XSLType::MESSAGE)); + xslTypes.put(NUMBER, new XSLType(XSLType::NUMBER)); + xslTypes.put(OTHERWISE, new XSLType(XSLType::OTHERWISE)); + xslTypes.put(OUTPUT, new XSLType(XSLType::OUTPUT)); + xslTypes.put(PARAM, new XSLType(XSLType::PARAM)); + xslTypes.put(PI, new XSLType(XSLType::PI)); + xslTypes.put(PRESERVE_SPACE, new XSLType(XSLType::PRESERVE_SPACE)); + xslTypes.put(STRIP_SPACE, new XSLType(XSLType::STRIP_SPACE)); + xslTypes.put(TEMPLATE, new XSLType(XSLType::TEMPLATE)); + xslTypes.put(TEXT, new XSLType(XSLType::TEXT)); + xslTypes.put(VALUE_OF, new XSLType(XSLType::VALUE_OF)); + xslTypes.put(VARIABLE, new XSLType(XSLType::VARIABLE)); + xslTypes.put(WHEN, new XSLType(XSLType::WHEN)); + xslTypes.put(WITH_PARAM, new XSLType(XSLType::WITH_PARAM)); + + //-- proprietary debug elements + xslTypes.put("expr-debug", new XSLType(XSLType::EXPR_DEBUG)); +} //-- XSLTProcessor + +/** + * Default destructor +**/ +XSLTProcessor::~XSLTProcessor() { + //-- currently does nothing, but added for future use +} //-- ~XSLTProcessor + +#ifdef MOZILLA +// Provide a Create method that can be called by a factory constructor: +NS_METHOD +XSLTProcessor::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) +{ + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + XSLTProcessor* xslp = new XSLTProcessor(); + if (xslp == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + // Note that Create doesn't initialize the instance -- that has to + // be done by the caller since the initialization args aren't passed + // in here. + + // AddRef before calling QI -- this makes it easier to handle the QI + // failure case because we'll always just Release and return + NS_ADDREF(xslp); + nsresult rv = xslp->QueryInterface(aIID, aResult); + + // This will free it if QI failed: + NS_RELEASE(xslp); + return rv; +} + +NS_IMPL_ISUPPORTS(XSLTProcessor, NS_GET_IID(nsIDocumentTransformer)); +#endif + +/** + * Registers the given ErrorObserver with this ProcessorState +**/ +void XSLTProcessor::addErrorObserver(ErrorObserver& errorObserver) { + errorObservers.add(&errorObserver); +} //-- addErrorObserver + +#ifndef MOZILLA +void XSLTProcessor::print + (Document& document, OutputFormat* format, ostream& out) +{ + + XMLPrinter* xmlPrinter = 0; + ostream* target = 0; + if ( !out ) target = &cout; + else target = &out; + + MBool indent = MB_FALSE; + if (format->isMethodExplicit()) { + if (format->isHTMLOutput()) xmlPrinter = new HTMLPrinter(*target); + else xmlPrinter = new XMLPrinter(*target); + indent = format->getIndent(); + } + else { + //-- try to determine output method + Element* element = document.getDocumentElement(); + String name; + if (element) name = element->getNodeName(); + name.toUpperCase(); + if (name.isEqual("HTML")) { + xmlPrinter = new HTMLPrinter(*target); + if (format->isIndentExplicit()) indent = format->getIndent(); + else indent = MB_TRUE; + } + else { + xmlPrinter = new XMLPrinter(*target); + indent = format->getIndent(); + } + } + + xmlPrinter->setUseFormat(indent); + xmlPrinter->print(&document); + delete xmlPrinter; + +} //-- print +#endif + +String& XSLTProcessor::getAppName() { + return appName; +} //-- getAppName + +String& XSLTProcessor::getAppVersion() { + return appVersion; +} //-- getAppVersion + +#ifndef MOZILLA +/** + * Parses all XML Stylesheet PIs associated with the + * given XML document. If any stylesheet PIs are found with + * type="text/xsl" the href psuedo attribute value will be + * added to the given href argument. If multiple text/xsl stylesheet PIs + * are found, the one closest to the end of the document is used. +**/ +void XSLTProcessor::getHrefFromStylesheetPI(Document& xmlDocument, String& href) { + + NodeList* nl = xmlDocument.getChildNodes(); + String type; + String tmpHref; + for ( int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + if ( node->getNodeType() == Node::PROCESSING_INSTRUCTION_NODE ) { + String target = ((ProcessingInstruction*)node)->getTarget(); + if ( STYLESHEET_PI.isEqual(target) || + STYLESHEET_PI_OLD.isEqual(target) ) { + String data = ((ProcessingInstruction*)node)->getData(); + type.clear(); + tmpHref.clear(); + parseStylesheetPI(data, type, tmpHref); + if ( XSL_MIME_TYPE.isEqual(type) ) { + href.clear(); + href.append(tmpHref); + } + } + } + } + +} //-- getHrefFromStylesheetPI + +/** + * Parses the contents of data, and returns the type and href psuedo attributes +**/ +void XSLTProcessor::parseStylesheetPI(String& data, String& type, String& href) { + + Int32 size = data.length(); + NamedMap bufferMap; + bufferMap.put("type", &type); + bufferMap.put("href", &href); + int ccount = 0; + MBool inLiteral = MB_FALSE; + char matchQuote = '"'; + String sink; + String* buffer = &sink; + + for (ccount = 0; ccount < size; ccount++) { + char ch = data.charAt(ccount); + switch ( ch ) { + case ' ' : + if ( inLiteral ) { + buffer->append(ch); + } + break; + case '=': + if ( inLiteral ) buffer->append(ch); + else if ( buffer->length() > 0 ) { + buffer = (String*)bufferMap.get(*buffer); + if ( !buffer ) { + sink.clear(); + buffer = &sink; + } + } + break; + case '"' : + case '\'': + if (inLiteral) { + if ( matchQuote == ch ) { + inLiteral = MB_FALSE; + sink.clear(); + buffer = &sink; + } + else buffer->append(ch); + } + else { + inLiteral = MB_TRUE; + matchQuote = ch; + } + break; + default: + buffer->append(ch); + break; + } + } + +} //-- parseStylesheetPI + +/** + * Processes the given XML Document, the XSL stylesheet + * will be retrieved from the XML Stylesheet Processing instruction, + * otherwise an empty document will be returned. + * @param xmlDocument the XML document to process + * @param documentBase the document base of the XML document, for + * resolving relative URIs + * @return the result tree. +**/ +Document* XSLTProcessor::process(Document& xmlDocument, String& documentBase) { + //-- look for Stylesheet PI + Document xslDocument; //-- empty for now + return process(xmlDocument, xslDocument, documentBase); +} //-- process + +/** + * Reads an XML Document from the given XML input stream, and + * processes the document using the XSL document derived from + * the given XSL input stream. + * @return the result tree. +**/ +Document* XSLTProcessor::process +(istream& xmlInput, istream& xslInput, String& documentBase) { + //-- read in XML Document + XMLParser xmlParser; + Document* xmlDoc = xmlParser.parse(xmlInput); + if (!xmlDoc) { + String err("error reading XML document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + return 0; + } + //-- Read in XSL document + Document* xslDoc = xmlParser.parse(xslInput); + if (!xslDoc) { + String err("error reading XSL stylesheet document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + delete xmlDoc; + return 0; + } + Document* result = process(*xmlDoc, *xslDoc, documentBase); + delete xmlDoc; + delete xslDoc; + return result; +} //-- process + +/** + * Reads an XML document from the given XML input stream. The + * XML document is processed using the associated XSL document + * retrieved from the XML document's Stylesheet Processing Instruction, + * otherwise an empty document will be returned. + * @param xmlDocument the XML document to process + * @param documentBase the document base of the XML document, for + * resolving relative URIs + * @return the result tree. +**/ +Document* XSLTProcessor::process(istream& xmlInput, String& documentBase) { + //-- read in XML Document + XMLParser xmlParser; + Document* xmlDoc = xmlParser.parse(xmlInput); + if (!xmlDoc) { + String err("error reading XML document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + return 0; + } + //-- Read in XSL document + String href; + String errMsg; + getHrefFromStylesheetPI(*xmlDoc, href); + istream* xslInput = URIUtils::getInputStream(href,documentBase,errMsg); + Document* xslDoc = 0; + if ( xslInput ) { + xslDoc = xmlParser.parse(*xslInput); + delete xslInput; + } + if (!xslDoc) { + String err("error reading XSL stylesheet document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + delete xmlDoc; + return 0; + } + Document* result = process(*xmlDoc, *xslDoc, documentBase); + delete xmlDoc; + delete xslDoc; + return result; +} //-- process +#endif + +/** + * Processes the Top level elements for an XSL stylesheet +**/ +void XSLTProcessor::processTopLevel + (Document* xslDocument, ProcessorState* ps) +{ + + if (!xslDocument) return; + + //-------------------------------------------------------/ + //- index templates and process top level xsl elements -/ + //-------------------------------------------------------/ + + Element* stylesheet = xslDocument->getDocumentElement(); + + if (!stylesheet) return; + + NodeList* nl = stylesheet->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++) { + Node* node = nl->item(i); + if (node->getNodeType() == Node::ELEMENT_NODE) { + Element* element = (Element*)node; + DOMString name = element->getNodeName(); + switch (getElementType(name, ps)) { + case XSLType::ATTRIBUTE_SET: + ps->addAttributeSet(element); + break; + case XSLType::PARAM : + { + String name = element->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + notifyError("missing required name attribute for xsl:param"); + break; + } + + ExprResult* exprResult + = processVariable(node, element, ps); + + bindVariable(name, exprResult, MB_TRUE, ps); + break; + } + case XSLType::INCLUDE : + { + + String href = element->getAttribute(HREF_ATTR); + //-- Read in XSL document + + if (ps->getInclude(href)) { + String err("stylesheet already included: "); + err.append(href); + notifyError(err, ErrorObserver::WARNING); + break; + } + + //-- get document base + String documentBase; + String currentHref; + //ps->getDocumentHref(element->getOwnerDocument(), + // currentHref); + if (currentHref.length() == 0) { + documentBase.append(ps->getDocumentBase()); + } + else { + URIUtils::getDocumentBase(currentHref, documentBase); + } + + String errMsg; + + istream* xslInput + = URIUtils::getInputStream(href,documentBase,errMsg); + Document* xslDoc = 0; + XMLParser xmlParser; + if ( xslInput ) { + xslDoc = xmlParser.parse(*xslInput); + delete xslInput; + } + if (!xslDoc) { + String err("error including XSL stylesheet: "); + err.append(href); + err.append("; "); + err.append(xmlParser.getErrorString()); + notifyError(err); + } + else { + //-- add stylesheet to list of includes + ps->addInclude(href, xslDoc); + processTopLevel(xslDoc, ps); + } + break; + + } + case XSLType::OUTPUT : + { + OutputFormat* format = ps->getOutputFormat(); + + String attValue = element->getAttribute(METHOD_ATTR); + if (attValue.length() > 0) format->setMethod(attValue); + + attValue = element->getAttribute(VERSION_ATTR); + if (attValue.length() > 0) format->setVersion(attValue); + + attValue = element->getAttribute(ENCODING_ATTR); + if (attValue.length() > 0) format->setEncoding(attValue); + + attValue = element->getAttribute(INDENT_ATTR); + if (attValue.length() > 0) { + MBool allowIndent = attValue.isEqual(YES_VALUE); + format->setIndent(allowIndent); + } + + attValue = element->getAttribute(DOCTYPE_PUBLIC_ATTR); + if (attValue.length() > 0) + format->setDoctypePublic(attValue); + + attValue = element->getAttribute(DOCTYPE_SYSTEM_ATTR); + if (attValue.length() > 0) + format->setDoctypeSystem(attValue); + + break; + } + case XSLType::TEMPLATE : + ps->addTemplate(element); + break; + case XSLType::VARIABLE : + { + String name = element->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + notifyError("missing required name attribute for xsl:variable"); + break; + } + ExprResult* exprResult = processVariable(node, element, ps); + bindVariable(name, exprResult, MB_FALSE, ps); + break; + } + case XSLType::PRESERVE_SPACE : + { + String elements = element->getAttribute(ELEMENTS_ATTR); + if ( elements.length() == 0 ) { + //-- add error to ErrorObserver + String err("missing required 'elements' attribute for "); + err.append("xsl:preserve-space"); + notifyError(err); + } + else ps->preserveSpace(elements); + break; + } + case XSLType::STRIP_SPACE : + { + String elements = element->getAttribute(ELEMENTS_ATTR); + if ( elements.length() == 0 ) { + //-- add error to ErrorObserver + String err("missing required 'elements' attribute for "); + err.append("xsl:strip-space"); + notifyError(err); + } + else ps->stripSpace(elements); + break; + } + default: + //-- unknown + break; + } + } + } + +} //-- process(Document, ProcessorState) + +/** + * Processes the given XML Document using the given XSL document + * and returns the result tree +**/ +Document* XSLTProcessor::process + (Document& xmlDocument, Document& xslDocument, String& documentBase) +{ + + Document* result = new Document(); + + //-- create a new ProcessorState + ProcessorState ps(xslDocument, *result); + ps.setDocumentBase(documentBase); + + //-- add error observers + ListIterator* iter = errorObservers.iterator(); + while ( iter->hasNext()) { + ps.addErrorObserver(*((ErrorObserver*)iter->next())); + } + delete iter; + + //-------------------------------------------------------/ + //- index templates and process top level xsl elements -/ + //-------------------------------------------------------/ + + processTopLevel(&xslDocument, &ps); + + //----------------------------------------/ + //- Process root of XML source document -/ + //--------------------------------------/ + process(&xmlDocument, &xmlDocument, &ps); + + //-- return result Document + return result; +} //-- process + +#ifndef MOZILLA +/** + * Processes the given XML Document using the given XSL document + * and prints the results to the given ostream argument +**/ +void XSLTProcessor::process + ( Document& xmlDocument, + Document& xslDocument, + ostream& out, + String& documentBase ) +{ + + + Document* result = new Document(); + + //-- create a new ProcessorState + ProcessorState ps(xslDocument, *result); + ps.setDocumentBase(documentBase); + + //-- add error observers + ListIterator* iter = errorObservers.iterator(); + while ( iter->hasNext()) { + ps.addErrorObserver(*((ErrorObserver*)iter->next())); + } + delete iter; + + //-------------------------------------------------------/ + //- index templates and process top level xsl elements -/ + //-------------------------------------------------------/ + + processTopLevel(&xslDocument, &ps); + + //----------------------------------------/ + //- Process root of XML source document -/ + //--------------------------------------/ + process(&xmlDocument, &xmlDocument, &ps); + + print(*result, ps.getOutputFormat(), out); + + delete result; +} //-- process + + +/** + * Reads an XML Document from the given XML input stream. + * The XSL Stylesheet is obtained from the XML Documents stylesheet PI. + * If no Stylesheet is found, an empty document will be the result; + * otherwise the XML Document is processed using the stylesheet. + * The result tree is printed to the given ostream argument, + * will not close the ostream argument +**/ +void XSLTProcessor::process + (istream& xmlInput, ostream& out, String& documentBase) +{ + + XMLParser xmlParser; + Document* xmlDoc = xmlParser.parse(xmlInput); + if (!xmlDoc) { + String err("error reading XML document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + return; + } + //-- Read in XSL document + String href; + String errMsg; + getHrefFromStylesheetPI(*xmlDoc, href); + istream* xslInput = URIUtils::getInputStream(href,documentBase,errMsg); + Document* xslDoc = 0; + if ( xslInput ) { + xslDoc = xmlParser.parse(*xslInput); + delete xslInput; + } + if (!xslDoc) { + String err("error reading XSL stylesheet document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + delete xmlDoc; + return; + } + process(*xmlDoc, *xslDoc, out, documentBase); + delete xmlDoc; + delete xslDoc; +} //-- process + +/** + * Reads an XML Document from the given XML input stream, and + * processes the document using the XSL document derived from + * the given XSL input stream. + * The result tree is printed to the given ostream argument, + * will not close the ostream argument +**/ +void XSLTProcessor::process + (istream& xmlInput, istream& xslInput, ostream& out, String& documentBase) +{ + //-- read in XML Document + XMLParser xmlParser; + Document* xmlDoc = xmlParser.parse(xmlInput); + if (!xmlDoc) { + String err("error reading XML document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + return; + } + //-- read in XSL Document + Document* xslDoc = xmlParser.parse(xslInput); + if (!xslDoc) { + String err("error reading XSL stylesheet document: "); + err.append(xmlParser.getErrorString()); + notifyError(err, ErrorObserver::FATAL); + delete xmlDoc; + return; + } + process(*xmlDoc, *xslDoc, out, documentBase); + delete xmlDoc; + delete xslDoc; +} //-- process + +#endif // ifndef MOZILLA + + //-------------------/ + //- Private Methods -/ +//-------------------/ + +void XSLTProcessor::bindVariable + (String& name, ExprResult* value, MBool allowShadowing, ProcessorState* ps) +{ + NamedMap* varSet = (NamedMap*)ps->getVariableSetStack()->peek(); + //-- check for duplicate variable names + VariableBinding* current = (VariableBinding*) varSet->get(name); + VariableBinding* binding = 0; + if (current) { + binding = current; + if (current->isShadowingAllowed() ) { + current->setShadowValue(value); + } + else { + //-- error cannot rebind variables + String err("error cannot rebind variables: "); + err.append(name); + err.append(" already exists in this scope."); + notifyError(err); + } + } + else { + binding = new VariableBinding(name, value); + varSet->put((const String&)name, binding); + } + if ( allowShadowing ) binding->allowShadowing(); + else binding->disallowShadowing(); + +} //-- bindVariable + +/** + * Returns the type of Element represented by the given name + * @return the XSLType represented by the given element name +**/ +short XSLTProcessor::getElementType(String& name, ProcessorState* ps) { + + + String namePart; + XMLUtils::getNameSpace(name, namePart); + XSLType* xslType = 0; + + if ( ps->getXSLNamespace().isEqual(namePart) ) { + namePart.clear(); + XMLUtils::getLocalPart(name, namePart); + xslType = (XSLType*) xslTypes.get(namePart); + } + + if ( !xslType ) { + return XSLType::LITERAL; + } + else return xslType->type; + +} //-- getElementType + +/** + * Gets the Text value of the given DocumentFragment. The value is placed + * into the given destination String. If a non text node element is + * encountered and warningForNonTextNodes is turned on, the MB_FALSE + * will be returned, otherwise true is always returned. + * @param dfrag the document fragment to get the text from + * @param dest the destination string to place the text into. + * @param deep indicates to process non text nodes and recusively append + * their value. If this value is true, the allowOnlyTextNodes flag is ignored. + * @param allowOnlyTextNodes +**/ +MBool XSLTProcessor::getText + (DocumentFragment* dfrag, String& dest, MBool deep, MBool allowOnlyTextNodes) +{ + if ( !dfrag ) return MB_TRUE; + + MBool flag = MB_TRUE; + if ( deep ) XMLDOMUtils::getNodeValue(dfrag, &dest); + else { + NodeList* nl = dfrag->getChildNodes(); + for ( int i = 0; i < nl->getLength(); i++ ) { + Node* node = nl->item(i); + switch(node->getNodeType()) { + case Node::CDATA_SECTION_NODE: + case Node::TEXT_NODE : + dest.append( ((CharacterData*)node)->getData() ); + break; + default: + if (allowOnlyTextNodes) flag = MB_FALSE; + break; + } + } + } + return flag; +} //-- getText + +/** + * 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, Node* context, ProcessorState* ps) { + process(node, context, 0, ps); +} //-- process + +void XSLTProcessor::process(Node* node, Node* context, String* mode, ProcessorState* ps) { + if ( !node ) return; + Element* xslTemplate = ps->findTemplate(node, context, mode); + if (!xslTemplate) return; + processTemplate(node, xslTemplate, ps); +} //-- process + +void XSLTProcessor::processAction + (Node* node, Node* xslAction, ProcessorState* ps) +{ + if (!xslAction) return; + Document* resultDoc = ps->getResultDocument(); + + short nodeType = xslAction->getNodeType(); + + //-- handle text nodes + if (nodeType == Node::TEXT_NODE) { + String textValue; + if ( ps->isXSLStripSpaceAllowed(xslAction) ) { + //-- strip whitespace + //-- Note: we might want to save results of whitespace stripping. + //-- I was thinking about removing whitespace while reading in the + //-- XSL document, but this won't handle the case of Dynamic XSL + //-- documents + const String curValue = ((Text*)xslAction)->getData(); + + //-- set leading + trailing whitespace stripping flags + MBool stripLWS = (MBool) (xslAction->getPreviousSibling()); + MBool stripTWS = (MBool) (xslAction->getNextSibling()); + XMLUtils::stripSpace(curValue,textValue, stripLWS, stripTWS); + //-- create new text node and add it to the result tree + //-- if necessary + } + else { + textValue = ((Text*)xslAction)->getData(); + } + if ( textValue.length() > 0) + ps->addToResultTree(resultDoc->createTextNode(textValue)); + return; + } + //-- handle element nodes + else if (nodeType == Node::ELEMENT_NODE) { + + String nodeName = xslAction->getNodeName(); + PatternExpr* pExpr = 0; + Expr* expr = 0; + + Element* actionElement = (Element*)xslAction; + switch ( getElementType(nodeName, ps) ) { + + //-- xsl:apply-templates + case XSLType::APPLY_TEMPLATES : + { + + String* mode = 0; + Attr* modeAttr = actionElement->getAttributeNode(MODE_ATTR); + if ( modeAttr ) mode = new String(modeAttr->getValue()); + String selectAtt = actionElement->getAttribute(SELECT_ATTR); + if ( selectAtt.length() == 0 ) selectAtt = "* | text()"; + pExpr = ps->getPatternExpr(selectAtt); + ExprResult* exprResult = pExpr->evaluate(node, ps); + NodeSet* nodeSet = 0; + if ( exprResult->getResultType() == ExprResult::NODESET ) { + nodeSet = (NodeSet*)exprResult; + + //-- make sure nodes are in DocumentOrder + ps->sortByDocumentOrder(nodeSet); + + //-- push nodeSet onto context stack + ps->getNodeSetStack()->push(nodeSet); + for (int i = 0; i < nodeSet->size(); i++) { + process(nodeSet->get(i), node, mode, ps); + } + //-- remove nodeSet from context stack + ps->getNodeSetStack()->pop(); + } + else { + notifyError("error processing apply-templates"); + } + //-- clean up + delete mode; + delete exprResult; + break; + } + //-- attribute + case XSLType::ATTRIBUTE: + { + Attr* attr = actionElement->getAttributeNode(NAME_ATTR); + if ( !attr) { + notifyError("missing required name attribute for xsl:attribute"); + } + else { + String ns = actionElement->getAttribute(NAMESPACE_ATTR); + //-- process name as an AttributeValueTemplate + String name; + processAttrValueTemplate(attr->getValue(),name,node,ps); + Attr* newAttr = 0; + //-- check name validity + if ( XMLUtils::isValidQName(name)) { + newAttr = resultDoc->createAttribute(name); + } + else { + String err("error processing xsl:attribute, "); + err.append(name); + err.append(" is not a valid QName."); + notifyError(err); + } + if ( newAttr ) { + DocumentFragment* dfrag = resultDoc->createDocumentFragment(); + ps->getNodeStack()->push(dfrag); + processTemplate(node, actionElement, ps); + ps->getNodeStack()->pop(); + String value; + XMLDOMUtils::getNodeValue(dfrag, &value); + XMLUtils::normalizeAttributeValue(value); + newAttr->setValue(value); + if ( ! ps->addToResultTree(newAttr) ) + delete newAttr; + delete dfrag; + } + } + break; + } + // call-template + case XSLType::CALL_TEMPLATE : + { + String templateName = actionElement->getAttribute(NAME_ATTR); + if ( templateName.length() > 0 ) { + Element* xslTemplate = ps->getNamedTemplate(templateName); + if ( xslTemplate ) { + NamedMap params; + params.setObjectDeletion(MB_TRUE); + Stack* bindings = ps->getVariableSetStack(); + bindings->push(¶ms); + processTemplateParams(xslTemplate, node, ps); + processParameters(actionElement, node, ps); + processTemplate(node, xslTemplate, ps); + bindings->pop(); + } + } + else { + notifyError("missing required name attribute for xsl:call-template"); + } + } + // xsl:if + case XSLType::CHOOSE : + { + NodeList* nl = actionElement->getChildNodes(); + Element* xslTemplate = 0; + for (int i = 0; i < nl->getLength(); i++ ) { + Node* tmp = nl->item(i); + if ( tmp->getNodeType() != Node::ELEMENT_NODE ) continue; + xslTemplate = (Element*)tmp; + DOMString nodeName = xslTemplate->getNodeName(); + switch ( getElementType(nodeName, ps) ) { + case XSLType::WHEN : + { + expr = ps->getExpr(xslTemplate->getAttribute(TEST_ATTR)); + ExprResult* result = expr->evaluate(node, ps); + if ( result->booleanValue() ) { + processTemplate(node, xslTemplate, ps); + return; + } + break; + } + case XSLType::OTHERWISE: + processTemplate(node, xslTemplate, ps); + return; //-- important to break out of everything + default: //-- invalid xsl:choose child + break; + } + } //-- end for-each child of xsl:choose + break; + } + case XSLType::COMMENT: + { + DocumentFragment* dfrag = resultDoc->createDocumentFragment(); + ps->getNodeStack()->push(dfrag); + processTemplate(node, actionElement, ps); + ps->getNodeStack()->pop(); + String value; + if (!getText(dfrag, value, MB_FALSE,MB_TRUE)) { + String warning(NON_TEXT_TEMPLATE_WARNING); + warning.append(COMMENT); + notifyError(warning, ErrorObserver::WARNING); + } + //XMLUtils::normalizePIValue(value); + Comment* comment = resultDoc->createComment(value); + if ( ! ps->addToResultTree(comment) ) delete comment; + delete dfrag; + break; + } + //-- xsl:copy + case XSLType::COPY: + xslCopy(node, actionElement, ps); + break; + //-- xsl:copy-of + case XSLType::COPY_OF: + { + DOMString selectAtt = actionElement->getAttribute(SELECT_ATTR); + Expr* expr = ps->getExpr(selectAtt); + ExprResult* exprResult = expr->evaluate(node, ps); + xslCopyOf(exprResult, ps); + delete exprResult; + break; + + } + case XSLType::ELEMENT: + { + Attr* attr = actionElement->getAttributeNode(NAME_ATTR); + if ( !attr) { + notifyError("missing required name attribute for xsl:element"); + } + else { + String ns = actionElement->getAttribute(NAMESPACE_ATTR); + //-- process name as an AttributeValueTemplate + String name; + processAttrValueTemplate(attr->getValue(),name,node,ps); + Element* element = 0; + //-- check name validity + if ( XMLUtils::isValidQName(name)) { + element = resultDoc->createElement(name); + } + else { + String err("error processing xsl:element, '"); + err.append(name); + err.append("' is not a valid QName."); + notifyError(err); + } + if ( element ) { + ps->addToResultTree(element); + ps->getNodeStack()->push(element); + //-- processAttributeSets + processAttributeSets(actionElement->getAttribute(USE_ATTRIBUTE_SETS_ATTR), + node, ps); + } + //-- process template + processTemplate(node, actionElement, ps); + if( element ) ps->getNodeStack()->pop(); + } + break; + } + //-- xsl:for-each + case XSLType::FOR_EACH : + { + String selectAtt = actionElement->getAttribute(SELECT_ATTR); + + if ( selectAtt.length() == 0 ) selectAtt = "*"; //-- default + + pExpr = ps->getPatternExpr(selectAtt); + + ExprResult* exprResult = pExpr->evaluate(node, ps); + NodeSet* nodeSet = 0; + if ( exprResult->getResultType() == ExprResult::NODESET ) { + nodeSet = (NodeSet*)exprResult; + + //-- push nodeSet onto context stack + ps->getNodeSetStack()->push(nodeSet); + for (int i = 0; i < nodeSet->size(); i++) { + processTemplate(nodeSet->get(i), xslAction, ps); + } + //-- remove nodeSet from context stack + ps->getNodeSetStack()->pop(); + } + else { + notifyError("error processing for-each"); + } + //-- clean up exprResult + delete exprResult; + break; + } + // xsl:if + case XSLType::IF : + { + DOMString selectAtt = actionElement->getAttribute(TEST_ATTR); + expr = ps->getExpr(selectAtt); + //-- check for Error + /* add later when we create ErrResult */ + + ExprResult* exprResult = expr->evaluate(node, ps); + if ( exprResult->booleanValue() ) { + processTemplate(node, actionElement, ps); + } + delete exprResult; + + break; + } + //-- xsl:message + case XSLType::MESSAGE : + { + String message; + + DocumentFragment* dfrag = resultDoc->createDocumentFragment(); + ps->getNodeStack()->push(dfrag); + processTemplate(node, actionElement, ps); + ps->getNodeStack()->pop(); + XMLDOMUtils::getNodeValue(dfrag, &message); + delete dfrag; + + //-- we should add a MessageObserver class + cout << "xsl:message - "<< message << endl; + break; + } + //-- xsl:number + case XSLType::NUMBER : + { + String result; + Numbering::doNumbering(actionElement, result, node, ps); + ps->addToResultTree(resultDoc->createTextNode(result)); + break; + } + //-- xsl:param + case XSLType::PARAM: + //-- ignore in this loop already processed + break; + //-- xsl:processing-instruction + case XSLType::PI: + { + Attr* attr = actionElement->getAttributeNode(NAME_ATTR); + if ( !attr) { + String err("missing required name attribute for xsl:"); + err.append(PI); + notifyError(err); + } + else { + String ns = actionElement->getAttribute(NAMESPACE_ATTR); + //-- process name as an AttributeValueTemplate + String name; + processAttrValueTemplate(attr->getValue(),name,node,ps); + //-- check name validity + if ( !XMLUtils::isValidQName(name)) { + String err("error processing xsl:"); + err.append(PI); + err.append(", '"); + err.append(name); + err.append("' is not a valid QName."); + notifyError(err); + } + DocumentFragment* dfrag = resultDoc->createDocumentFragment(); + ps->getNodeStack()->push(dfrag); + processTemplate(node, actionElement, ps); + ps->getNodeStack()->pop(); + String value; + if (!getText(dfrag, value, MB_FALSE,MB_TRUE)) { + String warning(NON_TEXT_TEMPLATE_WARNING); + warning.append(PI); + notifyError(warning, ErrorObserver::WARNING); + } + XMLUtils::normalizePIValue(value); + ProcessingInstruction* pi + = resultDoc->createProcessingInstruction(name, value); + if ( ! ps->addToResultTree(pi) ) delete pi; + delete dfrag; + } + break; + } + //-- xsl:text + case XSLType::TEXT : + { + String data; + //-- get Node value, and do not perform whitespace stripping + XMLDOMUtils::getNodeValue(actionElement, &data); + Text* text = resultDoc->createTextNode(data); + ps->addToResultTree(text); + break; + } + case XSLType::EXPR_DEBUG: //-- proprietary debug element + { + DOMString exprAtt = actionElement->getAttribute(EXPR_ATTR); + Expr* expr = ps->getExpr(exprAtt); + ExprResult* exprResult = expr->evaluate(node, ps); + String data("expr debug: "); + expr->toString(data); + cout << data << endl; + data.clear(); + cout << "result: "; + if ( exprResult ) { + switch ( exprResult->getResultType() ) { + case ExprResult::NODESET: + cout << "#NodeSet - "; + default: + exprResult->stringValue(data); + cout << data; + break; + } + } + cout << endl; + + delete exprResult; + break; + } + //-- xsl:value-of + case XSLType::VALUE_OF : + { + DOMString selectAtt = actionElement->getAttribute(SELECT_ATTR); + + Expr* expr = ps->getExpr(selectAtt); + ExprResult* exprResult = expr->evaluate(node, ps); + String value; + if ( !exprResult ) { + notifyError("null ExprResult"); + break; + } + exprResult->stringValue(value); + //-- handle whitespace stripping + if ( exprResult->getResultType() == ExprResult::NODESET) { + NodeSet* nodes = (NodeSet*)exprResult; + if ( nodes->size() > 0) { + Node* node = nodes->get(0); + if ( ps->isStripSpaceAllowed(node) ) { + const String temp = value; + value.clear(); + XMLUtils::stripSpace(temp, value); + } + } + } + ps->addToResultTree(resultDoc->createTextNode(value)); + delete exprResult; + break; + } + case XSLType::VARIABLE : + { + String name = actionElement->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + notifyError("missing required name attribute for xsl:variable"); + break; + } + ExprResult* exprResult = processVariable(node, actionElement, ps); + bindVariable(name, exprResult, MB_FALSE, ps); + break; + } + //-- literal + default: + Element* element = resultDoc->createElement(nodeName); + ps->addToResultTree(element); + ps->getNodeStack()->push(element); + //-- handle attributes + NamedNodeMap* atts = actionElement->getAttributes(); + if ( atts ) { + String xsltNameSpace = ps->getXSLNamespace(); + NodeSet nonXSLAtts(atts->getLength()); + //-- process special XSL attributes first + int i; + for (i = 0; i < atts->getLength(); i++ ) { + Attr* attr = (Attr*) atts->item(i); + //-- filter attributes in the XSLT namespace + String attrNameSpace; + XMLUtils::getNameSpace(attr->getName(), attrNameSpace); + if ( attrNameSpace.isEqual(xsltNameSpace) ) { + //-- check for useAttributeSet + String localPart; + XMLUtils::getLocalPart(attr->getName(), localPart); + if ( USE_ATTRIBUTE_SETS_ATTR.isEqual(localPart) ) { + processAttributeSets(attr->getValue(), node, ps); + } + continue; + } + else nonXSLAtts.add(attr); + } + //-- process all non XSL attributes + for ( i = 0; i < nonXSLAtts.size(); i++ ) { + Attr* attr = (Attr*) nonXSLAtts.get(i); + Attr* newAttr = resultDoc->createAttribute(attr->getName()); + //-- process Attribute Value Templates + String value; + processAttrValueTemplate(attr->getValue(), value, node, ps); + newAttr->setValue(value); + ps->addToResultTree(newAttr); + } + } + //-- process children + NodeList* nl = xslAction->getChildNodes(); + int i; + for ( i = 0; i < nl->getLength(); i++) { + processAction(node, nl->item(i),ps); + } + ps->getNodeStack()->pop(); + break; + } + } + + //cout << "XSLTProcessor#processAction [exit]\n"; +} //-- processAction + +/** + * Processes the attribute sets specified in the names argument +**/ +void XSLTProcessor::processAttributeSets + (const String& names, Node* node, ProcessorState* ps) +{ + //-- split names + Tokenizer tokenizer(names); + String name; + while ( tokenizer.hasMoreTokens() ) { + tokenizer.nextToken(name); + NodeSet* attSet = ps->getAttributeSet(name); + if ( attSet ) { + for ( int i = 0; i < attSet->size(); i++) { + processAction(node, attSet->get(i), ps); + } + } + } +} //-- processAttributeSets + +/** + * Processes the given attribute value as an AttributeValueTemplate + * @param attValue the attribute value to process + * @param result, the String in which to store the result + * @param context the current context node + * @param ps the current ProcessorState +**/ +void XSLTProcessor::processAttrValueTemplate + (const String& attValue, String& result, Node* context, ProcessorState* ps) +{ + AttributeValueTemplate* avt = 0; + avt = exprParser.createAttributeValueTemplate(attValue); + ExprResult* exprResult = avt->evaluate(context,ps); + exprResult->stringValue(result); + delete exprResult; + delete avt; + +} //-- processAttributeValueTemplate + +/** + * Processes the xsl:with-param elements of the given xsl action + * Only processes xsl:with-params that have a corresponding + * xsl:param already in the current VariableSet +**/ +void XSLTProcessor::processParameters(Element* xslAction, Node* context, ProcessorState* ps) +{ + if ( !xslAction ) return; + + //-- handle xsl:with-param elements + NodeList* nl = xslAction->getChildNodes(); + Stack* bindings = ps->getVariableSetStack(); + NamedMap* current = (NamedMap*)bindings->peek(); + for (int i = 0; i < nl->getLength(); i++) { + Node* tmpNode = nl->item(i); + int nodeType = tmpNode->getNodeType(); + if ( nodeType == Node::ELEMENT_NODE ) { + Element* action = (Element*)tmpNode; + String actionName = action->getNodeName(); + short xslType = getElementType(actionName, ps); + if ( xslType == XSLType::WITH_PARAM ) { + String name = action->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + notifyError("missing required name attribute for xsl:with-param"); + } + else { + if ( current->get(name) ) { + ExprResult* exprResult = processVariable(context, action, ps); + bindVariable(name, exprResult, MB_FALSE, ps); + } + } + } + } + } +} //-- processParameters + +/** + * Processes the set of nodes using the given context, and ProcessorState +**/ +void XSLTProcessor::processTemplate(Node* node, Node* xslTemplate, ProcessorState* ps) { + + if ( !xslTemplate ) { + //-- do default? + } + else { + Stack* bindings = ps->getVariableSetStack(); + NamedMap localBindings; + localBindings.setObjectDeletion(MB_TRUE); + bindings->push(&localBindings); + NodeList* nl = xslTemplate->getChildNodes(); + for (int i = 0; i < nl->getLength(); i++) + processAction(node, nl->item(i), ps); + bindings->pop(); + } +} //-- processTemplate + +/** + * Processes the set of nodes using the given context, and ProcessorState +**/ +void XSLTProcessor::processTemplateParams + (Node* xslTemplate, Node* context, ProcessorState* ps) { + + if ( xslTemplate ) { + NodeList* nl = xslTemplate->getChildNodes(); + int i = 0; + //-- handle params + for (i = 0; i < nl->getLength(); i++) { + Node* tmpNode = nl->item(i); + int nodeType = tmpNode->getNodeType(); + if ( nodeType == Node::ELEMENT_NODE ) { + Element* action = (Element*)tmpNode; + String actionName = action->getNodeName(); + short xslType = getElementType(actionName, ps); + if ( xslType == XSLType::PARAM ) { + String name = action->getAttribute(NAME_ATTR); + if ( name.length() == 0 ) { + notifyError("missing required name attribute for xsl:param"); + } + else { + ExprResult* exprResult = processVariable(context, action, ps); + bindVariable(name, exprResult, MB_TRUE, ps); + } + } + else break; + } + else if (nodeType == Node::TEXT_NODE) { + if (!XMLUtils::isWhitespace(((Text*)tmpNode)->getData())) break; + } + else break; + } + } +} //-- processTemplateParams + + +/** + * processes the xslVariable parameter as an xsl:variable using the given context, + * and ProcessorState. + * If the xslTemplate contains an "expr" attribute, the attribute is evaluated + * as an Expression and the ExprResult is returned. Otherwise the xslVariable is + * is processed as a template, and it's result is converted into an ExprResult + * @return an ExprResult +**/ +ExprResult* XSLTProcessor::processVariable + (Node* node, Element* xslVariable, ProcessorState* ps) +{ + + if ( !xslVariable ) { + return new StringResult("unable to process variable"); + } + + //-- check for select attribute + Attr* attr = xslVariable->getAttributeNode(SELECT_ATTR); + if ( attr ) { + Expr* expr = ps->getExpr(attr->getValue()); + return expr->evaluate(node, ps); + } + else { + NodeList* nl = xslVariable->getChildNodes(); + Document* resultTree = ps->getResultDocument(); + NodeStack* nodeStack = ps->getNodeStack(); + nodeStack->push(resultTree->createDocumentFragment()); + for (int i = 0; i < nl->getLength(); i++) { + processAction(node, nl->item(i), ps); + } + Node* node = nodeStack->pop(); + //-- add clean up for This new NodeSet; + NodeSet* nodeSet = new NodeSet(); + nodeSet->add(node); + return nodeSet; + } +} //-- processVariable + +/** + * Performs the xsl:copy action as specified in the XSL Working Draft +**/ +void XSLTProcessor::xslCopy(Node* node, Element* action, ProcessorState* ps) { + if ( !node ) return; + + Document* resultDoc = ps->getResultDocument(); + Node* copy = 0; + switch ( node->getNodeType() ) { + case Node::DOCUMENT_NODE: + //-- just process children + processTemplate(node, action, ps); + break; + case Node::ELEMENT_NODE: + { + Element* element = (Element*)node; + String nodeName = element->getNodeName(); + copy = resultDoc->createElement(nodeName); + ps->addToResultTree(copy); + ps->getNodeStack()->push(copy); + //-- copy namespace attributes + // * add later * + processTemplate(node, action, ps); + ps->getNodeStack()->pop(); + return; + } + //-- just copy node, xsl:copy template does not get processed + default: + copy = XMLDOMUtils::copyNode(node, resultDoc); + break; + } + if ( copy ) ps->addToResultTree(copy); +} //-- xslCopy + +/** + * Performs the xsl:copy-of action as specified in the XSL Working Draft +**/ +void XSLTProcessor::xslCopyOf(ExprResult* exprResult, ProcessorState* ps) { + + if ( !exprResult ) return; + + Document* resultDoc = ps->getResultDocument(); + + switch ( exprResult->getResultType() ) { + case ExprResult::NODESET: + { + NodeSet* nodes = (NodeSet*)exprResult; + for (int i = 0; i < nodes->size();i++) { + Node* node = nodes->get(i); + ps->addToResultTree(XMLDOMUtils::copyNode(node, resultDoc)); + } + break; + } + default: + { + String value; + exprResult->stringValue(value); + ps->addToResultTree(resultDoc->createTextNode(value)); + break; + } + + } +} //-- xslCopyOf + +#ifdef MOZILLA +NS_IMETHODIMP +XSLTProcessor::TransformDocument(nsIDOMElement* aSourceDOM, + nsIDOMElement* aStyleDOM, + nsIDOMDocument* aOutputDoc, + nsIObserver* aObserver) +{ + return NS_OK; +} +#endif + +XSLType::XSLType() { + this->type = LITERAL; +} //-- XSLType + +XSLType::XSLType(const XSLType& xslType) { + this->type = xslType.type; +} //-- XSLType + +XSLType::XSLType(short type) { + this->type = type; +} //-- XSLType + + + diff --git a/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h new file mode 100644 index 00000000000..ec6517b8d98 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/XSLTProcessor.h @@ -0,0 +1,416 @@ +/* + * 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. + * + * $Id: XSLTProcessor.h,v 1.1 2000-04-06 07:47:07 kvisco%ziplink.net Exp $ + */ + + +#ifndef TRANSFRMX_XSLTPROCESSOR_H +#define TRANSFRMX_XSLTPROCESSOR_H + +#ifndef __BORLANDC__ +#ifndef MOZILLA +#include +#include +#endif +#endif + + +#ifdef MOZILLA +#include "nsIDocumentTransformer.h" +#else +#include "CommandLineUtils.h" +#include "printers.h" +#include "URIUtils.h" +#include "XMLParser.h" +#include "XMLDOMUtils.h" +#endif + +#include "dom.h" +#include "ExprParser.h" +#include "MITREObject.h" +#include "NamedMap.h" +#include "Names.h" +#include "NodeSet.h" +#include "ProcessorState.h" +#include "String.h" +#include "Tokenizer.h" +#include "ErrorObserver.h" +#include "List.h" +#include "VariableBinding.h" +#include "Numbering.h" + + +#ifdef MOZILLA +/* bacd8ad0-552f-11d3-a9f7-000064657374 */ +#define MITRE_XSL_PROCESSOR_CID \ +{ 0xbacd8ad0, 0x552f, 0x11d3, {0xa9, 0xf7, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} } + +#endif + + +/** + * A class for Processing XSL Stylesheets + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:47:07 $ +**/ +class XSLTProcessor +#ifdef MOZILLA +: nsIDocumentTransformer +#endif +{ + +public: +#ifdef MOZILLA + // Define a Create method to be used with a factory: + static NS_METHOD + Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult); + + /** + * This macro expands into a declaration of the nsISupports interface. + * Every XPCOM component needs to implement nsISupports, as it acts + * as the gateway to other interfaces this component implements. You + * could manually declare QueryInterface, AddRef, and Release instead + * of using this macro, but why? + */ + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIDocumentTransformer methods + NS_IMETHOD TransformDocument(nsIDOMElement* aSourceDOM, + nsIDOMElement* aStyleDOM, + nsIDOMDocument* aOutputDoc, + nsIObserver* aObserver); +#endif + + /** + * A warning message used by all templates that do not allow non character + * data to be generated + **/ + static const String NON_TEXT_TEMPLATE_WARNING; + + /** + * Creates a new XSLTProcessor + **/ + XSLTProcessor(); + + /** + * Default destructor for XSLTProcessor + **/ + virtual ~XSLTProcessor(); + + /** + * Registers the given ErrorObserver with this XSLTProcessor + **/ + void addErrorObserver(ErrorObserver& errorObserver); + + /** + * Returns the name of this XSLT processor + **/ + String& getAppName(); + + /** + * Returns the version of this XSLT processor + **/ + String& getAppVersion(); + + //--------------------------------------------/ + //-- Methods that return the Result Document -/ + //--------------------------------------------/ +#ifndef MOZILLA + /** + * Parses all XML Stylesheet PIs associated with the + * given XML document. If any stylesheet PIs are found with + * type="text/xsl" the href psuedo attribute value will be + * added to the given href argument. If multiple text/xsl stylesheet PIs + * are found, the one closest to the end of the document is used. + **/ + void getHrefFromStylesheetPI(Document& xmlDocument, String& href); + + /** + * Processes the given XML Document, the XSL stylesheet + * will be retrieved from the XML Stylesheet Processing instruction, + * otherwise an empty document will be returned. + * @param xmlDocument the XML document to process + * @param documentBase the document base of the XML document, for + * resolving relative URIs + * @return the result tree. + **/ + Document* process(Document& xmlDocument, String& documentBase); + +#endif + + /** + * Processes the given XML Document using the given XSL document + * @return the result tree. + * @param documentBase the document base for resolving relative URIs. + **/ + Document* process + (Document& xmlDocument, Document& xslDocument, String& documentBase); + + /** + * Reads an XML Document from the given XML input stream, and + * processes the document using the XSL document derived from + * the given XSL input stream. + * @param documentBase the document base for resolving relative URIs. + * @return the result tree. + **/ + Document* process(istream& xmlInput, istream& xslInput, + String& documentBase); + +#ifndef MOZILLA + /** + * Reads an XML document from the given XML input stream. The + * XML document is processed using the associated XSL document + * retrieved from the XML document's Stylesheet Processing Instruction, + * otherwise an empty document will be returned. + * @param xmlDocument the XML document to process + * @param documentBase the document base of the XML document, for + * resolving relative URIs + * @return the result tree. + **/ + Document* process(istream& xmlInput, String& documentBase); + + //----------------------------------------------/ + //-- Methods that print the result to a stream -/ + //----------------------------------------------/ + + /** + * Reads an XML Document from the given XML input stream. + * The XSL Stylesheet is obtained from the XML Documents stylesheet PI. + * If no Stylesheet is found, an empty document will be the result; + * otherwise the XML Document is processed using the stylesheet. + * The result tree is printed to the given ostream argument, + * will not close the ostream argument + **/ + void process(istream& xmlInput, ostream& out, String& documentBase); + + /** + * Processes the given XML Document using the given XSL document. + * The result tree is printed to the given ostream argument, + * will not close the ostream argument + * @param documentBase the document base for resolving relative URIs. + **/ + void process + (Document& xmlDocument, Document& xslDocument, + ostream& out, String& documentBase); + + /** + * Reads an XML Document from the given XML input stream, and + * processes the document using the XSL document derived from + * the given XSL input stream. + * The result tree is printed to the given ostream argument, + * will not close the ostream argument + * @param documentBase the document base for resolving relative URIs. + **/ + void process(istream& xmlInput, istream& xslInput, + ostream& out, String& documentBase); + +#endif + +private: + + + /** + * Application Name and version + **/ + String appName; + String appVersion; + + /** + * The list of ErrorObservers + **/ + List errorObservers; + + /** + * Fatal ErrorObserver + **/ + SimpleErrorObserver fatalObserver; + + /** + * An expression parser for creating AttributeValueTemplates + **/ + ExprParser exprParser; + + /** + * The version of XSL which this Processes + **/ + String xslVersion; + + /** + * Named Map for quick reference to XSL Types + **/ + NamedMap xslTypes; + + /** + * Binds the given Variable + **/ + void bindVariable(String& name, + ExprResult* value, + MBool allowShadowing, + ProcessorState* ps); + +#ifndef MOZILLA + + /** + * Prints the given XML document to the given ostream and uses + * the properties specified in the OutputFormat. + * This method is used to print the result tree + * @param document the XML document to print + * @param format the OutputFormat specifying formatting info + * @param ostream the Stream to print to + **/ + void print(Document& document, OutputFormat* format, ostream& out); +#endif + + + /** + * Processes the xsl:with-param elements of the given xsl action + **/ + void processParameters(Element* xslAction, Node* context, ProcessorState* ps); + + /** + * Looks up the given XSLType with the given name + * The ProcessorState is used to get the current XSLT namespace + **/ + short getElementType(String& name, ProcessorState* ps); + + + /** + * Gets the Text value of the given DocumentFragment. The value is placed + * into the given destination String. If a non text node element is + * encountered and warningForNonTextNodes is turned on, the MB_FALSE + * will be returned, otherwise true is always returned. + * @param dfrag the document fragment to get the text from + * @param dest the destination string to place the text into. + * @param deep indicates to process non text nodes and recusively append + * their value. If this value is true, the allowOnlyTextNodes flag is ignored. + **/ + MBool getText + (DocumentFragment* dfrag, String& dest, MBool deep, MBool allowOnlyTextNodes); + + /** + * 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); + +#ifndef MOZILLA + /** + * Parses the contents of data, and returns the type and href psuedo attributes + **/ + void parseStylesheetPI(String& data, String& type, String& href); +#endif + + void process(Node* node, Node* context, ProcessorState* ps); + void process(Node* node, Node* context, String* mode, ProcessorState* ps); + + void processAction(Node* node, Node* xslAction, ProcessorState* ps); + + /** + * Processes the attribute sets specified in the names argument + **/ + void processAttributeSets(const String& names, Node* node, ProcessorState* ps); + + /** + * Processes the given attribute value as an AttributeValueTemplate + * @param attValue the attribute value to process + * @param result, the String in which to store the result + * @param context the current context node + * @param ps the current ProcessorState + **/ + void processAttrValueTemplate + (const String& attValue, String& result, Node* context, ProcessorState* ps); + + void processTemplate(Node* node, Node* xslTemplate, ProcessorState* ps); + void processTemplateParams(Node* xslTemplate, Node* context, ProcessorState* ps); + + void processTopLevel(Document* xslDocument, ProcessorState* ps); + + ExprResult* processVariable(Node* node, Element* xslVariable, ProcessorState* ps); + + /** + * Performs the xsl:copy action as specified in the XSL Working Draft + **/ + void xslCopy(Node* node, Element* action, ProcessorState* ps); + + /** + * Performs the xsl:copy-of action as specified in the XSLT Working Draft + **/ + void xslCopyOf(ExprResult* exprResult, ProcessorState* ps); + +}; //-- XSLTProcessor + +class XSLType : public MITREObject { + +public: + enum _XSLType { + APPLY_IMPORTS = 1, + APPLY_TEMPLATES, + ATTRIBUTE, + ATTRIBUTE_SET, + CALL_TEMPLATE, + CHOOSE, + COMMENT, + COPY, + COPY_OF, + ELEMENT, + IF, + INCLUDE, + FOR_EACH, + LITERAL, + NUMBER, + OTHERWISE, + OUTPUT, + PARAM, + PI, + PRESERVE_SPACE, + STRIP_SPACE, + TEMPLATE, + TEXT, + VALUE_OF, + VARIABLE, + WHEN, + WITH_PARAM, + MESSAGE, + EXPR_DEBUG, // temporary, used for debugging + }; + + XSLType(const XSLType& xslType); + XSLType(); + XSLType(short type); + short type; +}; + +#endif + + diff --git a/mozilla/extensions/transformiix/source/xslt/makefile.win b/mozilla/extensions/transformiix/source/xslt/makefile.win new file mode 100644 index 00000000000..56afc55c9b2 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/makefile.win @@ -0,0 +1,62 @@ +#!nmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH=..\..\..\..\.. + +DIRS=util + +LIBRARY_NAME=transformix_xsl +MODULE=transformix +REQUIRES=xpcom raptor + +DEFINES=-DMOZILLA + +CPPSRCS= \ + XSLProcessor.cpp \ + ProcessorState.cpp \ + Names.cpp \ + $(NULL) + +CPP_OBJS= \ + .\$(OBJDIR)\XSLProcessor.obj \ + .\$(OBJDIR)\ProcessorState.obj \ + .\$(OBJDIR)\Names.obj \ + $(NULL) + +EXPORTS = \ + XSLProcessor.h \ + $(NULL) + +LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I.\expr -I.\util -I..\xml\dom \ + -I..\base -I ..\xml + +LCFLAGS = \ + $(LCFLAGS) \ + $(DEFINES) \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(LIBRARY) + $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib + +clobber:: + rm -f $(DIST)\lib\$(LIBRARY_NAME).lib diff --git a/mozilla/extensions/transformiix/source/xslt/util/Makefile b/mozilla/extensions/transformiix/source/xslt/util/Makefile new file mode 100644 index 00000000000..cb720128aa7 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/util/Makefile @@ -0,0 +1,10 @@ + +ALL_OBJS = NodeStack.o + + +INCLUDE_PATH = -I../../base -I../..expr -I../../xml -I../../xml/dom + +target: $(ALL_OBJS) + +NodeStack.o: NodeStack.h NodeStack.cpp + $(CC) $(INCLUDE_PATH) -c NodeStack.cpp diff --git a/mozilla/extensions/transformiix/source/xslt/util/NodeStack.cpp b/mozilla/extensions/transformiix/source/xslt/util/NodeStack.cpp new file mode 100644 index 00000000000..72c275d8634 --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/util/NodeStack.cpp @@ -0,0 +1,271 @@ +/* + * 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. + * + * Larry Fitzpatrick, OpenText, lef@opentext.com + * -- moved initialization of DEFAULT_SIZE from NodeStack.h to here + * + * $Id: NodeStack.cpp,v 1.1 2000-04-06 07:47:41 kvisco%ziplink.net Exp $ + */ + +#include "NodeStack.h" +#include + +/** + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:47:41 $ +**/ + + + //-------------/ + //- Constants -/ +//-------------/ +const int NodeStack::DEFAULT_SIZE = 25; + + //----------------/ + //- Constructors -/ +//----------------/ + +/** + * Creates a new NodeStack with the default Size +**/ +NodeStack::NodeStack() { + initialize(DEFAULT_SIZE); +} //-- NodeStack + +/** + * Creates a new NodeStack with the specified size +**/ +NodeStack::NodeStack(int size) { + initialize(size); +} //-- NodeStack + +/** + * Helper method for Constructors +**/ +void NodeStack::initialize(int size) { + elements = new Node*[size]; + elementCount = 0; + bufferSize = size; + initialSize = size; +} //-- initialize + +/** + * Destructor for NodeSet +**/ +NodeStack::~NodeStack() { + delete [] elements; +} //-- ~NodeStack + +/** + * Returns the specified Node from the top of this Stack, + * without removing it from the stack. + * @param node the Node to add to the top of the Stack + * @return a pointer to the Node that is the top of this Stack +**/ +Node* NodeStack::peek() { + return get(size()-1); +} //-- peek + +/** + * Removes the specified Node from the top of this Stack. + * @param node the Node to add to the top of the Stack + * @return a pointer to the Node that was the top of this Stack +**/ +Node* NodeStack::pop() { + return remove(size()-1); +} //-- pop + +/** + * Adds the specified Node to the top of this Stack. + * @param node the Node to add to the top of the Stack +**/ +void NodeStack::push(Node* node) { + if (elementCount == bufferSize) increaseSize(); + elements[elementCount++] = node; +} //-- push + + +/** + * Removes all elements from the Stack +**/ +void NodeStack::clear() { + for (int i = 0; i < elementCount; i++) { + elements[i] = 0; + } + elementCount = 0; +} //-- clear + +/** + * Returns true if the specified Node is contained in the Stack. + * if the specfied Node is null, then if the NodeStack contains a null + * value, true will be returned. + * @param node the element to search the NodeStack for + * @return true if specified Node is contained in the NodeStack +**/ +MBool NodeStack::contains(Node* node) { + cout << "NodeStack#contains [enter]\n"; + MBool retVal = (indexOf(node) >= 0) ? MB_TRUE : MB_FALSE; + cout << "NodeStack#contains [exit]\n"; + return retVal; + +} //-- contains + +/** + * Compares the specified NodeStack with this NodeStack for equality. + * Returns true if and only if the specified NodeStack is the same + * size as this NodeSet and all of its associated + * Nodes are contained within this NodeStack in the same order. + * @return true if and only if the specified NodeStack is the + * same size as this NodeStack and all of its associated + * Nodes are contained within this NodeStack in the same order. +**/ +MBool NodeStack::equals(NodeStack* nodeStack) { + if (!nodeStack) return MB_FALSE; + if (nodeStack->size() != size()) return MB_FALSE; + + for (int i = 0; i < size(); i++) { + if (nodeStack->get(i) != get(i)) return MB_FALSE; + } + return MB_TRUE; +} //-- equals + +/** + * Returns the Node at the specified position in this NodeStack. + * @param index the position of the Node to return +**/ +Node* NodeStack::get(int index) { + if ((index < 0) || index >= elementCount) return 0; + return elements[index]; +} //-- get + + +/** + * Returns the index of the specified Node, + * or -1 if the Node is not contained in the NodeStack + * @param node the Node to get the index for +**/ +int NodeStack::indexOf(Node* node) { + + for (int i = 0; i < elementCount; i++) { + if (node == elements[i]) { + return i; + } + } + return -1; +} //-- indexOf + +/** + * Returns true if there are no Nodes in the NodeStack. + * @return true if there are no Nodes in the NodeStack. +**/ +MBool NodeStack::isEmpty() { + return (elementCount == 0) ? MB_TRUE : MB_FALSE; +} //-- isEmpty + +/** + * Removes the Node at the specified index from the NodeStack + * @param index the position in the NodeStack to remove the Node from + * @return the Node that was removed from the NodeStack +**/ +Node* NodeStack::remove(int index) { + + if ((index < 0) || (index > elementCount)) return 0; + Node* node = elements[index]; + shiftDown(index+1); + --elementCount; + return node; +} //-- remove + +/** + * Removes the the specified Node from the NodeStack + * @param node the Node to remove from the NodeStack + * @return true if the Node was removed from the list +**/ +MBool NodeStack::remove(Node* node) { + int index = indexOf(node); + + if (index > -1) { + remove(index); + } + else return MB_FALSE; + + return MB_TRUE; +} //-- remove + + +/** + * Returns the number of elements in the NodeStack + * @return the number of elements in the NodeStack +**/ +int NodeStack::size() { + return elementCount; +} //-- size + + //-------------------/ + //- Private Methods -/ +//-------------------/ + +/** + * increase the NodeStack capacity by a factor of its initial size +**/ +void NodeStack::increaseSize() { + + bufferSize += bufferSize; + Node** tmpNodes = elements; + elements = new Node*[bufferSize]; + for (int i=0;i < elementCount; i++) { + elements[i] = tmpNodes[i]; + } + delete [] tmpNodes; + +} //-- increaseSize + +/** + * Shifts all elements at the specified index to down by 1 +**/ +void NodeStack::shiftDown(int index) { + if ((index <= 0) || (index >= elementCount)) return; + + //-- from Java + //-- System.arraycopy(elements, index, elements, index - 1, elementCount - index); + for (int i = index; i < elementCount; i++) { + elements[index-1] = elements[index]; + } + + elements[elementCount-1] = 0; +} //-- shiftDown + +/** + * Shifts all elements at the specified index up by 1 +**/ +void NodeStack::shiftUp(int index) { + if (index == elementCount) return; + if (elementCount == bufferSize) increaseSize(); + + //-- from Java + //-- System.arraycopy(elements, index, elements, index + 1, elementCount - index); + for (int i = elementCount; i > index; i--) { + elements[i] = elements[i-1]; + } +} //-- shiftUp + diff --git a/mozilla/extensions/transformiix/source/xslt/util/NodeStack.h b/mozilla/extensions/transformiix/source/xslt/util/NodeStack.h new file mode 100644 index 00000000000..b3462b95f5e --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/util/NodeStack.h @@ -0,0 +1,198 @@ +/* + * 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. + * + * Larry Fitzpatrick, OpenText, lef@opentext.com + * -- moved initialization of DEFAULT_SIZE to NodeStack.cpp + * $Id: NodeStack.h,v 1.1 2000-04-06 07:47:42 kvisco%ziplink.net Exp $ + */ + + +/** + * NodeStack + * @author Keith Visco + * @version $Revision: 1.1 $ $Date: 2000-04-06 07:47:42 $ +**/ +#include "dom.h" +#include "baseutils.h" + +#ifndef NODESTACK_H +#define NODESTACK_H + +class NodeStack { + + +public: + + //----------------/ + //- Constructors -/ + //----------------/ + + /** + * Creates a new NodeStack with the default Size + **/ + NodeStack(); + + /** + * Creates a new NodeStack with the specified Size + **/ + NodeStack(int size); + + /** + * Destructor for NodeStack, will not delete Node References + **/ + ~NodeStack(); + + /** + * Returns the specified Node from the top of this Stack, + * without removing it from the stack. + * @param node the Node to add to the top of the Stack + * @return a pointer to the Node that is the top of this Stack + **/ + Node* peek(); + void push(Node* node); + Node* pop(); + + /** + * Adds the specified Node to the NodeSet at the specified index, + * as long as the Node is not already contained within the set + * @param node the Node to add to the NodeSet + * @return true if the Node is added to the NodeSet + * @exception IndexOutOfBoundsException + **/ + MBool add(int index, Node* node); + + /** + * Removes all elements from the list + **/ + void clear(); + + /** + * Returns true if the specified Node is contained in the set. + * if the specfied Node is null, then if the NodeSet contains a null + * value, true will be returned. + * @param node the element to search the NodeSet for + * @return true if specified Node is contained in the NodeSet + **/ + MBool contains(Node* node); + + /** + * Compares the specified object with this NodeSet for equality. + * Returns true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. + * @return true if and only if the specified Object is a NodeSet + * that is the same size as this NodeSet and all of its associated + * Nodes are contained within this NodeSet. + **/ + MBool equals(NodeStack* nodeStack); + + /** + * Returns the Node at the specified position in this NodeSet. + * @param index the position of the Node to return + * @exception IndexOutOfBoundsException + **/ + Node* get(int index); + + + /** + * Returns the index of the specified Node, + * or -1 if the Node is not contained in the NodeSet + * @param node the Node to get the index for + **/ + int indexOf(Node* node); + + /** + * Returns true if there are no Nodes in the NodeSet. + * @return true if there are no Nodes in the NodeSet. + **/ + MBool isEmpty(); + + /** + * Removes the Node at the specified index from the NodeSet + * @param index the position in the NodeSet to remove the Node from + * @return the Node that was removed from the list + **/ + Node* remove(int index); + + /** + * Removes the the specified Node from the NodeSet + * @param node the Node to remove from the NodeSet + * @return true if the Node was removed from the list + **/ + MBool remove(Node* node); + + + /** + * Returns the number of elements in the NodeSet + * @return the number of elements in the NodeSet + **/ + int size(); + +private: + + + //-------------------/ + //- Private Members -/ + //-------------------/ + + static const int DEFAULT_SIZE; + + Node** elements; + + int initialSize; + int bufferSize; + + /** + * The next available location in the elements array + **/ + int elementCount; + + //-------------------/ + //- Private Methods -/ + //-------------------/ + + /** + * Helper method for constructors + **/ + void initialize(int size); + + /** + * increase the NodeSet capacity by a factor of its initial size + **/ + void increaseSize(); + + /** + * Shifts all elements at the specified index to down by 1 + **/ + void shiftDown(int index); + + /** + * Shifts all elements at the specified index up by 1 + **/ + void shiftUp(int index); + +}; //-- NodeSet + +#endif + diff --git a/mozilla/extensions/transformiix/source/xslt/util/makefile.win b/mozilla/extensions/transformiix/source/xslt/util/makefile.win new file mode 100644 index 00000000000..f0bf63683fc --- /dev/null +++ b/mozilla/extensions/transformiix/source/xslt/util/makefile.win @@ -0,0 +1,53 @@ +#!nmake +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH=..\..\..\..\..\.. + +LIBRARY_NAME=transformix_xslt_util +MODULE=transformix +REQUIRES=xpcom raptor + +CPPSRCS= \ + NodeStack.cpp \ + $(NULL) + +CPP_OBJS= \ + .\$(OBJDIR)\NodeStack.obj \ + $(NULL) + +EXPORTS = \ + $(NULL) + +LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I..\..\base -I..\..\xml\dom \ + -I..\expr -I..\..\xml + +LCFLAGS = \ + $(LCFLAGS) \ + $(DEFINES) \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(LIBRARY) + $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib + +clobber:: + rm -f $(DIST)\lib\$(LIBRARY_NAME).lib