/* * 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_XSLTENGINEIMPL_HEADER_GUARD) #define XALAN_XSLTENGINEIMPL_HEADER_GUARD // Base include file. Must be first. #include "XSLTDefinitions.hpp" // Base class #include "XSLTProcessor.hpp" // Standard library headers #include #include #if defined(XALAN_AUTO_PTR_REQUIRES_DEFINITION) #include #endif #include #include #include #include #include #include #include #include #include "OutputContextStack.hpp" #include "ProblemListenerDefault.hpp" #include "ResultNamespacesStack.hpp" #include "StylesheetExecutionContext.hpp" #include "XSLTProcessorException.hpp" #include "XalanParamHolder.hpp" namespace XERCES_CPP_NAMESPACE { class InputSource; class DocumentHandler; } namespace XALAN_CPP_NAMESPACE { typedef xercesc::InputSource InputSourceType; typedef xercesc::DocumentHandler DocumentHandlerType; using xercesc::InputSource; using xercesc::DocumentHandler; // Forward declarations... class DOMSupport; class GenerateEvent; class PrintWriter; class StylesheetConstructionContext; class StylesheetRoot; class XalanAttr; class XalanSourceTreeDocument; class XalanText; class XMLParserLiaison; class XObject; class XPathEnvSupport; class XPathFactory; class XPathProcessor; class XSLTResultTarget; /** * It's the responsibility of the XSLTEngineImpl class, collaborating with the * XML parser liaison, the DOM, and the XPath engine, to transform a source * tree of nodes into a result tree according to instructions and templates * specified by a stylesheet tree. The process method is the primary * public entry points. * * * If you reuse the processor instance, you should call reset() between calls. * */ class XALAN_XSLT_EXPORT XSLTEngineImpl : public XSLTProcessor, public PrefixResolver { public: struct LessXalanDOMStringPointers { bool operator()( const XalanDOMString* theLHS, const XalanDOMString* theRHS) const { if (theLHS == 0 && theRHS != 0) { return true; } else if (theRHS == 0) { return false; } else { return theLHS->compare(*theRHS) < 0 ? true : false; } } }; typedef XalanVector LocatorStack; typedef XalanVector TraceListenerVectorType; typedef XalanVector XalanDOMStringPointerVectorType; typedef XalanVector BoolVectorType; struct FindStringPointerFunctor { FindStringPointerFunctor(const XalanDOMString& theString) : m_string(theString) { } bool operator()(const XalanDOMString* theString) const { assert(theString != 0); return *theString == m_string; } private: const XalanDOMString& m_string; }; typedef XalanMemMgrAutoPtr XPathProcessorPtrType; typedef Function::XObjectArgVectorType XObjectArgVectorType; typedef StylesheetExecutionContext::ParamVectorType ParamVectorType; typedef XPathConstructionContext::GetCachedString CCGetCachedString; typedef XPathExecutionContext::GetCachedString ECGetCachedString; typedef XalanMap ParamMapType; // Public members //--------------------------------------------------------------------- /** * Construct an XSL processor that can call back to a XML processor, so it * can handle included files, and the like. You must create a new instance * of the XSLTEngineImpl class each time you run a transformation. * * @param XMLParserLiaison liaison to an object that can help with a * specific parser implementation * @param xpathEnvSupport An XPathEnvSupport instance * @param domSupport A DOMSupport instance for the DOM being used * @param xobjectFactory object responsible for XObject objects * @param xpathFactory object responsible for XPath objects */ XSLTEngineImpl( MemoryManager& theManager, XMLParserLiaison& parserLiaison, XPathEnvSupport& xpathEnvSupport, DOMSupport& domSupport, XObjectFactory& xobjectFactory, XPathFactory& xpathFactory); virtual ~XSLTEngineImpl(); MemoryManager& getMemoryManager() const { return m_xpathConstructionContext.getMemoryManager(); } MemoryManager& getMemoryManager() { return m_xpathConstructionContext.getMemoryManager(); } /** * Perform initialization of statics -- must be called before any * processing occurs. See class XSLTInit. */ static void initialize(MemoryManager& theManager); /** * Perform termination of statics. See class XSLTInit. */ static void terminate(); // These methods are inherited from XSLTProcessor ... virtual void problem( eSource source, eClassification classification, const XalanDOMString& msg, const Locator* locator, const XalanNode* sourceNode); virtual void problem( eSource source, eClassification classification, const XalanDOMString& msg, const XalanNode* sourceNode); virtual void process( const XSLTInputSource& inputSource, const XSLTInputSource& stylesheetSource, XSLTResultTarget& outputTarget, StylesheetConstructionContext& constructionContext, StylesheetExecutionContext& executionContext); virtual void process( const XSLTInputSource& inputSource, XSLTResultTarget& outputTarget, StylesheetExecutionContext& executionContext); virtual StylesheetRoot* processStylesheet( const XSLTInputSource& stylesheetSource, StylesheetConstructionContext& constructionContext); virtual StylesheetRoot* processStylesheet( const XalanDOMString& xsldocURLString, StylesheetConstructionContext& constructionContext); virtual XalanNode* getSourceTreeFromInput(const XSLTInputSource& inputSource); virtual void resolveTopLevelParams(StylesheetExecutionContext& executionContext); virtual XMLParserLiaison& getXMLParserLiaison() const; virtual void getUniqueNamespaceValue(XalanDOMString& theValue); virtual void setStylesheetParam( const XalanDOMString& key, const XalanDOMString& expression); virtual void setStylesheetParam( const XalanDOMString& key, XObjectPtr value); virtual void clearStylesheetParams(); virtual FormatterListener* getFormatterListener() const; virtual void setFormatterListener(FormatterListener* flistener); // Trace-related functions... virtual size_type getTraceListeners() const; virtual void addTraceListener(TraceListener* tl); virtual void removeTraceListener(TraceListener* tl); virtual void fireGenerateEvent(const GenerateEvent& ge); virtual void fireTraceEvent(const TracerEvent& te); virtual void fireSelectEvent(const SelectionEvent& se); virtual bool getTraceSelects() const; virtual void setTraceSelects(bool b); void traceSelect( StylesheetExecutionContext& executionContext, const ElemTemplateElement& theTemplate, const NodeRefListBase& nl, const XPath* xpath) const; virtual void setQuietConflictWarnings(bool b); virtual void setDiagnosticsOutput(PrintWriter* pw); // Inherited from PrefixResolver... /** * Retrieve a namespace corresponding to a prefix. This assumes that * the PrevixResolver hold's its own namespace context, or is a namespace * context itself. * * @param prefix Prefix to resolve * @return namespace that prefix resolves to, or null if prefix is not found */ virtual const XalanDOMString* getNamespaceForPrefix(const XalanDOMString& prefix) const; /** * Retrieve the base URI for the resolver. * * @return URI string */ virtual const XalanDOMString& getURI() const; /** * Read in the XML file, either producing a Document or calling SAX events, * and register the document in a table. If the document has already been * read in, it will not be reparsed. * * @param urlString location of the XML * @param docHandler pointer to SAX event handler * @param docToRegister if using a SAX event handler, the object to register in the source docs table. * @return document object, which represents the parsed XML * @exception SAXException */ XalanDocument* parseXML( const XalanDOMString& urlString, DocumentHandler* docHandler, XalanDocument* docToRegister, ErrorHandler* theErrorHandler = 0); /** * Read in the XML file, either producing a Document or calling SAX events, * and register the document in a table. If the document has already been * read in, it will not be reparsed. * * @param inputSource location of the XML * @param docHandler pointer to SAX event handler * @param docToRegister if using a SAX event handler, the object to register in the source docs table. * @return document object, which represents the parsed XML * @exception SAXException */ XalanDocument* parseXML( const InputSource& inputSource, DocumentHandler* docHandler, XalanDocument* docToRegister, ErrorHandler* theErrorHandler = 0); /** * Reset the state of the XSL processor by reading in a new XSL stylesheet * from a processing instruction. * * @param xslURLString valid URI to an XSL stylesheet * @param fragBase base of tree if URI represents document * fragment * @param xmlBaseIdent base identifier for stylesheet URI * @param isRoot true if stylesheet is root of tree * @param constructionContext context for construction of object * @return pointer to stylesheet */ Stylesheet* getStylesheetFromPIURL( const XalanDOMString& xslURLString, XalanNode& fragBase, const XalanDOMString& xmlBaseIdent, bool isRoot, StylesheetConstructionContext& constructionContext); /** * Flush the pending element. */ void flushPending(); /** * Add a namespace declaration to the namespace stack * * @param prefix namespace prefix * @param namespaceVal value of namespace */ void addResultNamespaceDecl( const XalanDOMString& prefix, const XalanDOMString& namespaceVal) { addResultNamespaceDecl( prefix, namespaceVal.c_str(), namespaceVal.length()); } /** * Add a namespace declaration to the namespace stack * * @param prefix namespace prefix * @param namespaceVal value of namespace * @param len length of namespace */ void addResultNamespaceDecl( const XalanDOMString& prefix, const XalanDOMChar* namespaceVal, size_type len) { m_resultNamespacesStack.addDeclaration( prefix, namespaceVal, len); } /** * Add attribute to attribute list, and if it is a namespace, add it to the * namespaces stack. * * @param attList attribute list added to * @param aname name of attribute * @param value value of attribute * @param fromCopy true if the attribute is being copied from the source tree * @param locator The Locator for reporting errors. */ void addResultAttribute( AttributeListImpl& attList, const XalanDOMString& aname, const XalanDOMString& value, bool fromCopy = false, const Locator* locator = 0) { addResultAttribute( attList, aname, value.c_str(), fromCopy, locator); } /** * Add attribute to attribute list, and if it is a namespace, add it to the * namespaces stack. * * @param attList attribute list added to * @param aname name of attribute * @param value value of attribute * @param fromCopy true if the attribute is being copied from the source tree * @param locator The Locator for reporting errors. */ void addResultAttribute( AttributeListImpl& attList, const XalanDOMString& aname, const XalanDOMChar* value, bool fromCopy = false, const Locator* locator = 0) { addResultAttribute( attList, aname, value, length(value), fromCopy, locator); } /** * Add attribute to attribute list, and if it is a namespace, add it to the * namespaces stack. * * @param attList attribute list added to * @param aname name of attribute * @param value value of attribute * @param theLength The length of the value * @param fromCopy true if the attribute is being copied from the source tree * @param locator The Locator for reporting errors. */ void addResultAttribute( AttributeListImpl& attList, const XalanDOMString& aname, const XalanDOMChar* value, size_type theLength, bool fromCopy = false, const Locator* locator = 0); /** * Add attribute to pending attributes list, and if it is a namespace, add * it to the namespaces stack. * * @param aname name of attribute * @param value value of attribute * @param fromCopy true if the attribute is being copied from the source tree * @param locator The Locator for reporting errors. */ void addResultAttribute( const XalanDOMString& aname, const XalanDOMChar* value, bool fromCopy = false, const Locator* locator = 0) { assert(m_outputContextStack.empty() == false); addResultAttribute( getPendingAttributesImpl(), aname, value, fromCopy, locator); } /** * Add attribute to pending attributes list, and if it is a namespace, add * it to the namespaces stack. * * @param aname name of attribute * @param value value of attribute * @param fromCopy true if the attribute is being copied from the source tree * @param locator The Locator for reporting errors. */ void addResultAttribute( const XalanDOMString& aname, const XalanDOMString& value, bool fromCopy = false, const Locator* locator = 0) { assert(m_outputContextStack.empty() == false); addResultAttribute( getPendingAttributesImpl(), aname, value, fromCopy, locator); } /** * Report an error copying a duplicate namespace node. * * @param theName The name of the node. */ void reportDuplicateNamespaceNodeError( const XalanDOMString& theName, const Locator* locator); void setDocumentLocator(const Locator* locator); void startDocument(); void endDocument(); void startElement( const XalanDOMChar* name, AttributeListType& atts); void endElement(const XalanDOMChar* name); void characters ( const XalanDOMChar* ch, size_type length); void ignorableWhitespace( const XalanDOMChar* ch, size_type length); void processingInstruction( const XalanDOMChar* target, const XalanDOMChar* data); void resetDocument(); /** * Receive notification of character data. * * @param ch pointer to characters from the XML document * @param start startng offset in 'ch' array * @param length number of characters to read from the array */ void characters( const XalanDOMChar* ch, size_type start, size_type length); /** * Send character data from the node to the result tree. * * @param node The node to send. */ void characters(const XalanNode& node); /** * Send character data from an XObject to the result tree. * * @param node The xobject to send. */ void characters(const XObjectPtr& xobject); /** * Receive notification of the beginning of an element with an empty * attribute list * * @param name element type name */ void startElement(const XalanDOMChar* name); /** * Receive notification of character data. If available, when the * disable-output-escaping attribute is used, output raw text without * escaping. * * @param ch pointer to characters from the XML document * @param start start position in the array * @param length number of characters to read from the array */ void charactersRaw( const XalanDOMChar* ch, size_type start, size_type length); /** * Send raw character data from the node to the result tree. * * @param node The node to send. */ void charactersRaw(const XalanNode& node); /** * Send raw character data from an XObject to the result tree. * * @param node The xobject to send. */ void charactersRaw(const XObjectPtr& xobject); /** * Called when a Comment is to be constructed. * * @param data pointer to comment data */ void comment(const XalanDOMChar* data); /** * Receive notification of a entityReference. * * @param data pointer to characters from the XML document * @exception SAXException */ void entityReference(const XalanDOMChar* data); /** * Receive notification of cdata. * * @param ch pointer to characters from the XML document * @param start start position in the array * @param length number of characters to read from the array */ void cdata( const XalanDOMChar* ch, size_type start, size_type length); /** * Clone a node to the result tree * * @param node node to clone * @param cloneTextNodesOnly if true, only text nodes will be cloned * @param locator the Locator for the event, if any. */ void cloneToResultTree( const XalanNode& node, bool cloneTextNodesOnly, const Locator* locator); /** * Clone a node to the result tree * * @param node node to clone * @param nodeType the type of the node * @param overrideStrip false if white space stripping should be done * @param shouldCloneAttributes true if attributes should be cloned * @param cloneTextNodesOnly if true, only text nodes will be cloned * @param locator the Locator for the event, if any. */ void cloneToResultTree( const XalanNode& node, XalanNode::NodeType nodeType, bool overrideStrip, bool shouldCloneAttributes, bool cloneTextNodesOnly, const Locator* locator); /** * Output an object to the result tree by doing the right conversions. * * @param value the XObject to output * @param outputTextNodesOnly if true, only text nodes will be copied * @param locator the Locator for the event, if any. */ void outputToResultTree( const XObject& value, bool outputTextNodesOnly, const Locator* locator); /** * Given a result tree fragment, walk the tree and output it to the result * stream. * * @param theTree result tree fragment * @param outputTextNodesOnly if true, only text nodes will be copied * @param locator the Locator for the event, if any. */ void outputResultTreeFragment( const XObject& theTree, bool outputTextNodesOnly, const Locator* locator) { outputResultTreeFragment( theTree.rtree(), outputTextNodesOnly, locator); } /** * Given a result tree fragment, walk the tree and output it to the result * stream. * * @param theTree result tree fragment * @param outputTextNodesOnly if true, only text nodes will be copied * @param locator the Locator for the event, if any. */ void outputResultTreeFragment( const XalanDocumentFragment& theTree, bool outputTextNodesOnly, const Locator* locator); /** * Retrieve the root stylesheet. * * @return pointer to root stylesheet */ virtual const StylesheetRoot* getStylesheetRoot() const; /** * Set the root stylesheet. * * @param theStylesheet pointer to new root stylesheet */ virtual void setStylesheetRoot(const StylesheetRoot* theStylesheet); /** * Set the execution context. * * @param theExecutionContext pointer to new execution context. */ virtual void setExecutionContext(StylesheetExecutionContext* theExecutionContext); /** * Retrieve the URI for the current XSL namespace, for example, * "http://www.w3.org/1999/XSL/Transform" * * @return URI string */ static const XalanDOMString& getXSLNameSpaceURL() { return s_XSLNameSpaceURL; } /** * Special Xalan namespace for built-in extensions. * * @return Xalan namespace for extensions */ static const XalanDOMString& getXalanXSLNameSpaceURL() { return s_XalanNamespaceURL; } /** * Whether to warn about pattern match conflicts. * * @return true to not warn about pattern match conflicts */ bool getQuietConflictWarnings() const { return m_quietConflictWarnings; } /** * Retrieve the result namespace corresponding to a prefix. * * @param prefix prefix for namespace * @return string for namespace URI */ const XalanDOMString* getResultNamespaceForPrefix(const XalanDOMString& prefix) const; /** * Retrieve the result prefix corresponding to a namespace. * * @param theNamespace namespace for prefix * @return string for namespace prefix */ const XalanDOMString* getResultPrefixForNamespace(const XalanDOMString& theNamespace) const; /** * Determine whether or not a prefix is in use on the pending element or * the pending attributes. * * @param thePrefix prefix for namespace * * @return true if the prefix is in use, false if not. */ bool isPendingResultPrefix(const XalanDOMString& thePrefix) const; /** * Evaluate an xpath string and return the result as a numberic score. * * @param str string to evaluate * @param context context node * @param executionContext current execution context * @return score number, higher representing better match */ double evalMatchPatternStr( const XalanDOMString& str, XalanNode* context, XPathExecutionContext& executionContext); /** * Create and initialize an xpath and return it. * * @param str string for XPath * @param resolver resolver for namespace resolution * @return pointer to XPath created */ const XPath* createMatchPattern( const XalanDOMString& str, const PrefixResolver& resolver); /** * Return the xpath created by createXPath() or * createMatchPattern(). * * @param xpath The XPath to return. */ void returnXPath(const XPath* xpath); /** * Copy XMLNS: attributes in if not already in scope. * * @param src source node */ void copyNamespaceAttributes(const XalanNode& src); /** * Evaluate an xpath string and return the result. * * @param str string to evaluate * @param executionContext current execution context * @return pointer to XObject result */ const XObjectPtr evalXPathStr( const XalanDOMString& str, XPathExecutionContext& executionContext); /** * Evaluate an xpath string and return the result. * * @param str string to evaluate * @param contextNode context node * @param prefixResolver prefix resolver to use * @param executionContext current execution context * @return pointer to XObject result */ const XObjectPtr evalXPathStr( const XalanDOMString& str, XalanNode* contextNode, const PrefixResolver& prefixResolver, XPathExecutionContext& executionContext); /** * Evaluate an xpath string and return the result. * * @param str string to evaluate * @param contextNode context node * @param prefixResolver prefix resolver to use * @param executionContext current execution context * @return pointer to XObject result */ const XObjectPtr evalXPathStr( const XalanDOMString& str, XalanNode* contextNode, const XalanElement& prefixResolver, XPathExecutionContext& executionContext); /** * Copy an attribute to an AttributeListImpl. * * @param attrName The name of the attribute * @param attrValue The value of the attribute * @param attrList The attribute list added to */ void copyAttributeToTarget( const XalanDOMString& attrName, const XalanDOMString& attrValue, AttributeListImpl& attrList); /** * Get the factory for making xpaths. * * @return XPath factory object */ XPathFactory& getXPathFactory() { return m_xpathFactory; } /** * Get the XPath processor object. * * @return XPathProcessor interface being used */ XPathProcessor& getXPathProcessor() { return *m_xpathProcessor.get(); } /** * Reset the state. This needs to be called after a process() call * is invoked, if the processor is to be used again. */ virtual void reset(); /** * Retrieve the XPath environment support object * * @return XPath environment support object */ XPathEnvSupport& getXPathEnvSupport() { return m_xpathEnvSupport; } /** * Set the problem listener property. The XSL class can have a single * listener that can be informed of errors and warnings, and can normally * control if an exception is thrown or not (or the problem listeners can * throw their own RuntimeExceptions). * * @param l pointer to ProblemListener interface */ void setProblemListener(ProblemListener* l) { m_problemListener = l; } /** * Get the problem listener property. The XSL class can have a single * listener that can be informed of errors and warnings, and can normally * control if an exception is thrown or not (or the problem listeners can * throw their own RuntimeExceptions). * * @return pointer to ProblemListener interface */ ProblemListener* getProblemListener() const { return m_problemListener; } /* * Push a new output context using the provided FormatterListener. * * @param A pointer to the FormatterListener instance for the new context. */ void pushOutputContext(FormatterListener* theListener) { m_outputContextStack.pushContext(theListener); } /* * Pop the current output context. */ void popOutputContext() { m_outputContextStack.popContext(); } /* * See if there is a pending start document event waiting. * @return true if there is a start document event waiting. */ bool getHasPendingStartDocument() const { return getHasPendingStartDocumentImpl(); } /* * Set the pending start document event state. * @param the new value */ void setHasPendingStartDocument(bool b) { setHasPendingStartDocumentImpl(b); } /* * See if a pending start document event must be flushed. * @return true if the event must be flushed. */ bool getMustFlushPendingStartDocument() const { return getMustFlushPendingStartDocumentImpl(); } /* * Set the pending start document event flush state. * @param the new value */ void setMustFlushPendingStartDocument(bool b) { setMustFlushPendingStartDocumentImpl(b); } /** * Get the list of attributes yet to be processed * * @return attribute list */ const AttributeListType& getPendingAttributes() const { return getPendingAttributesImpl(); } /** * Set the list of attributes yet to be processed * * @param pendingAttributes The attribute list */ void setPendingAttributes(const AttributeListType& pendingAttributes) { getPendingAttributesImpl() = pendingAttributes; } /** * Replace the contents of a pending attribute. * * @param theName name of attribute * @param theNewType type of attribute * @param theNewValue new value of attribute */ void replacePendingAttribute( const XalanDOMChar* theName, const XalanDOMChar* theNewType, const XalanDOMChar* theNewValue) { // Remove the old attribute, then add the new one. AttributeListImpl::addAttribute() // does this for us. getPendingAttributesImpl().addAttribute(theName, theNewType, theNewValue); } bool isElementPending() const { return !getPendingElementNameImpl().empty(); } /** * Retrieve name of the pending element currently being processed. * * @return element name */ const XalanDOMString& getPendingElementName() const { return getPendingElementNameImpl(); } /** * Changes the currently pending element name. * * @param elementName new name of element */ void setPendingElementName(const XalanDOMString& elementName) { setPendingElementNameImpl(elementName); } void setPendingElementName(const XalanDOMChar* elementName) { setPendingElementNameImpl(elementName); } /** * Get the locator from the top of the locator stack. * * @return A pointer to the Locator, or 0 if there is nothing on the stack. */ const Locator* getLocatorFromStack() const { return m_stylesheetLocatorStack.empty() == true ? 0 : m_stylesheetLocatorStack.back(); } /** * Push a locator on to the locator stack. * * @param A pointer to the Locator to push. */ void pushLocatorOnStack(const Locator* locator) { m_stylesheetLocatorStack.push_back(locator); } /** * Pop the locator from the top of the locator stack. */ void popLocatorStack() { if (m_stylesheetLocatorStack.empty() == false) { m_stylesheetLocatorStack.pop_back(); } } protected: /** * Get the list of attributes yet to be processed * * @return attribute list */ const AttributeListImpl& getPendingAttributesImpl() const { return m_outputContextStack.getPendingAttributes(); } /** * Get the list of attributes yet to be processed * * @return attribute list */ AttributeListImpl& getPendingAttributesImpl() { return m_outputContextStack.getPendingAttributes(); } /** * Set the list of attributes yet to be processed * * @param pendingAttributes The attribute list */ void setPendingAttributesImpl(const AttributeListType& pendingAttributes) { getPendingAttributesImpl() = pendingAttributes; } /** * Retrieve name of the pending element currently being processed. * * @return element name */ const XalanDOMString& getPendingElementNameImpl() const { return m_outputContextStack.getPendingElementName(); } /** * Retrieve name of the pending element currently being processed. * * @return element name */ XalanDOMString& getPendingElementNameImpl() { return m_outputContextStack.getPendingElementName(); } /** * Changes the currently pending element name. * * @param elementName new name of element */ void setPendingElementNameImpl(const XalanDOMString& elementName) { m_outputContextStack.getPendingElementName() = elementName; } /** * Changes the currently pending element name. * * @param elementName new name of element */ void setPendingElementNameImpl(const XalanDOMChar* elementName) { assert(elementName != 0); m_outputContextStack.getPendingElementName() = elementName; } /* * See if there is a pending start document event waiting. * @return true if there is a start document event waiting. */ bool getHasPendingStartDocumentImpl() const { return m_outputContextStack.getHasPendingStartDocument(); } /* * Set the pending start document event state. * @param the new value */ void setHasPendingStartDocumentImpl(bool b) { m_outputContextStack.getHasPendingStartDocument() = b; } /* * See if a pending start document event must be flushed. * @return true if the event must be flushed. */ bool getMustFlushPendingStartDocumentImpl() const { return m_outputContextStack.getMustFlushPendingStartDocument(); } /* * Set the pending start document event flush state. * @param the new value */ void setMustFlushPendingStartDocumentImpl(bool b) { m_outputContextStack.getMustFlushPendingStartDocument() = b; } FormatterListener* getFormatterListenerImpl() const { return m_outputContextStack.getFormatterListener(); } void setFormatterListenerImpl(FormatterListener* flistener) { m_outputContextStack.getFormatterListener() = flistener; } /** * The namespace that the result tree conforms to. A null value * indicates that result-ns is not used and there is no checking. * A empty string indicates that the result tree conforms to the * default namespace. */ XalanDOMString m_resultNameSpacePrefix; /** * The URL that belongs to the result namespace. */ XalanDOMString m_resultNameSpaceURL; /** * Copy the attributes from the XSL element to the created * output element. */ void copyAttributesToAttList( const XalanNode& node, AttributeListImpl& attList); // Factory for creating xpaths. XPathFactory& m_xpathFactory; // Factory for creating xobjects XObjectFactory& m_xobjectFactory; // The query/pattern-matcher object. const XPathProcessorPtrType m_xpathProcessor; /** * Stack of Booleans to keep track of if we should be outputting * cdata instead of escaped text. */ BoolVectorType m_cdataStack; private: /** * Issue a warning that only text nodes can be copied. * * @param sourceNode node in source where error occurred * @param locator The Locator to use, if any. */ void warnCopyTextNodesOnly( const XalanNode* sourceNode, const Locator* locator); /** * Clone a text node to the result tree * * @param node node to clone * @param overrideStrip false if white space stripping should be done */ void cloneToResultTree( const XalanText& node, bool overrideStrip); /** * Determine if any pending attributes is a default * namespace. */ bool pendingAttributesHasDefaultNS() const; void addResultNamespace( const XalanDOMString& thePrefix, const XalanDOMString& theName, const XalanNode& theNode, AttributeListImpl& thePendingAttributes, bool fOnlyIfPrefixNotPresent); void addResultNamespace( const XalanNode& theNode, AttributeListImpl& thePendingAttributes, bool fOnlyIfPrefixNotPresent = false); /** * The top of this stack should contain the currently processed * stylesheet SAX locator object. */ LocatorStack m_stylesheetLocatorStack; /** * The XSL class can have a single listener that can be informed * of errors and warnings, and can normally control if an exception * is thrown or not (or the problem listeners can throw their * own RuntimeExceptions). */ ProblemListenerDefault m_defaultProblemListener; ProblemListener* m_problemListener; /** * The root of a linked set of stylesheets. */ const StylesheetRoot* m_stylesheetRoot; /** * The namespace that we must match as a minimum for XSLT. */ static const XalanDOMString& s_XSLNameSpaceURL; //"http://www.w3.org/1999/XSL/Transform" /** * Special Xalan namespace for built-in extensions. */ static const XalanDOMString& s_XalanNamespaceURL; // "http://xml.apache.org/xalan" /** * Prefix to use when generating unique namespaces. */ static const XalanDOMString& s_uniqueNamespacePrefix; /** * If this is set to true, selects will be traced */ bool m_traceSelects; /** * If this is set to true, do not warn about pattern * match conflicts. */ bool m_quietConflictWarnings; /* * A stream to print diagnostics to. */ PrintWriter* m_diagnosticsPrintWriter; /** * List of listeners who are interested in tracing what's * being generated. */ TraceListenerVectorType m_traceListeners; void problem( const XalanDOMString& msg, ProblemListener::eClassification classification, const XalanNode* sourceNode, const ElemTemplateElement* styleNode) const; void problem( const XalanDOMString& msg, ProblemListener::eClassification classification, const Locator& locator, const XalanNode* sourceNode) const; void problem( const XalanDOMString& msg, ProblemListener::eClassification classification) const; //========================================================== // SECTION: Function to do with attribute handling //========================================================== /** * This is used whenever a unique namespace is needed. */ XMLUInt32 m_uniqueNSValue; ParamVectorType m_topLevelParams; public: /** * Reset the vector of top level parameters */ void clearTopLevelParams() { m_topLevelParams.clear(); } private: bool generateCDATASection() const { if (m_hasCDATASectionElements == false) { return false; } else { assert(m_cdataStack.empty() == false); return m_cdataStack.back(); } } void doFlushPending() { setMustFlushPendingStartDocument(true); flushPending(); } /** * Tell if a given element name should output its text * as cdata. * * @param elementName name of element * @return true if it should output as cdata */ bool isCDataResultElem(const XalanDOMString& elementName); void fireCharacterGenerateEvent( const XalanNode& theNode, bool isCDATA); void fireCharacterGenerateEvent( const XObjectPtr& theXObject, bool isCDATA); void fireCharacterGenerateEvent( const XalanDOMString& theString, bool isCDATA); void fireCharacterGenerateEvent( const XalanDOMChar* ch, size_type start, size_type length, bool isCDATA); void checkDefaultNamespace( const XalanDOMString& theElementName, const XalanDOMString& theElementNamespaceURI); void error( const XalanDOMString& theMessage, const Locator* theLocator, const XalanNode* theSourceNode); void warn( const XalanDOMString& theMessage, const Locator* theLocator, const XalanNode* theSourceNode); void message( const XalanDOMString& theMessage, const Locator* theLocator, const XalanNode* theSourceNode); // Data members... XMLParserLiaison& m_parserLiaison; XPathEnvSupport& m_xpathEnvSupport; DOMSupport& m_domSupport; /** * Current execution context... */ StylesheetExecutionContext* m_executionContext; /* * Stack of current output contexts... */ OutputContextStack m_outputContextStack; /* * Stack of current result namespaces... */ XalanNamespacesStack m_resultNamespacesStack; /* * Dummy AttributeListImpl */ AttributeListImpl m_dummyAttributesList; XalanDOMString m_scratchString; XalanDOMStringPointerVectorType m_attributeNamesVisited; bool m_hasCDATASectionElements; XPathConstructionContextDefault m_xpathConstructionContext; ParamMapType m_stylesheetParams; static void installFunctions(MemoryManager& theManager); static void uninstallFunctions(); static const XalanDOMString s_emptyString; static const XalanDOMString& s_stylesheetNodeName; static const XalanDOMString& s_typeString; static const XalanDOMString& s_hrefString; static const XalanDOMString& s_piTokenizerString; static const XalanDOMString& s_typeValueString1; static const XalanDOMString& s_typeValueString2; static const XalanDOMString& s_typeValueString3; static const XalanDOMString& s_typeValueString4; // Not implemented... XSLTEngineImpl(const XSLTEngineImpl&); XSLTEngineImpl& operator=(const XSLTEngineImpl&); bool operator==(const XSLTEngineImpl&) const; }; } #endif // XALAN_XSLTENGINEIMPL_HEADER_GUARD