blob: 38e8abfa8ba4fa108af5d6a36177d87907272cde [file] [log] [blame]
/*
* 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 <cassert>
#include <xalanc/XalanDOM/XalanDOMString.hpp>
#if defined(XALAN_AUTO_PTR_REQUIRES_DEFINITION)
#include <xalanc/XPath/XPathProcessor.hpp>
#endif
#include <xalanc/Include/XalanMemMgrAutoPtr.hpp>
#include <xalanc/Include/XalanMap.hpp>
#include <xalanc/PlatformSupport/AttributeListImpl.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/PrefixResolver.hpp>
#include <xalanc/DOMSupport/XalanNamespacesStack.hpp>
#include <xalanc/XPath/Function.hpp>
#include <xalanc/XPath/XPathConstructionContextDefault.hpp>
#include "OutputContextStack.hpp"
#include "ProblemListenerDefault.hpp"
#include "ResultNamespacesStack.hpp"
#include "StylesheetExecutionContext.hpp"
#include "XSLTProcessorException.hpp"
#include "XalanParamHolder.hpp"
namespace XERCES_CPP_NAMESPACE { class InputSource; }
namespace XERCES_CPP_NAMESPACE { class DocumentHandler; }
XALAN_CPP_NAMESPACE_BEGIN
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<const Locator*> LocatorStack;
typedef XalanVector<TraceListener*> TraceListenerVectorType;
typedef XalanVector<const XalanDOMString*> XalanDOMStringPointerVectorType;
typedef XalanVector<bool> 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<XPathProcessor> XPathProcessorPtrType;
typedef Function::XObjectArgVectorType XObjectArgVectorType;
typedef StylesheetExecutionContext::ParamVectorType ParamVectorType;
typedef XPathConstructionContext::GetCachedString CCGetCachedString;
typedef XPathExecutionContext::GetCachedString ECGetCachedString;
typedef XalanMap<XalanDOMString, XalanParamHolder> 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.
*/
unsigned long 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;
};
XALAN_CPP_NAMESPACE_END
#endif // XALAN_XSLTENGINEIMPL_HEADER_GUARD