sicking%bigfoot.com d8d0cac658 Landing XSLT branch. Tracking bug is 155578, fixes bugs 46633, 54659, 73492, 70369, 85408, 90157, 130161, 109918, 150916 and 170097
* New scriptable interfaces to XSLT
* Make HTML-output create real html
* cleanup the XSLTProcessor class

Patch by sicking, pike and peterv

r=sicking/pike, sr=peterv, a=asa


git-svn-id: svn://10.0.0.236/trunk@132337 18797224-902f-48f8-a5cc-f745e15eee43
2002-10-21 21:35:23 +00:00

534 lines
14 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is TransforMiiX XSLT processor.
*
* The Initial Developer of the Original Code is The MITRE Corporation.
* Portions created by MITRE are Copyright (C) 1999 The MITRE Corporation.
*
* Portions created by Keith Visco as a Non MITRE employee,
* (C) 1999 Keith Visco. All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
*/
#ifndef TRANSFRMX_PROCESSORSTATE_H
#define TRANSFRMX_PROCESSORSTATE_H
#include "NodeSet.h"
#include "Stack.h"
#include "ErrorObserver.h"
#include "NamedMap.h"
#include "txPatternParser.h"
#include "Expr.h"
#include "StringList.h"
#include "txOutputFormat.h"
#include "Map.h"
#include "txIXPathContext.h"
#include "txExpandedNameMap.h"
#include "txXMLEventHandler.h"
#include "XSLTFunctions.h"
#include "txError.h"
class txVariableMap;
class txXSLKey;
/**
* Class used for keeping the current state of the XSL Processor
*/
class ProcessorState : public txIMatchContext {
public:
/**
* Creates a new ProcessorState for the given XSL document
* And result Document
*/
ProcessorState(Document* aSourceDocument,
Document* aXslDocument);
/**
* Destroys this ProcessorState
*/
~ProcessorState();
/**
* Contain information that is import precedence dependant.
*/
class ImportFrame {
public:
ImportFrame(ImportFrame* aFirstNotImported);
~ImportFrame();
// Map of named templates
txExpandedNameMap mNamedTemplates;
// Map of template modes, each item in the map is a list
// of templates
txExpandedNameMap mMatchableTemplates;
// List of whitespace preserving and stripping nametests
txList mWhiteNameTests;
// Map of named attribute sets
txExpandedNameMap mNamedAttributeSets;
// Output format, as specified by the xsl:output elements
txOutputFormat mOutputFormat;
// ImportFrame which is the first one *not* imported by this frame
ImportFrame* mFirstNotImported;
// Map of top-level variables/parameters
txExpandedNameMap mVariables;
// The following stuff is missing here:
// Namespace aliases (xsl:namespace-alias)
};
// To be able to do some cleaning up in destructor
friend class ImportFrame;
/**
* Adds the given attribute set to the list of available named attribute
* sets
* @param aAttributeSet the Element to add as a named attribute set
* @param aImportFrame ImportFrame to add the attributeset to
*/
void addAttributeSet(Element* aAttributeSet, ImportFrame* aImportFrame);
/**
* Registers the given ErrorObserver with this ProcessorState
*/
void addErrorObserver(ErrorObserver& errorObserver);
/**
* Adds the given template to the list of templates to process
* @param aXslTemplate The Element to add as a template
* @param aImportFrame ImportFrame to add the template to
*/
void addTemplate(Element* aXslTemplate, ImportFrame* aImportFrame);
/**
* Adds the given LRE Stylesheet to the list of templates to process
* @param aStylesheet The Stylesheet to add as a template
* @param importFrame ImportFrame to add the template to
*/
void addLREStylesheet(Document* aStylesheet, ImportFrame* aImportFrame);
/**
* Returns the AttributeSet associated with the given name
* or null if no AttributeSet is found
*/
NodeSet* getAttributeSet(const txExpandedName& aName);
/**
* Returns the template associated with the given name, or
* null if not template is found
*/
Element* getNamedTemplate(const txExpandedName& aName);
/**
* Returns the OutputFormat which contains information on how
* to serialize the output.
*/
txOutputFormat* getOutputFormat();
/**
* Add a global variable
*/
nsresult addGlobalVariable(const txExpandedName& aVarName,
Element* aVarElem,
ImportFrame* aImportFrame,
ExprResult* aDefaultValue);
/**
* Returns map on top of the stack of local variable-bindings
*/
txVariableMap* getLocalVariables();
/**
* Sets top map of the local variable-bindings stack
*/
void setLocalVariables(txVariableMap* aMap);
/**
* Enums for the getExpr and getPattern functions
*/
enum ExprAttr {
SelectAttr = 0,
TestAttr,
ValueAttr
};
enum PatternAttr {
CountAttr = 0,
FromAttr
};
Expr* getExpr(Element* aElem, ExprAttr aAttr);
txPattern* getPattern(Element* aElem, PatternAttr aAttr);
/**
* Retrieve the document designated by the URI uri, using baseUri as base URI.
* Parses it as an XML document, and returns it. If a fragment identifier is
* supplied, the element with seleced id is returned.
* The returned document is owned by the ProcessorState
*
* @param uri the URI of the document to retrieve
* @param baseUri the base URI used to resolve the URI if uri is relative
* @return loaded document or element pointed to by fragment identifier. If
* loading or parsing fails NULL will be returned.
*/
Node* retrieveDocument(const String& uri, const String& baseUri);
/**
* Return stack of urls of currently entered stylesheets
*/
Stack* getEnteredStylesheets();
/**
* Return list of import containers
*/
List* getImportFrames();
/**
* Find template in specified mode matching the supplied node
* @param aNode node to find matching template for
* @param aMode mode of the template
* @param aImportFrame out-param, is set to the ImportFrame containing
* the found template
* @return root-node of found template, null if none is found
*/
Node* findTemplate(Node* aNode,
const txExpandedName& aMode,
ImportFrame** aImportFrame)
{
return findTemplate(aNode, aMode, 0, aImportFrame);
}
/**
* Find template in specified mode matching the supplied node. Only search
* templates imported by a specific ImportFrame
* @param aNode node to find matching template for
* @param aMode mode of the template
* @param aImportedBy seach only templates imported by this ImportFrame,
* or null to search all templates
* @param aImportFrame out-param, is set to the ImportFrame containing
* the found template
* @return root-node of found template, null if none is found
*/
Node* findTemplate(Node* aNode,
const txExpandedName& aMode,
ImportFrame* aImportedBy,
ImportFrame** aImportFrame);
/**
* Struct holding information about a current template rule
*/
struct TemplateRule {
ImportFrame* mFrame;
const txExpandedName* mMode;
txVariableMap* mParams;
};
/**
* Gets current template rule
*/
TemplateRule* getCurrentTemplateRule();
/**
* Sets current template rule
*/
void setCurrentTemplateRule(TemplateRule* aTemplateRule);
/**
* Adds the set of names to the Whitespace preserving element set
*/
void preserveSpace(String& names);
void processAttrValueTemplate(const String& aAttValue,
Element* aContext,
String& aResult);
/**
* Adds the set of names to the Whitespace stripping handling list.
* xsl:strip-space calls this with MB_TRUE, xsl:preserve-space
* with MB_FALSE
* aElement is used to resolve QNames
*/
void shouldStripSpace(String& aNames, Element* aElement,
MBool aShouldStrip,
ImportFrame* aImportFrame);
/**
* Adds the supplied xsl:key to the set of keys
*/
MBool addKey(Element* aKeyElem);
/**
* Returns the key with the supplied name
* returns NULL if no such key exists
*/
txXSLKey* getKey(txExpandedName& keyName);
/**
* Adds a decimal format. Returns false if the format already exists
* but dosn't contain the exact same parametervalues
*/
MBool addDecimalFormat(Element* element);
/**
* Returns a decimal format or NULL if no such format exists.
*/
txDecimalFormat* getDecimalFormat(const txExpandedName& name);
/**
* Returns a pointer to a document that can be used to create RTFs
*/
Document* getRTFDocument();
/**
* Sets a new document to be used for creating RTFs
*/
void setRTFDocument(Document* aDoc);
/**
* Returns the stylesheet document
*/
Document* getStylesheetDocument();
/**
* Virtual methods from txIEvalContext
*/
TX_DECL_MATCH_CONTEXT;
/**
* Set the current txIEvalContext and get the prior one
*/
txIEvalContext* setEvalContext(txIEvalContext* aEContext)
{
txIEvalContext* tmp = mEvalContext;
mEvalContext = aEContext;
return tmp;
}
/**
* Get the current txIEvalContext
*/
txIEvalContext* getEvalContext()
{
return mEvalContext;
}
/**
* More other functions
*/
void receiveError(String& errorMessage)
{
receiveError(errorMessage, NS_ERROR_FAILURE);
}
/**
* Returns a FunctionCall which has the given name.
* @return the FunctionCall for the function with the given name.
*/
nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID,
Element* aElem, FunctionCall*& aFunction);
#ifdef TX_EXE
txIOutputXMLEventHandler* mOutputHandler;
#else
nsCOMPtr<txIOutputXMLEventHandler> mOutputHandler;
#endif
txXMLEventHandler* mResultHandler;
txIOutputHandlerFactory* mOutputHandlerFactory;
private:
class MatchableTemplate {
public:
MatchableTemplate(Node* aTemplate, txPattern* aPattern,
double aPriority)
: mTemplate(aTemplate), mMatch(aPattern), mPriority(aPriority)
{
}
Node* mTemplate;
txPattern* mMatch;
double mPriority;
};
class GlobalVariableValue : public TxObject {
public:
GlobalVariableValue(ExprResult* aValue = 0)
: mValue(aValue), mFlags(nonOwned)
{
}
virtual ~GlobalVariableValue();
ExprResult* mValue;
char mFlags;
enum _flags
{
nonOwned = 0,
evaluating,
owned
};
};
/**
* The list of ErrorObservers registered with this ProcessorState
*/
List errorObservers;
/**
* Stack of URIs for currently entered stylesheets
*/
Stack enteredStylesheets;
/**
* List of import containers. Sorted by ascending import precedence
*/
txList mImportFrames;
/**
* The output format used when serializing the result
*/
txOutputFormat mOutputFormat;
/**
* The set of loaded documents. This includes both document() loaded
* documents and xsl:include/xsl:import'ed documents.
*/
NamedMap loadedDocuments;
/**
* The set of all available keys
*/
txExpandedNameMap mXslKeys;
/**
* The set of all avalible decimalformats
*/
txExpandedNameMap mDecimalFormats;
/**
* Default decimal-format
*/
txDecimalFormat mDefaultDecimalFormat;
/**
* List of hashes with parsed expression. Every listitem holds the
* expressions for an attribute name
*/
Map mExprHashes[3];
/**
* List of hashes with parsed patterns. Every listitem holds the
* patterns for an attribute name
*/
Map mPatternHashes[2];
/**
* Current txIEvalContext*
*/
txIEvalContext* mEvalContext;
/**
* Current template rule
*/
TemplateRule* mCurrentTemplateRule;
/**
* Top of stack of local variable-bindings
*/
txVariableMap* mLocalVariables;
/**
* Map of values of global variables
*/
txExpandedNameMap mGlobalVariableValues;
Document* mSourceDocument;
Document* xslDocument;
/**
* Document used to create RTFs
*/
Document* mRTFDocument;
};
/**
* txNameTestItem holds both an ElementExpr and a bool for use in
* whitespace stripping.
*/
class txNameTestItem {
public:
txNameTestItem(txAtom* aPrefix, txAtom* aLocalName, PRInt32 aNSID,
MBool stripSpace)
: mNameTest(aPrefix, aLocalName, aNSID, Node::ELEMENT_NODE),
mStrips(stripSpace)
{
}
MBool matches(Node* aNode, txIMatchContext* aContext) {
return mNameTest.matches(aNode, aContext);
}
MBool stripsSpace() {
return mStrips;
}
double getDefaultPriority() {
return mNameTest.getDefaultPriority();
}
protected:
txNameTest mNameTest;
MBool mStrips;
};
/**
* txPSParseContext
* a txIParseContext forwarding all but resolveNamespacePrefix
* to a ProcessorState
*/
class txPSParseContext : public txIParseContext {
public:
txPSParseContext(ProcessorState* aPS, Element* aStyleNode)
: mPS(aPS), mStyle(aStyleNode)
{
}
~txPSParseContext()
{
}
nsresult resolveNamespacePrefix(txAtom* aPrefix, PRInt32& aID);
nsresult resolveFunctionCall(txAtom* aName, PRInt32 aID,
FunctionCall*& aFunction);
void receiveError(const String& aMsg, nsresult aRes);
protected:
ProcessorState* mPS;
Element* mStyle;
};
#endif