/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if !defined(XALAN_ELEMTEMPLATEELEMENT_HEADER_GUARD) #define XALAN_ELEMTEMPLATEELEMENT_HEADER_GUARD // Base include file. Must be first. #include #include #include #include #include #include #include #include #include "LocalMsgIndex.hpp" namespace XERCES_CPP_NAMESPACE { class AttributeList; class Locator; } namespace XALAN_CPP_NAMESPACE { typedef xercesc::AttributeList AttributeListType; typedef xercesc::Locator LocatorType; using xercesc::AttributeList; using xercesc::Locator; class ElemTemplate; class ElemTextLiteral; class NamespacesHandler; class Stylesheet; class StylesheetConstructionContext; class StylesheetExecutionContext; class XPath; class XALAN_XSLT_EXPORT ElemTemplateElement : public PrefixResolver { public: /** * Construct a template element instance. * * @param constructionContext context when object constructed * @param stylesheetTree owning stylesheet * @param lineNumber line in the XSLT file where the element occurs * @param columnNumber column index in the XSLT file where the * element occurs * @param xslToken an integer representing the type of instance. */ ElemTemplateElement( StylesheetConstructionContext& constructionContext, Stylesheet& stylesheetTree, XalanFileLoc lineNumber, XalanFileLoc columnNumber, int xslToken); /** * Special constructor used by dummy elements which do not exist in the * final stylesheet. * * @param constructionContext context when object constructed * @param stylesheetTree owning stylesheet * @param baseURI The base URI of the XSLT file where the element occurs. * @param lineNumber line in the XSLT file where the element occurs * @param columnNumber column index in the XSLT file where the * element occurs * @param xslToken an integer representing the type of instance. */ ElemTemplateElement( StylesheetConstructionContext& constructionContext, Stylesheet& stylesheetTree, int xslToken, const XalanDOMString& baseURI = XalanDOMString(XalanMemMgrs::getDummyMemMgr()), XalanFileLoc lineNumber = XalanLocator::getUnknownValue(), XalanFileLoc columnNumber = XalanLocator::getUnknownValue()); virtual ~ElemTemplateElement(); /** * Get the Locator for the node. This may return 0. * * @return The Locator for the node. */ virtual const Locator* getLocator() const; /** * See if this is a xmlns attribute or in a non-XSLT. * * @param attrName qualified name of attribute * @param atts attribute list where the element comes from (not used at * this time) * @param which index into the attribute list (not used at this time) * @param constructionContext The current construction context * @return true if this is a namespace name */ virtual bool isAttrOK( const XalanDOMChar* attrName, const AttributeListType& atts, XalanSize_t which, StylesheetConstructionContext& constructionContext) const; /** * Tell whether or not this is a xml:space attribute and, if so, process it. * * @param elementName name of the element with the attribute * @param aname name of the attribute in question * @param atts attribute list that owns the attribute * @param which index of the attribute into the attribute list * @param constructionContext The current construction context * @return true if this is a xml:space attribute */ bool processSpaceAttr( const XalanDOMChar* elementName, const XalanDOMChar* aname, const AttributeListType& atts, XalanSize_t which, StylesheetConstructionContext& constructionContext); /** * Validate that the string is an NCName. * * @param s name in question * @return true if the string is a valid NCName according to XML rules * @see http://www.w3.org/TR/REC-xml-names#NT-NCName */ static bool isValidNCName(const XalanDOMString& s); #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) /** * Completes "pre-processing" before any sub-elements are invoked * (i.e. children, attribute sets and templates). If there are * no sub-elements it executes the primary function of the element. * * @param executionContext context to execute this element */ virtual const ElemTemplateElement* startElement(StylesheetExecutionContext& executionContext) const; /** * Completes "post-processing" afer any sub-elements are invoked * (i.e. children, attribute sets and templates). If there are * no sub-elements it does nothing * * @param executionContext context to execute this element */ virtual void endElement(StylesheetExecutionContext& executionContext) const; /** * Execute the element. * * @param execute context to execute this element */ virtual void execute(StylesheetExecutionContext& executionContext) const; /** * Execute the children of this element. * * @param execute context to execute this element */ virtual void executeChildren(StylesheetExecutionContext& executionContext) const; /** * Returns the element that invoked this element. * @returns element that invoked this element. */ virtual const ElemTemplateElement* getInvoker(StylesheetExecutionContext& executionContext) const; #else /** * Execute the element's primary function. Subclasses of this function may * recursively execute down the element tree. * * @param executionContext The current execution context */ virtual void execute(StylesheetExecutionContext& executionContext) const; /** * Process the children of a template. * * @param processor XSLT processor instance */ virtual void executeChildren(StylesheetExecutionContext& executionContext) const; /** * Set the current node and process the children of a template. * * @param processor XSLT processor instance * @param sourceNode current node */ virtual void executeChildren( StylesheetExecutionContext& executionContext, XalanNode* sourceNode) const; /** * Take the contents of a template element, process it, and * convert it to a string. Returns a const reference to * the resulting string value. Note that this may _not_ be * the XalanDOMString instance passed in, if an optimization * is available to return a pre-existing string. * * @param executionContext The current execution context * @param result result of executing the elements children * @result a reference to a string containing the result. */ const XalanDOMString& childrenToString( StylesheetExecutionContext& executionContext, XalanDOMString& result) const; /** * Take the contents of a template element, process it, and * convert it to a string. Then, add an attribute to the * result tree using the provided name and the string value. * * @param executionContext The current execution context * @param theName The name for the result attribute */ void childrenToResultAttribute( StylesheetExecutionContext& executionContext, const XalanDOMString& theName) const; /** * Take the contents of a template element, process it, and * convert it to a string. Then, add a comment to the * result tree using the string value. * * @param executionContext The current execution context */ void childrenToResultComment(StylesheetExecutionContext& executionContext) const; /** * Take the contents of a template element, process it, and * convert it to a string. Then, add a processing instruction * to the result tree using the string value, and the provided * target. * * @param executionContext The current execution context * @param theName The name for the result attribute */ void childrenToResultPI( StylesheetExecutionContext& executionContext, const XalanDOMString& theTarget) const; /** * Get an integer representation of the element type. * * @return integer representation of the element, defined in the Constants * class * @see class Constants */ #endif int getXSLToken() const { return m_xslToken; } /** * Tell if the element will generate text which is XML whitespace. * * @return true if the text is pure whitespace */ virtual bool isWhitespace() const; /** * Get a string for the name of the element. Useful for debugging purposes, * and error reporting. * * @return A string containing the name of the element. */ virtual const XalanDOMString& getElementName() const = 0; /** * Get the QName associated with any name attribute of this element. * If the element has no name attribute, this will be an empty QName. * * @return A string containing the name of the element. */ virtual const XalanQName& getNameAttribute() const; /** * Called during compilation when an instance is not parented by * another element, and thus, is a child of the stylesheet.. * * @param constructionContext The current construction context * @param theStylesheet The owning stylesheet * @return nothing */ virtual void addToStylesheet( StylesheetConstructionContext& constructionContext, Stylesheet& theStylesheet); /** * Called during compilation to process xsl:sort elements in * the stylesheet. * * @param constructionContext The current construction context * @param theStylesheet The owning stylesheet * @param atts The list of attributes for the sort element * @param locator A Locator instance for error reporting, if available. * * @return nothing */ virtual void processSortElement( StylesheetConstructionContext& constructionContext, Stylesheet& theStylesheet, const AttributeListType& atts, const Locator* locator = 0); /** * Sets a flag indicating this is the default template * * @param value The value of flag. */ virtual void setDefaultTemplate(bool value); /** * Get the namespaces handler for this element. * * @return The element's NamespacesHandler instance. */ const NamespacesHandler& getNamespacesHandler() const { return m_namespacesHandler; } /** * Retrieve the stylesheet from which this element comes * * @return reference to source stylesheet */ const Stylesheet& getStylesheet() const { return m_stylesheet; } /** * Set the flag indicating construction of the element is completed. * * @param fValue The value to set */ void setFinishedConstruction(bool fValue) { setFlag(eFinishedConstruction, fValue); } /** * Get the flag indicating construction of the element is completed. */ bool getFinishedConstruction() const { return getFlag(eFinishedConstruction); } /** * Called after construction is completed. */ virtual void postConstruction( StylesheetConstructionContext& constructionContext, const NamespacesHandler& theParentHandler); // Type-safe getters/setters... /** * Get the first child. * * @return first child node of this node */ virtual ElemTemplateElement* getFirstChildElem() const; #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) /** * Method to initiate the execution of the element's children. * * @param executionContext context to execute this element * @returns the first child element to execute */ virtual const ElemTemplateElement* beginExecuteChildren( StylesheetExecutionContext& executionContext) const; /** * Method to indicate the execution of the element's children * is complete * * @param executionContext context to execute this element */ virtual void endExecuteChildren( StylesheetExecutionContext& executionContext) const; /** * Method to initiate output from the children * to a string. * * @param executionContext context to execute this element * @param result string to contain the final result * @returns the first child element to execute */ const ElemTemplateElement* beginChildrenToString( StylesheetExecutionContext& executionContext, XalanDOMString& result) const; /** * Method to indicate string output from the children is * complete. * * @param executionContext context to execute this element */ void endChildrenToString( StylesheetExecutionContext& executionContext) const; #endif /** * Set the first child. * * theChild - the new value for the first child. * * @return nothing */ virtual void setFirstChildElem(ElemTemplateElement* theChild); /** * Get the last child. * * @return last child node of this node */ virtual ElemTemplateElement* getLastChildElem() const; /** * Get the next sibling. * * @return next sibling node of this node */ virtual ElemTemplateElement* getNextSiblingElem() const; #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) /** * Returns the next sub-element *(i.e. children, attribute-sets, templates) to execute. * * @param executionContext context to execute element * @param currentElem the last sub-element to be executed * @returns next sub-element to execute, 0 only if no more sub-elements to execute */ virtual const ElemTemplateElement* getNextChildElemToExecute( StylesheetExecutionContext& executionContext, const ElemTemplateElement* currentElem) const; /** * Returns the first sub-element *(i.e. children, attribute-sets, templates) to execute. * * @param executionContext context to execute element * @returns first sub-element to execute, 0 only if no sub-elements to execute */ virtual const ElemTemplateElement* getFirstChildElemToExecute( StylesheetExecutionContext& executionContext) const; /** * Filters sub-elements that should be executed * * @param executionContext context to execute element * @param element the element to be executed * @returns true if element should be executed, false otherwise */ virtual bool executeChildElement( StylesheetExecutionContext& executionContext, const ElemTemplateElement* element) const; #endif /** * Set the next sibling. * * theSibling - the new value for the next sibling. * * @return nothing */ virtual void setNextSiblingElem(ElemTemplateElement* theSibling); /** * Get the previous sibling. * * @return previous sibling node of this node */ virtual ElemTemplateElement* getPreviousSiblingElem() const; /** * Set the previous sibling. * * theSibling - the new value for the previous sibling. * * @return nothing */ virtual void setPreviousSiblingElem(ElemTemplateElement* theSibling); /** * Get the parent node. * * @return parent node of this node */ virtual ElemTemplateElement* getParentNodeElem() const; /** * Set the parent node. * * theParent - the new value for the parent. * * @return nothing */ virtual void setParentNodeElem(ElemTemplateElement* theParent); /** * Append a child. * * theParent - the new value for the parent. * * @return nothing */ virtual ElemTemplateElement* appendChildElem(ElemTemplateElement* newChild); /** * Get XPath pattern/expression of one of the element atribute * * @index number of the attribute. If an attribute has more * then one attribute with pattern/expression,the order of * the returned expressions are undefined * * @return pointer or null */ virtual const XPath* getXPath(XalanSize_t index) const; // These interfaces are inherited from PrefixResolver... virtual const XalanDOMString* getNamespaceForPrefix(const XalanDOMString& prefix) const; virtual const XalanDOMString& getURI() const; // A class that implements the XalanLocator // abstract base class. ElemTemplateElement // uses this class to provide locator information. class LocatorProxy : public XalanLocator { public: LocatorProxy( XalanFileLoc theLineNumber, XalanFileLoc theColumnNumber, const XalanDOMString& theURI); virtual ~LocatorProxy(); virtual const XMLCh* getPublicId() const; virtual const XMLCh* getSystemId() const; virtual XalanFileLoc getLineNumber() const; virtual XalanFileLoc getColumnNumber() const; const XalanDOMString& getURI() const { return m_uri; } private: // Not implemented... LocatorProxy(const LocatorProxy&); LocatorProxy& operator=(const LocatorProxy&); bool operator==(const LocatorProxy&) const; // data members... const XalanFileLoc m_lineNumber; const XalanFileLoc m_columnNumber; const XalanDOMString& m_uri; }; XalanFileLoc getLineNumber() const { return m_locatorProxy.getLineNumber(); } XalanFileLoc getColumnNumber() const { return m_locatorProxy.getColumnNumber(); } bool hasParams() const { return getFlag(eHasParams); } bool hasVariables() const { return getFlag(eHasVariables); } bool hasSingleTextChild() const { return getFlag(eHasSingleTextChild); } bool hasChildren() const { return m_firstChild != 0 ? true : false; } bool hasDirectTemplate() const { return getFlag(eHasDirectTemplate); } bool canGenerateAttributes() const { return getFlag(eCanGenerateAttributes); } bool isDefaultTemplate() const { return getFlag(eDefaultTemplate); } protected: void canGenerateAttributes(bool value) { setFlag(eCanGenerateAttributes, value); } void hasPrefix(bool value) { setFlag(eHasPrefix, value); } bool hasPrefix() const { return getFlag(eHasPrefix); } void preserveSpace(bool value) { setFlag(eSpacePreserve, value); } bool preserveSpace() const { return getFlag(eSpacePreserve); } void disableOutputEscaping(bool value) { setFlag(eDisableOutputEscaping, value); } bool disableOutputEscaping() const { return getFlag(eDisableOutputEscaping); } /** * Process the exclude-result-prefixes or the extension-element-prefixes * attributes, for the purpose of prefix exclusion. * * @param constructionContext context when object consructed * @param stylesheetTree The current Stylesheet object. * @param localName The local name of the attribute. * @param attrValue The value of the attribute. */ bool processPrefixControl( StylesheetConstructionContext& constructionContext, const Stylesheet& stylesheetTree, const XalanDOMString& localName, const XalanDOMChar* attrValue); /** * Get the namespace for a given prefix. * * @param prefix The prefix to search for * @param fExists If not null, set to true if the namespace was defined. * @return The namespace string. */ const XalanDOMString* getNamespaceForPrefixInternal(const XalanDOMString& prefix) const; #if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) /** * Given an element, find the corresponding * template. * * @param executionContext The current execution context * @param xslInstruction The calling element * @param template The template to use if xsl:for-each, or null. * @param child The source context node. * @returns matching template if any. Returns 0 if no matching template or corresponds to a default rule. */ virtual const ElemTemplateElement* findTemplateToTransformChild( StylesheetExecutionContext& executionContext, const ElemTemplateElement& xslInstruction, const ElemTemplateElement* theTemplate, XalanNode* child) const; /** * Given an element, find the corresponding * template. * * @param executionContext The current execution context * @param xslInstruction The calling element * @param template The template to use if xsl:for-each, or null. * @param child The source context node. * @param nodeType The type of child. * @returns matching template if any. Returns 0 if no matching template or corresponds to a default rule. */ virtual const ElemTemplateElement* findTemplateToTransformChild( StylesheetExecutionContext& executionContext, const ElemTemplateElement& xslInstruction, const ElemTemplateElement* theTemplate, XalanNode* child, XalanNode::NodeType nodeType) const; #else /** * Given an element, find the corresponding * template and process the contents. * * @param executionContext The current execution context * @param xslInstruction The calling element * @param template The template to use if xsl:for-each, or null. * @param child The source context node. */ virtual void transformChild( StylesheetExecutionContext& executionContext, const ElemTemplateElement& xslInstruction, const ElemTemplateElement* theTemplate, XalanNode* child) const; /** * Given an element, find the corresponding * template and process the contents. * * @param executionContext The current execution context * @param xslInstruction The calling element * @param template The template to use if xsl:for-each, or null. * @param child The source context node. * @param nodeType The type of child. */ virtual void transformChild( StylesheetExecutionContext& executionContext, const ElemTemplateElement& xslInstruction, const ElemTemplateElement* theTemplate, XalanNode* child, XalanNode::NodeType nodeType) const; #endif /** * Given an xsl token type, determine whether or not a child * of that type is allowed. This is so derived types can * determine whether a particular type of child is allowed for * the instance. It is called from appendChildElem(). * * The default is to allow no types (no children) * * @param xslToken The xsl token value of the child. * * @return true if the child is allowed, or false if not. */ virtual bool childTypeAllowed(int xslToken) const; /** * Called after construction is completed. This is a hook for * deriving classes to handle post-construction with the * instances HamespaceHandler instance, which is otherwise only * available through a const accessor. */ virtual void namespacesPostConstruction( StylesheetConstructionContext& constructionContext, const NamespacesHandler& theParentHandler, NamespacesHandler& theHandler); const NamespacesHandler& getNamespaces() const { return m_namespacesHandler; } /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message */ void error( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode) const; /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message * @param theToken The substitution token for the message */ void error( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode, const XalanDOMString& theToken) const; /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message * @param theLocator The Locator instance to use, if any */ void error( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode, const Locator* theLocator) const; /** * A convenience function for loading a message * and reporting a warning through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message */ void warn( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode) const; /** * A convenience function for loading a message * and reporting a warning through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message * @param theToken The substitution token for the message */ void warn( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode, const XalanDOMString& theToken) const; /** * A convenience function for loading a message * and reporting a warning through the provided * StylesheetExecutionContext instance. * * @param theContext The StylesheetExecutionContext to use * @param theCode The code of the message * @param theLocator The Locator instance to use, if any */ void warn( StylesheetExecutionContext& theContext, XalanMessages::Codes theCode, const Locator* theLocator) const; /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode); /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken The substitution token for the message * @param theLocator The Locator instance to use, if any */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMString& theToken); /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken The substitution token for the message * @param theLocator The Locator instance to use, if any */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMString& theToken, const Locator* theLocator); /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken1 The first substitution token for the message * @param theToken2 The second substitution token for the message */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMString& theToken1, const XalanDOMString& theToken2); /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken1 The first substitution token for the message * @param theToken2 The second substitution token for the message */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMChar* theToken1, const XalanDOMChar* theToken2); /** * A convenience function for loading a message * and reporting an error through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken1 The first substitution token for the message * @param theToken2 The second substitution token for the message * @param theToken3 The third substitution token for the message */ void error( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMChar* theToken1, const XalanDOMChar* theToken2, const XalanDOMChar* theToken3); /** * A convenience function for loading a message * and reporting a warning through the provided * StylesheetConstructionContext instance. * * @param theContext The StylesheetConstructionContext to use * @param theCode The code of the message * @param theToken1 The first substitution token for the message * @param theToken2 The second substitution token for the message * @param theToken3 The third substitution token for the message */ void warn( StylesheetConstructionContext& theContext, XalanMessages::Codes theCode, const XalanDOMChar* theToken1, const XalanDOMChar* theToken2, const XalanDOMChar* theToken3); // A handy empty XalanDOMString instance for // derived classes to use. static const XalanDOMString s_emptyString; private: enum eFlags { eHasParams = 1, eHasSingleTextChild = 2, eHasVariables = 4, eHasDirectTemplate = 8, eCanGenerateAttributes = 16, eDefaultTemplate = 32, eSpacePreserve = 64, eFinishedConstruction = 128, eHasPrefix = 256, eDisableOutputEscaping = 512 }; bool getFlag(eFlags theFlag) const { return m_flags & theFlag ? true : false; } void setFlag( eFlags theFlag, bool theValue) { if (theValue == true) { m_flags |= theFlag; } else { m_flags &= ~theFlag; } } #if defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION) /** * Take the contents of a template element, process it, and * convert it to a string. * * @param executionContext The current execution context * @param result result of executing the elements children * @result a reference to a string containing the result. */ XalanDOMString& doChildrenToString( StylesheetExecutionContext& executionContext, XalanDOMString& result) const; #endif Stylesheet& m_stylesheet; /* * This object handles all result tree namespace processing. */ NamespacesHandler m_namespacesHandler; const int m_xslToken; ElemTemplateElement* m_parentNode; ElemTemplateElement* m_nextSibling; ElemTemplateElement* m_previousSibling; union { ElemTemplateElement* m_firstChild; const ElemTemplate* m_directTemplate; const ElemTextLiteral* m_textLiteralChild; }; LocatorProxy m_locatorProxy; unsigned short m_flags; static const XalanQNameByReference s_emptyQName; // Not implemented... ElemTemplateElement(const ElemTemplateElement&); ElemTemplateElement& operator=(const ElemTemplateElement&); bool operator==(const ElemTemplateElement&) const; }; } #endif // XALAN_ELEMTEMPLATEELEMENT_HEADER_GUARD