/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */



// Class header file.
#include "XSLTEngineImpl.hpp"



#include <sax/DocumentHandler.hpp>
#include <sax/EntityResolver.hpp>
#include <sax/Locator.hpp>
#include <sax/SAXException.hpp>
#include <util/PlatformUtils.hpp>
#include <framework/URLInputSource.hpp>



#include <Include/STLHelper.hpp>



#include <XalanDOM/XalanDOMException.hpp>
#include <XalanDOM/XalanNode.hpp>
#include <XalanDOM/XalanAttr.hpp>
#include <XalanDOM/XalanComment.hpp>
#include <XalanDOM/XalanCDATASection.hpp>
#include <XalanDOM/XalanNodeList.hpp>
#include <XalanDOM/XalanNamedNodeMap.hpp>
#include <XalanDOM/XalanProcessingInstruction.hpp>
#include <XalanDOM/XalanText.hpp>



#include <PlatformSupport/PrintWriter.hpp>
#include <PlatformSupport/StringTokenizer.hpp>
#include <PlatformSupport/XalanUnicode.hpp>



#include <DOMSupport/DOMServices.hpp>
#include <DOMSupport/DOMSupport.hpp>



#include <XMLSupport/FormatterToDOM.hpp>
#include <XMLSupport/FormatterToText.hpp>
#include <XMLSupport/FormatterToXML.hpp>
#include <XMLSupport/FormatterToHTML.hpp>
#include <XMLSupport/FormatterTreeWalker.hpp>
#include <XMLSupport/XMLParserLiaison.hpp>
#include <XMLSupport/FormatterTreeWalker.hpp>



#include <XPath/ElementPrefixResolverProxy.hpp>
#include <XPath/XalanQNameByReference.hpp>
#include <XPath/ResultTreeFrag.hpp>
#include <XPath/XObject.hpp>
#include <XPath/XObjectFactory.hpp>
#include <XPath/XPathEnvSupport.hpp>
#include <XPath/XPathEnvSupportDefault.hpp>
#include <XPath/XPathExecutionContextDefault.hpp>
#include <XPath/XPathFactory.hpp>
#include <XPath/XPathProcessorImpl.hpp>
#include <XPath/XResultTreeFrag.hpp>



#include "Constants.hpp"
#include "ElemWithParam.hpp"
#include "FunctionCurrent.hpp"
#include "FunctionDocument.hpp"
#include "FunctionElementAvailable.hpp"
#include "FunctionFunctionAvailable.hpp"
#include "FunctionFormatNumber.hpp"
#include "FunctionGenerateID.hpp"
#include "FunctionKey.hpp"
#include "FunctionSystemProperty.hpp"
#include "FunctionUnparsedEntityURI.hpp"
#include "GenerateEvent.hpp"
#include "ProblemListener.hpp"
#include "ProblemListenerDefault.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"
#include "StylesheetHandler.hpp"
#include "StylesheetRoot.hpp"
#include "TraceListener.hpp"
#include "XSLTInputSource.hpp"
#include "XSLTProcessorException.hpp"
#include "XSLTResultTarget.hpp"



//#define XALAN_VQ_SPECIAL_TRACE
#if defined(XALAN_VQ_SPECIAL_TRACE)
#include "C:/Program Files/Rational/Quantify/pure.h"
#endif



const XalanDOMString	XSLTEngineImpl::s_emptyString;



//==========================================================
// SECTION: Constructors
//==========================================================

XSLTEngineImpl::XSLTEngineImpl(
			XMLParserLiaison&	parserLiaison,
			XPathEnvSupport&	xpathEnvSupport,
			DOMSupport&			domSupport,
			XObjectFactory&		xobjectFactory,
			XPathFactory&		xpathFactory) :
	XSLTProcessor(),
	DocumentHandler(),
	PrefixResolver(),
	m_useDOMResultTreeFactory(false),
	m_domResultTreeFactory(0),
	m_resultNameSpacePrefix(),
	m_resultNameSpaceURL(),
	m_xpathFactory(xpathFactory),
	m_xobjectFactory(xobjectFactory),
	m_xpathProcessor(new XPathProcessorImpl),
	m_cdataStack(),
	m_stylesheetLocatorStack(),
	m_defaultProblemListener(),
	m_problemListener(&m_defaultProblemListener),
	m_stylesheetRoot(0),
	m_traceSelects(false),
	m_quietConflictWarnings(false),
	m_diagnosticsPrintWriter(0),
	m_durationsTable(),
	m_traceListeners(),
	m_uniqueNSValue(0),
	m_topLevelParams(),
	m_parserLiaison(parserLiaison),
	m_xpathEnvSupport(xpathEnvSupport),
	m_domSupport(domSupport),
	m_executionContext(0),
	m_outputContextStack(),
	m_resultNamespacesStack(),
	m_dummyAttributesList()
{
	m_outputContextStack.pushContext();
}



void
XSLTEngineImpl::reset()
{
	m_topLevelParams.clear();
	m_durationsTable.clear();
	m_stylesheetLocatorStack.clear();
	m_cdataStack.clear();

	if (m_domResultTreeFactory != 0)
	{
		m_parserLiaison.destroyDocument(m_domResultTreeFactory);
		m_domResultTreeFactory = 0;
	}

	m_stylesheetRoot = 0;

	m_outputContextStack.reset();

	m_outputContextStack.pushContext();

	m_xpathEnvSupport.reset();
	m_xpathFactory.reset();
	m_xobjectFactory.reset();
	m_domSupport.reset();

	m_resultNamespacesStack.clear();
}



XSLTEngineImpl::~XSLTEngineImpl()
{
	reset();
}



//==========================================================
// SECTION: Main API Functions
//==========================================================



static const XalanDOMChar	s_dummyString = 0;


void
XSLTEngineImpl::process(
			const XSLTInputSource&			inputSource, 
	        const XSLTInputSource&			stylesheetSource,
	        XSLTResultTarget&				outputTarget,
			StylesheetConstructionContext&	constructionContext,
			StylesheetExecutionContext&		executionContext)
{
	XalanDOMString	xslIdentifier;

	if (0 == stylesheetSource.getSystemId())
	{
		xslIdentifier = XalanDOMString(XALAN_STATIC_UCODE_STRING("Input XSL"));
	}
	else
	{
		xslIdentifier = stylesheetSource.getSystemId();
	}

	bool totalTimeID = true;

	pushTime(&totalTimeID);

	XalanNode*	sourceTree = getSourceTreeFromInput(inputSource);

	m_stylesheetRoot = processStylesheet(stylesheetSource, constructionContext);

	if(0 != sourceTree && m_stylesheetRoot == 0)
	{
		// Didn't get a stylesheet from the input source, so look for a
		// stylesheet processing instruction...
		XalanDOMString			stylesheetURI;

		// The PI must be a child of the document...
		XalanNode*				child = sourceTree->getFirstChild();

#if !defined(XALAN_NO_NAMESPACES)
		using std::vector;
#endif

		vector<XalanDOMString>	hrefs;

		// $$$ ToDo: is this first one style valid?
		const XalanDOMString	stylesheetNodeName1(XALAN_STATIC_UCODE_STRING("xml-stylesheet"));
		const XalanDOMString	stylesheetNodeName2(XALAN_STATIC_UCODE_STRING("xml:stylesheet"));

		// $$$ ToDo: This code is much like that in getStyleSheetURIFromDoc().
		// Why is it repeated???
		// $$$ ToDo: Move these embedded strings from inside these loops
		// out here...
		// $$$ ToDo: These loops are a mess of repeated use of the
		// same data values.
		while(child != 0)
		{
			if(XalanNode::PROCESSING_INSTRUCTION_NODE == child->getNodeType())
			{
				const XalanDOMString	nodeName(child->getNodeName());

				if(equals(nodeName, stylesheetNodeName1) ||
				   equals(nodeName, stylesheetNodeName2))
				{
					bool isOK = true;

					StringTokenizer 	tokenizer(child->getNodeValue(), XALAN_STATIC_UCODE_STRING(" \t="));

					while(tokenizer.hasMoreTokens())
					{
						if(equals(tokenizer.nextToken(), XALAN_STATIC_UCODE_STRING("type")))
						{
							XalanDOMString	typeVal = tokenizer.nextToken();

							typeVal = substring(typeVal, 1, length(typeVal) - 1);

							if(!equals(typeVal, XALAN_STATIC_UCODE_STRING("text/xsl")))
							{
								isOK = false;
							}
						}
					}	
						
					if(isOK)
					{
						StringTokenizer 	tokenizer(child->getNodeValue(), XALAN_STATIC_UCODE_STRING(" \t="));

						while(tokenizer.hasMoreTokens())
						{
							const XalanDOMString	theCurrentToken = tokenizer.nextToken();

							if(equals(theCurrentToken, XALAN_STATIC_UCODE_STRING("href")))
							{
								stylesheetURI = tokenizer.nextToken();
								stylesheetURI = substring(stylesheetURI, 1, length(stylesheetURI) - 1);
								hrefs.push_back(stylesheetURI);
							}
						}
					}
				}
			}

			child = child->getNextSibling();
		}

		bool isRoot = true;
		Stylesheet* prevStylesheet = 0;
			
		if (hrefs.empty() == false)
		{
			const XalanDOMChar* const	pxch = inputSource.getSystemId();

			const XalanDOMString		sysid(pxch == 0 ? &s_dummyString : pxch); 

			do
			{
				const XalanDOMString&	ref =  hrefs.back();

				Stylesheet* stylesheet =
							getStylesheetFromPIURL(
								ref,
								*sourceTree,
								sysid,
								isRoot,
								constructionContext);

				if(false == isRoot)
				{
					prevStylesheet->addImport(stylesheet, false);
				}

				prevStylesheet = stylesheet;
				isRoot = false;
				hrefs.pop_back();
			} while(!hrefs.empty());
		}
	}

	if(0 == m_stylesheetRoot)
	{
		error("Failed to process stylesheet!");
	}
	else if(0 != sourceTree)
	{
		executionContext.setStylesheetRoot(m_stylesheetRoot);

		FormatterListener* const	theFormatter =
				outputTarget.getDocumentHandler();

		if (theFormatter != 0)
		{
			theFormatter->setPrefixResolver(this);
		}

		m_stylesheetRoot->process(sourceTree, outputTarget, executionContext);

		if(0 != m_diagnosticsPrintWriter)
		{
			displayDuration(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Total time")), &totalTimeID);
		}
	}
}



void
XSLTEngineImpl::process(
			const XSLTInputSource&			inputSource, 
	        XSLTResultTarget&				outputTarget,
			StylesheetExecutionContext&		executionContext)
{
	bool	totalTimeID = true;

	if(0 != m_diagnosticsPrintWriter)
	{
		pushTime(&totalTimeID);
	}

	XalanNode* const	sourceTree = getSourceTreeFromInput(inputSource);

	if(0 != sourceTree)
	{
		if (m_stylesheetRoot == 0)
		{
			error("No stylesheet is available to process!");
		}

		FormatterListener* const	theFormatter =
				outputTarget.getDocumentHandler();

		if (theFormatter != 0)
		{
			theFormatter->setPrefixResolver(this);
		}

		m_stylesheetRoot->process(sourceTree, outputTarget, executionContext);
	}

	if(0 != m_diagnosticsPrintWriter)
	{
		displayDuration(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Total time")), &totalTimeID);
	}
}



StylesheetRoot*
XSLTEngineImpl::processStylesheet(
			const XalanDOMString&			xsldocURLString,
			StylesheetConstructionContext&	constructionContext)
{
	const XSLTInputSource	input(c_wstr(xsldocURLString));

	return processStylesheet(input, constructionContext);
}



StylesheetRoot*
XSLTEngineImpl::processStylesheet(
  			const XSLTInputSource&			stylesheetSource,
			StylesheetConstructionContext&	constructionContext)
{
	StylesheetRoot*		theStylesheet = 0;

	const XalanDOMChar* const	systemID = stylesheetSource.getSystemId();
	XalanNode* const			stylesheetNode = stylesheetSource.getNode();

	if (systemID != 0 || stylesheetNode != 0 || stylesheetSource.getStream() != 0)
	{
		XalanDOMString	xslIdentifier;

		theStylesheet = constructionContext.create(stylesheetSource);

		StylesheetHandler	stylesheetProcessor(*theStylesheet, constructionContext);

		if(stylesheetNode != 0)
		{
			xslIdentifier = XALAN_STATIC_UCODE_STRING("Input XSL");

			FormatterTreeWalker tw(stylesheetProcessor);

			tw.traverse(stylesheetSource.getNode());
		}
		else
		{
			if (systemID != 0)
			{
				xslIdentifier = systemID;
			}

			diag(XALAN_STATIC_UCODE_STRING("========= Parsing ") + xslIdentifier + XALAN_STATIC_UCODE_STRING(" =========="));

			pushTime(&xslIdentifier);

			m_parserLiaison.parseXMLStream(stylesheetSource,
										   stylesheetProcessor);

			if(0 != m_diagnosticsPrintWriter)
				displayDuration(XALAN_STATIC_UCODE_STRING("Parse of ") + xslIdentifier, &xslIdentifier);
		}

		theStylesheet->postConstruction(constructionContext);
	}

	return theStylesheet;
}



//==========================================================
// SECTION: XML Parsing Functions
//==========================================================

XalanNode*
XSLTEngineImpl::getSourceTreeFromInput(const XSLTInputSource&	inputSource)
{
	XalanNode*		sourceTree = inputSource.getNode();

	if(0 == sourceTree)
	{
		const XalanDOMString	xmlIdentifier = 0 != inputSource.getSystemId() ?
												XalanDOMString(inputSource.getSystemId()) :
												StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Input XML"));

		// In case we have a fragment identifier, go ahead and 
		// try to parse the XML here.
		diag(XALAN_STATIC_UCODE_STRING("========= Parsing ") +
					xmlIdentifier +
					XALAN_STATIC_UCODE_STRING(" =========="));

		pushTime(&xmlIdentifier);

#if defined(XALAN_VQ_SPECIAL_TRACE)
		QuantifyStartRecordingData();
#endif

		XalanDocument* const	theDocument =
						m_parserLiaison.parseXMLStream(inputSource,
													   xmlIdentifier);
		assert(theDocument != 0);

#if defined(XALAN_VQ_SPECIAL_TRACE)
		QuantifyStopRecordingData();
#endif
		if(0 != m_diagnosticsPrintWriter)
		{
			displayDuration(
				XALAN_STATIC_UCODE_STRING("Parse of ") + xmlIdentifier,
				&xmlIdentifier);
		}

		m_xpathEnvSupport.setSourceDocument(xmlIdentifier, theDocument);

		sourceTree = theDocument;
	}

	return sourceTree;
}



const XalanDOMString*
XSLTEngineImpl::getNamespaceForPrefix(const XalanDOMString&		prefix) const
{
	return m_resultNamespacesStack.getNamespaceForPrefix(prefix);
}



const XalanDOMString&
XSLTEngineImpl::getURI() const
{
	return s_emptyString;
}



XalanDocument*
XSLTEngineImpl::parseXML(
			const XalanDOMString&	urlString,
			DocumentHandler*		docHandler,
			XalanDocument*			docToRegister)
{
	
	XalanDocument*	doc =
			m_xpathEnvSupport.getSourceDocument(urlString);

	if(doc == 0)
	{
		EntityResolver* const	theResolver = 
			m_parserLiaison.getEntityResolver();

		if (theResolver == 0)
		{
			const XSLTInputSource	inputSource(c_wstr(urlString));

			doc = parseXML(inputSource, docHandler, docToRegister);
		}
		else
		{
			const XalanAutoPtr<InputSource>		resolverInputSource =
				theResolver->resolveEntity(0, c_wstr(urlString));

			if (resolverInputSource.get() != 0)
			{
				doc = parseXML(*resolverInputSource.get(), docHandler, docToRegister);
			}
			else
			{
				const XSLTInputSource	inputSource(c_wstr(urlString));

				doc = parseXML(inputSource, docHandler, docToRegister);
			}
		}

		if (doc != 0)
		{
			m_xpathEnvSupport.setSourceDocument(urlString, doc);
		}
	}

	return doc;
}



XalanDocument*
XSLTEngineImpl::parseXML(
			const InputSource&	inputSource,
			DocumentHandler*	docHandler,
			XalanDocument*		docToRegister)
{
	if(0 != docHandler)
	{
		m_parserLiaison.parseXMLStream(inputSource, *docHandler);

		return docToRegister;
	}
	else
	{
		return m_parserLiaison.parseXMLStream(inputSource);
	}
}



Stylesheet*
XSLTEngineImpl::getStylesheetFromPIURL(
			const XalanDOMString&			xslURLString,
			XalanNode&						fragBase,
			const XalanDOMString&			xmlBaseIdent,
			bool							isRoot,
			StylesheetConstructionContext&	constructionContext)
{
	Stylesheet*				stylesheet = 0;

	XalanDOMString			stringHolder;

	XalanDOMString			localXSLURLString = trim(xslURLString);

	const unsigned int		fragIndex = indexOf(localXSLURLString, XalanUnicode::charNumberSign);

	const XalanDocument*	stylesheetDoc = 0;

	if(fragIndex == 0)
	{
		diag("Locating stylesheet from fragment identifier...");

		const XalanDOMString	fragID = substring(localXSLURLString, 1);

		const XalanElement*		nsNode = 0;

		const XalanNode::NodeType	theType = fragBase.getNodeType();

		if (theType == XalanNode::DOCUMENT_NODE)
		{
			const XalanDocument&	doc =
#if defined(XALAN_OLD_STYLE_CASTS)
				(const XalanDocument&)fragBase;
#else
				static_cast<const XalanDocument&>(fragBase);
#endif

			nsNode = doc.getDocumentElement(); 
		}
		else if	(theType == XalanNode::ELEMENT_NODE)
		{
#if defined(XALAN_OLD_STYLE_CASTS)
			nsNode = (const XalanElement*)&fragBase;
#else
			nsNode = static_cast<const XalanElement*>(&fragBase);
#endif
		}
		else
		{
			XalanNode* const	node = fragBase.getParentNode();

			if	(node->getNodeType() == XalanNode::ELEMENT_NODE) 
			{
#if defined(XALAN_OLD_STYLE_CASTS)
				nsNode = (const XalanElement*)&fragBase;
#else
				nsNode = static_cast<XalanElement*>(node);
#endif
			}
			else
			{
				error("Could not identify fragment: " + fragID);
			}
		}

		// Try a bunch of really ugly stuff to find the fragment.
		// What's the right way to do this?
		XalanDOMString	ds(XALAN_STATIC_UCODE_STRING("id("));

		ds += fragID;
		ds += XALAN_STATIC_UCODE_STRING(")");

		ElementPrefixResolverProxy		theProxy(nsNode, m_xpathEnvSupport, m_domSupport);

		XPathExecutionContextDefault	theExecutionContext(m_xpathEnvSupport,
															m_domSupport,
															m_xobjectFactory,
															&fragBase,
															0,
															&theProxy);

		const XObjectPtr	xobj(evalXPathStr(ds, theExecutionContext));
		assert(xobj.null() == false);

		NodeRefList		nl(xobj->nodeset());

		if(nl.getLength() == 0)
		{
			NodeRefList		theEmptyList;

			ds = XALAN_STATIC_UCODE_STRING("//*[@id='");
			ds += fragID;
			ds += XALAN_STATIC_UCODE_STRING("']");

			theExecutionContext.setContextNodeList(theEmptyList);

			const XObjectPtr	xobj(evalXPathStr(ds, theExecutionContext));
			assert(xobj.null() == false);

			nl = xobj->nodeset();

			if(nl.getLength() == 0)
			{
				ds = XALAN_STATIC_UCODE_STRING("//*[@name='");
				ds += fragID;
				ds += XALAN_STATIC_UCODE_STRING("']");

				theExecutionContext.setContextNodeList(theEmptyList);

				const XObjectPtr	xobj(evalXPathStr(ds, theExecutionContext));
				assert(xobj.null() == false);

				nl = xobj->nodeset();

				if(nl.getLength() == 0)
				{
					// Well, hell, maybe it's an XPath...
					theExecutionContext.setContextNodeList(theEmptyList);

					const XObjectPtr	xobj(evalXPathStr(fragID, theExecutionContext));
					assert(xobj.null() == false);

					nl = xobj->nodeset();
				}
			}
		}

		if(nl.getLength() == 0)
		{
			error("Could not find fragment: " + fragID);
		}

		XalanNode* const	frag = nl.item(0);

		if(XalanNode::ELEMENT_NODE == frag->getNodeType())
		{
			pushTime(frag);

			XalanAutoPtr<Stylesheet>	theGuard;

			if(isRoot)
			{
				StylesheetRoot* const	theLocalRoot =
					constructionContext.create(stringHolder);

				stylesheet = theLocalRoot;

				m_stylesheetRoot = theLocalRoot;
			}
			else
			{
#if defined(XALAN_OLD_STYLE_CASTS)
				stylesheet = constructionContext.create(*((StylesheetRoot*)m_stylesheetRoot), stringHolder);
#else
				stylesheet = constructionContext.create(*const_cast<StylesheetRoot*>(m_stylesheetRoot), stringHolder);
#endif

				theGuard.reset(stylesheet);
			}

			StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext);

			FormatterTreeWalker tw(stylesheetProcessor);

			tw.traverse(frag, frag->getParentNode());

			displayDuration(
					XalanDOMString(XALAN_STATIC_UCODE_STRING("Setup of ")) +
					localXSLURLString,
					frag);

			stylesheet->postConstruction(constructionContext);

			theGuard.release();
		}
		else
		{
			stylesheetDoc = 0;
			error("Node pointed to by fragment identifier was not an element: " + fragID);
		}
	}
	else
	{
		diag(XalanDOMString(XALAN_STATIC_UCODE_STRING("========= Parsing and preparing ")) +
				localXSLURLString +
				XALAN_STATIC_UCODE_STRING(" =========="));
		pushTime(&localXSLURLString);

		XalanAutoPtr<Stylesheet>	theGuard;

		const XalanDocument* const	theOwnerDocument =
				fragBase.getNodeType() == XalanNode::DOCUMENT_NODE ?
#if defined(XALAN_OLD_STYLE_CASTS)
				(const XalanDocument*)&fragBase :
#else
				static_cast<const XalanDocument*>(&fragBase) :
#endif
				fragBase.getOwnerDocument();
		assert(theOwnerDocument != 0);

		if (length(xmlBaseIdent) == 0)
		{
			localXSLURLString =
					URISupport::getURLStringFromString(
						localXSLURLString,
						m_xpathEnvSupport.findURIFromDoc(theOwnerDocument));
		}
		else
		{
			localXSLURLString =
					URISupport::getURLStringFromString(
						localXSLURLString,
						xmlBaseIdent);
		}

		if(isRoot)
		{
			StylesheetRoot* const	theLocalRoot =
					constructionContext.create(localXSLURLString);

			stylesheet = theLocalRoot;

			m_stylesheetRoot = theLocalRoot;
		}
		else
		{
#if defined(XALAN_OLD_STYLE_CASTS)
			stylesheet = new Stylesheet(*(StylesheetRoot*)m_stylesheetRoot, localXSLURLString, constructionContext);
#else
			stylesheet = new Stylesheet(*const_cast<StylesheetRoot*>(m_stylesheetRoot), localXSLURLString, constructionContext);
#endif

			theGuard.reset(stylesheet);
		}

		StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext);

		typedef StylesheetConstructionContext::URLAutoPtrType	URLAutoPtrType;

		URLAutoPtrType	xslURL(constructionContext.getURLFromString(localXSLURLString));

		XSLTInputSource		inputSource(xslURL->getURLText());

		m_parserLiaison.parseXMLStream(inputSource, stylesheetProcessor);

		stylesheet->postConstruction(constructionContext);

		theGuard.release();

		displayDuration("Parsing and init of " + localXSLURLString, &localXSLURLString);
	}

	return stylesheet;
}


//==========================================================
// SECTION: Stylesheet Tables
//==========================================================


double
XSLTEngineImpl::getXSLTVerSupported()
{
	return s_XSLTVerSupported;
}


//==========================================================
// SECTION: XSL directive handling functions
//==========================================================  



int
XSLTEngineImpl::getXSLToken(const XalanNode&	node) const
{
	int 	tok = -2;

	if(XalanNode::ELEMENT_NODE != node.getNodeType()) return tok;

	const XalanDOMString& 	ns = node.getNamespaceURI();

	if(equals(ns, s_XSLNameSpaceURL))
	{
		const XalanDOMString& 	localName =
			DOMServices::getLocalNameOfNode(node);

		const ElementKeysMapType::const_iterator		j =
						s_elementKeys.find(localName);

		if(j != s_elementKeys.end())
		{
			tok = (*j).second;
		}
	}
	else if(equals(ns, s_XSLT4JNameSpaceURL))
	{
		const XalanDOMString&	localName =
			DOMServices::getLocalNameOfNode(node);

		const ElementKeysMapType::const_iterator		j =
						s_XSLT4JElementKeys.find(localName);

		if(j != s_XSLT4JElementKeys.end())
		{
			tok = (*j).second;
		}
	}

	return tok;
}



void
XSLTEngineImpl::outputToResultTree(
			StylesheetExecutionContext&		executionContext,
			const XObject&					value)
{
	const XObject::eObjectType	type = value.getType();

	switch(type)
	{
	case XObject::eTypeBoolean:
	case XObject::eTypeNumber:
	case XObject::eTypeString:
		{
			const XalanDOMString&	s = value.str();

			characters(toCharArray(s), 0, length(s));
		}
		break;				

	case XObject::eTypeNodeSet:
		{
			const NodeRefListBase&	nl = value.nodeset();

			const unsigned int		nChildren = nl.getLength();

			for(unsigned int i = 0; i < nChildren; i++)
			{
				XalanNode*			pos = nl.item(i);
				assert(pos != 0);

				XalanNode* const	top = pos;

				while(0 != pos)
				{
					flushPending();

					XalanNode::NodeType		posNodeType = pos->getNodeType();

					cloneToResultTree(*pos, posNodeType, false, false, true);

					XalanNode*	nextNode = pos->getFirstChild();

					while(0 == nextNode)
					{
						if(XalanNode::ELEMENT_NODE == posNodeType)
						{
							endElement(c_wstr(pos->getNodeName()));
						}

						if(top == pos)
							break;

						nextNode = pos->getNextSibling();

						if(0 == nextNode)
						{
							pos = pos->getParentNode();
							assert(pos != 0);

							posNodeType = pos->getNodeType();

							if(top == pos)
							{
								if(XalanNode::ELEMENT_NODE == posNodeType)
								{
									endElement(c_wstr(pos->getNodeName()));
								}

								nextNode = 0;
								break;
							}
						}
					}

					pos = nextNode;

					if (pos != 0)
					{
						posNodeType = pos->getNodeType();
					}
				}
			}
		}
		break;
		
	case XObject::eTypeResultTreeFrag:
		outputResultTreeFragment(executionContext, value);
		break;

	case XObject::eTypeNull:
	case XObject::eTypeUnknown:
	case XObject::eUnknown:
	default:
		assert(0);
	}
}



const StylesheetRoot*
XSLTEngineImpl::getStylesheetRoot() const
{
	return m_stylesheetRoot;
}



void
XSLTEngineImpl::setStylesheetRoot(const StylesheetRoot*		theStylesheet)
{
	m_stylesheetRoot = theStylesheet;
}



void
XSLTEngineImpl::setExecutionContext(StylesheetExecutionContext*		theExecutionContext)
{
	m_executionContext = theExecutionContext;
}



//==========================================================
// SECTION: Diagnostic functions
//==========================================================

unsigned long
XSLTEngineImpl::getTraceListeners() const
{
	return m_traceListeners.size();
}



void
XSLTEngineImpl::addTraceListener(TraceListener* tl)
{
	if (tl != 0)
	{
		m_traceListeners.push_back(tl);
	}
}



void
XSLTEngineImpl::removeTraceListener(TraceListener*	tl)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::remove;
#endif

	const TraceListenerVectorType::iterator		i =
		remove(
			m_traceListeners.begin(),
			m_traceListeners.end(),
			tl);

	m_traceListeners.erase(i);
}



void
XSLTEngineImpl::fireGenerateEvent(const GenerateEvent&	ge)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::for_each;
#endif

	for_each(
		m_traceListeners.begin(),
		m_traceListeners.end(),
		TraceListener::TraceListenerGenerateFunctor(ge));
}



void
XSLTEngineImpl::fireSelectEvent(const SelectionEvent&	se)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::for_each;
#endif

	for_each(
		m_traceListeners.begin(),
		m_traceListeners.end(),
		TraceListener::TraceListenerSelectFunctor(se));
}



void
XSLTEngineImpl::fireTraceEvent(const TracerEvent& te)
{
#if !defined(XALAN_NO_NAMESPACES)
	using std::for_each;
#endif

	for_each(
		m_traceListeners.begin(),
		m_traceListeners.end(),
		TraceListener::TraceListenerTraceFunctor(te));
}



bool
XSLTEngineImpl::getTraceSelects() const
{
	return m_traceSelects;
}



void
XSLTEngineImpl::setTraceSelects(bool	b)
{
	m_traceSelects = b;
}



void
XSLTEngineImpl::message(
			const XalanDOMString&	msg,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode) const
{
	problem(msg, ProblemListener::eMESSAGE, sourceNode, styleNode);
}



void
XSLTEngineImpl::message(
			const XalanDOMString&		msg,
			const XalanNode*			sourceNode,
			const ElemTemplateElement*	styleNode) const
{
	problem(msg, ProblemListener::eMESSAGE, sourceNode, styleNode);
}



void
XSLTEngineImpl::message(
			const char*			msg,
			const XalanNode*	sourceNode,
			const XalanNode*	styleNode) const
{
	message(TranscodeFromLocalCodePage(msg), sourceNode, styleNode);
}



void
XSLTEngineImpl::problem(
			const XalanDOMString&				msg, 
			ProblemListener::eClassification	classification,
			const XalanNode*					sourceNode,
			const XalanNode*					styleNode) const
{
	const Locator* const	locator = getLocatorFromStack();

	const XalanDOMChar*		id = 0;

	XalanDOMString			uri;

	int						lineNumber = -1;
	int 					columnNumber = -1;

	if (locator != 0)
	{
		id = locator->getPublicId();

		if (id == 0)
		{
			id = locator->getSystemId();
		}

		if (id != 0)
		{
			uri = id;
		}

		lineNumber = locator->getLineNumber();
		columnNumber = locator->getColumnNumber();
	}

	if (m_problemListener != 0)
	{
		m_problemListener->problem(
					ProblemListener::eXSLPROCESSOR,
					classification,
					sourceNode,
					styleNode,
					msg,
					id,
					lineNumber,
					columnNumber);
	}

	if (classification == ProblemListener::eERROR)
	{
		throw XSLTProcessorException(msg, uri, lineNumber, columnNumber);
	}
}



void
XSLTEngineImpl::problem(
			const XalanDOMString&				msg, 
			ProblemListener::eClassification	classification,
			const XalanNode*					sourceNode,
			const ElemTemplateElement*			styleNode) const
{
	const XalanDOMChar*		id = 0;

	XalanDOMString			uri;

	int						lineNumber = -1;
	int 					columnNumber = -1;

	const Locator*			locator = getLocatorFromStack();

	if (locator == 0)
	{
		locator = styleNode->getLocator();
	}

	if (locator != 0)
	{
		id = locator->getPublicId();

		if (id == 0)
		{
			id = locator->getSystemId();
		}

		if (id != 0)
		{
			uri = id;
		}

		lineNumber = locator->getLineNumber();
		columnNumber = locator->getColumnNumber();
	}
	else if (styleNode != 0)
	{
		lineNumber = styleNode->getLineNumber();
		columnNumber = styleNode->getColumnNumber();

		uri = styleNode->getURI();
	}

	if (m_problemListener != 0)
	{
		m_problemListener->problem(
					ProblemListener::eXSLPROCESSOR,
					classification,
					styleNode,
					sourceNode,
					msg,
					id,
					lineNumber,
					columnNumber);
	}

	if (classification == ProblemListener::eERROR)
	{
		throw XSLTProcessorException(msg, uri, lineNumber, columnNumber);
	}
}



void
XSLTEngineImpl::warn(
			const XalanDOMString&	msg,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode) const
{
	problem(msg, ProblemListener::eWARNING, sourceNode, styleNode);
}



void
XSLTEngineImpl::warn(
			const XalanDOMString&		msg,
			const XalanNode*			sourceNode,
			const ElemTemplateElement*	styleNode) const
{
	problem(msg, ProblemListener::eWARNING, sourceNode, styleNode);
}



void
XSLTEngineImpl::warn(
			const char*			msg,
			const XalanNode*	sourceNode,
			const XalanNode*	styleNode) const
{
	warn(TranscodeFromLocalCodePage(msg), sourceNode, styleNode);
}



void
XSLTEngineImpl::error(
			const XalanDOMString&	msg,
			const XalanNode*		sourceNode,
			const XalanNode*		styleNode) const
{
	problem(msg, ProblemListener::eERROR, sourceNode, styleNode);
}



void
XSLTEngineImpl::error(
			const XalanDOMString&		msg,
			const XalanNode*			sourceNode,
			const ElemTemplateElement*	styleNode) const
{
	problem(msg, ProblemListener::eERROR, sourceNode, styleNode);
}



void
XSLTEngineImpl::error(
			const char*			msg,
			const XalanNode*	sourceNode,
			const XalanNode*	styleNode) const
{
	error(TranscodeFromLocalCodePage(msg), sourceNode, styleNode);
}



void
XSLTEngineImpl::pushTime(const void*	key)
{
	if(0 != key)
	{
		m_durationsTable[key] = clock();
	}
}



clock_t
XSLTEngineImpl::popDuration(const void*		key)
{
	clock_t 	clockTicksDuration = 0;

	if(0 != key)
	{
		const DurationsTableMapType::iterator	i =
				m_durationsTable.find(key);

		if (i != m_durationsTable.end())
		{
			clockTicksDuration = clock() - (*i).second;

			m_durationsTable.erase(i);
		}
	}

	return clockTicksDuration;
}



void
XSLTEngineImpl::displayDuration(
			const XalanDOMString&	info,
			const void*				key)
{
	if(0 != key)
	{
		const clock_t	theDuration = popDuration(key);

		if(0 != m_diagnosticsPrintWriter)
		{
			const double	millis = (double(theDuration) / CLOCKS_PER_SEC) * 1000.0L;

			XalanDOMString	msg(info);

			msg += XALAN_STATIC_UCODE_STRING(" took ");
			msg += DoubleToDOMString(millis);
			msg += XALAN_STATIC_UCODE_STRING(" milliseconds");

			m_diagnosticsPrintWriter->println(msg);
		}
	}
}



void
XSLTEngineImpl::setDiagnosticsOutput(PrintWriter*	pw)
{
	m_diagnosticsPrintWriter = pw;

	m_problemListener->setPrintWriter(pw);
}



void
XSLTEngineImpl::diag(const XalanDOMString& 	s) const
{
	if (0 != m_diagnosticsPrintWriter)
	{
		m_diagnosticsPrintWriter->println(s);
	}
}



void
XSLTEngineImpl::diag(const char*	s) const
{
	diag(TranscodeFromLocalCodePage(s));
}



void
XSLTEngineImpl::setQuietConflictWarnings(bool	b)
{
	m_quietConflictWarnings = b;
}



void
XSLTEngineImpl::setDocumentLocator(const Locator* const		/* locator */)
{
	// Do nothing for now
}



void
XSLTEngineImpl::traceSelect(
			const XalanElement& 	theTemplate,
			const NodeRefListBase&	nl) const
{
	if (0 != m_diagnosticsPrintWriter)
	{
		XalanDOMString	msg = theTemplate.getNodeName() + XalanDOMString(XALAN_STATIC_UCODE_STRING(": "));

		XalanAttr*		attr = theTemplate.getAttributeNode(Constants::ATTRNAME_SELECT);

		if(0 != attr)
		{
			msg += attr->getValue();
			msg += XALAN_STATIC_UCODE_STRING(", ");
			msg += LongToDOMString(nl.getLength());
			msg += XALAN_STATIC_UCODE_STRING(" selected");
		}
		else
		{
			msg += XALAN_STATIC_UCODE_STRING("*|text(), (default select), ");
			msg += LongToDOMString(nl.getLength());
			msg += XALAN_STATIC_UCODE_STRING(" selected");
		}

		attr = theTemplate.getAttributeNode(Constants::ATTRNAME_MODE);

		if(0 != attr)
		{
			msg += XalanDOMString(XALAN_STATIC_UCODE_STRING(", mode = ")) + attr->getValue();
		}

		m_diagnosticsPrintWriter->println(msg);
	}
}



void
XSLTEngineImpl::startDocument()
{
	assert(getFormatterListener() != 0);
	assert(m_executionContext != 0);

	if (getHasPendingStartDocument() == false)
	{
		m_resultNamespacesStack.pushContext();

		setHasPendingStartDocument(true);

		setMustFlushPendingStartDocument(false);
	}
	else if (getMustFlushPendingStartDocument() == true)
	{
		getFormatterListener()->startDocument();

		if(getTraceListeners() > 0)
		{
			const GenerateEvent		ge(GenerateEvent::EVENTTYPE_STARTDOCUMENT);

			fireGenerateEvent(ge);
		}

		// Reset this, but leave getMustFlushPendingStartDocument() alone,
		// since it will still be needed.
		setHasPendingStartDocument(false);
	}
}



void
XSLTEngineImpl::endDocument()
{
	assert(getFormatterListener() != 0);
	assert(m_executionContext != 0);

	setMustFlushPendingStartDocument(true);

	flushPending();

	getFormatterListener()->endDocument();

	if(getTraceListeners() > 0)
	{
		const GenerateEvent		ge(GenerateEvent::EVENTTYPE_ENDDOCUMENT);

		fireGenerateEvent(ge);
	}

	m_resultNamespacesStack.popContext();

	assert(m_resultNamespacesStack.size() == 0);
}



void
XSLTEngineImpl::addResultNamespaceDecl(
			const XalanDOMString&	prefix, 
	        const XalanDOMString&	namespaceVal)
{
	m_resultNamespacesStack.addDeclaration(prefix, namespaceVal);
}



void
XSLTEngineImpl::addResultAttribute(
			AttributeListImpl&	attList,
			const XalanDOMString&	aname,
			const XalanDOMString&	value)
{
	bool	fExcludeAttribute = false;

	if (equals(aname, DOMServices::s_XMLNamespace)) 
	{
		// OK, we're adding a default namespace declaration.  So see if the length
		// of the namespace is 0.  If it's not, go ahead and add the declaration.
		// If it's not, it means we're "turning off" the previous default
		// declaration.

		const XalanDOMString* const		currentDefaultNamespace =
					getNamespaceForPrefix(s_emptyString);

		// Note that we use an empty string for the prefix, instead of "xmlns", since the
		// prefix really is "".
		if (length(value) != 0)
		{
			if (currentDefaultNamespace != 0 &&
				equals(*currentDefaultNamespace, value) == true)
			{
				fExcludeAttribute = true;
			}
			else
			{
				addResultNamespaceDecl(s_emptyString, value);
			}
		}
		else
		{
			// OK, we're turning of the previous default namespace declaration.
			// Check to see if there is one, and if there isn't, don't add
			// the namespace declaration _and_ don't add the attribute.
			if (currentDefaultNamespace != 0 && length(*currentDefaultNamespace) != 0)
			{
				addResultNamespaceDecl(s_emptyString, value);
			}
			else
			{
				fExcludeAttribute = true;
			}
		}
	}
	else if (startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator) == true)
	{
		assert(m_executionContext != 0);

		StylesheetExecutionContext::GetAndReleaseCachedString	prefixGuard(*m_executionContext);

		XalanDOMString&		prefix = prefixGuard.get();

		prefix = substring(aname, DOMServices::s_XMLNamespaceWithSeparatorLength);

		addResultNamespaceDecl(prefix, value);
	}

	if (fExcludeAttribute == false)
	{
		attList.addAttribute(
			c_wstr(aname),
			c_wstr(Constants::ATTRTYPE_CDATA),
			c_wstr(value));
	}
}



bool
XSLTEngineImpl::pendingAttributesHasDefaultNS() const
{
	const AttributeListImpl&	thePendingAttributes =
		getPendingAttributes();

	const unsigned int	n = thePendingAttributes.getLength();

	for(unsigned int i = 0; i < n; i++)
	{
		if(equals(thePendingAttributes.getName(i),
				  DOMServices::s_XMLNamespace) == true)
		{
			return true;
		}
	}

	return false;
}



void
XSLTEngineImpl::flushPending()
{
	if(getHasPendingStartDocument() == true && 0 != length(getPendingElementName()))
	{
		assert(getFormatterListener() != 0);
		assert(m_executionContext != 0);

		if (m_stylesheetRoot->isOutputMethodSet() == false)
		{
			if (equalsIgnoreCaseASCII(getPendingElementName(),
								 Constants::ELEMNAME_HTML_STRING) == true &&
				pendingAttributesHasDefaultNS() == false)
			{
				if (getFormatterListener()->getOutputFormat() == FormatterListener::OUTPUT_METHOD_XML)
				{
					// Yuck!!! Ugly hack to switch to HTML on-the-fly.
					FormatterToXML* const	theFormatter =
#if defined(XALAN_OLD_STYLE_CASTS)
						(FormatterToXML*)getFormatterListener();
#else
						static_cast<FormatterToXML*>(getFormatterListener());
#endif

					setFormatterListenerImpl(
						m_executionContext->createFormatterToHTML(
							*theFormatter->getWriter(),
							theFormatter->getEncoding(),
							theFormatter->getMediaType(),
							theFormatter->getDoctypeSystem(),
							theFormatter->getDoctypePublic(),
							true,	// indent
							theFormatter->getIndent() > 0 ? theFormatter->getIndent() :
											StylesheetExecutionContext::eDefaultHTMLIndentAmount));
				}
			}
		}
	}

	XalanDOMString&		thePendingElementName = getPendingElementNameImpl();

	if(getHasPendingStartDocument() == true && getMustFlushPendingStartDocument() == true)
	{
		startDocument();
	}

	if(0 != length(thePendingElementName) && getMustFlushPendingStartDocument() == true)
	{
		assert(getFormatterListener() != 0);
		assert(m_executionContext != 0);

		m_cdataStack.push_back(isCDataResultElem(thePendingElementName) ? true : false);

		AttributeListImpl&	thePendingAttributes =
				getPendingAttributesImpl();

		getFormatterListener()->startElement(c_wstr(thePendingElementName), thePendingAttributes);

		if(getTraceListeners() > 0)
		{
			const GenerateEvent		ge(
				GenerateEvent::EVENTTYPE_STARTELEMENT,
				thePendingElementName,
				&thePendingAttributes);

			fireGenerateEvent(ge);
		}

		thePendingAttributes.clear();

		clear(thePendingElementName);
	}
}



void
XSLTEngineImpl::startElement(const XMLCh* const	name)
{
	assert(getFormatterListener() != 0);
	assert(name != 0);

	flushPending();

	m_resultNamespacesStack.pushContext();

	setPendingElementName(name);

	setMustFlushPendingStartDocument(true);
}



void
XSLTEngineImpl::startElement(
			const XMLCh* const	name,
			AttributeList&		atts)
{
	assert(getFormatterListener() != 0);
	assert(name != 0);

	flushPending();

	const unsigned int	nAtts = atts.getLength();

	assert(m_outputContextStack.size() > 0);

	AttributeListImpl&	thePendingAttributes =
		getPendingAttributesImpl();

	thePendingAttributes.clear();

	for(unsigned int i = 0; i < nAtts; i++)
	{
		thePendingAttributes.addAttribute(
			atts.getName(i),
			atts.getType(i),
			atts.getValue(i));
	}

	m_resultNamespacesStack.pushContext();

	setPendingElementName(name);
}



void
XSLTEngineImpl::endElement(const XMLCh* const 	name)
{
	assert(getFormatterListener() != 0);
	assert(name != 0);

	flushPending();

	getFormatterListener()->endElement(name);

	if(getTraceListeners() > 0)
	{
		const GenerateEvent		ge(GenerateEvent::EVENTTYPE_ENDELEMENT, name);

		fireGenerateEvent(ge);
	}

	m_resultNamespacesStack.popContext();

	if(m_stylesheetRoot->hasCDATASectionElements() == true)
	{
		m_cdataStack.pop_back();
	}
}



void
XSLTEngineImpl::characters(
			const XMLCh* const	ch,
			const unsigned int 	length)
{
	characters(ch,
			   0,
			   length);
}



void
XSLTEngineImpl::characters(
			const XMLCh* const	ch,
			const unsigned int	start,
			const unsigned int 	length)
{
	assert(getFormatterListener() != 0);
	assert(ch != 0);

	doFlushPending();

	if(generateCDATASection() == true)
	{
		getFormatterListener()->cdata(ch + start, length);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(ch, start, length, true);
		}
	}
	else
	{
		getFormatterListener()->characters(ch + start, length);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(ch, start, length, false);
		}
	}
}



void
XSLTEngineImpl::characters(const XalanNode&		node)
{
	assert(getFormatterListener() != 0);

	doFlushPending();

	if(generateCDATASection() == true)
	{
		DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::cdata);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(node, true);
		}
	}
	else
	{
		DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::characters);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(node, false);
		}
	}
}



void
XSLTEngineImpl::characters(const XObjectPtr&	xobject)
{
	assert(getFormatterListener() != 0);
	assert(xobject.null() == false);

	doFlushPending();

	if(generateCDATASection() == true)
	{
		xobject->str(*getFormatterListener(), &FormatterListener::cdata);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(xobject, true);
		}
	}
	else
	{
		xobject->str(*getFormatterListener(), &FormatterListener::characters);

		if(getTraceListeners() > 0)
		{
			fireCharacterGenerateEvent(xobject, false);
		}
	}
}



void 
XSLTEngineImpl::charactersRaw(
			const XMLCh* const	ch,
			const unsigned int	start,
			const unsigned int	length)
{
	assert(ch != 0);

	doFlushPending();

	getFormatterListener()->charactersRaw(ch, length);

	if(getTraceListeners() > 0)
	{
		fireCharacterGenerateEvent(ch, start, length, false);
	}
}



void
XSLTEngineImpl::charactersRaw(const XalanNode&	node)
{
	doFlushPending();

	DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::charactersRaw);

	if(getTraceListeners() > 0)
	{
		fireCharacterGenerateEvent(node, false);
	}
}



void
XSLTEngineImpl::charactersRaw(const XObjectPtr&		xobject)
{
	doFlushPending();

	xobject->str(*getFormatterListener(), &FormatterListener::charactersRaw);

	if(getTraceListeners() > 0)
	{
		fireCharacterGenerateEvent(xobject, false);
	}
}



void
XSLTEngineImpl::resetDocument()
{
	assert(getFormatterListener() != 0);

	flushPending();
	
	getFormatterListener()->resetDocument();
}



void
XSLTEngineImpl::ignorableWhitespace(
			const XMLCh* const	ch,
			const unsigned int 	length)
{
	assert(getFormatterListener() != 0);
	assert(ch != 0);

	doFlushPending();

	getFormatterListener()->ignorableWhitespace(ch, length);

	if(getTraceListeners() > 0)
	{
		GenerateEvent ge(GenerateEvent::EVENTTYPE_IGNORABLEWHITESPACE,
					ch, 0, length);

		fireGenerateEvent(ge);
	}
}



void
XSLTEngineImpl::processingInstruction(
			const XMLCh* const	target,
			const XMLCh* const	data)
{
	assert(getFormatterListener() != 0);
	assert(target != 0);
	assert(data != 0);

	doFlushPending();

	getFormatterListener()->processingInstruction(target, data);

	if(getTraceListeners() > 0)
	{
		GenerateEvent ge(
				GenerateEvent::EVENTTYPE_PI,
                target,
				data);

		fireGenerateEvent(ge);
	}
}



void
XSLTEngineImpl::comment(const XMLCh* const	data)
{
	assert(getFormatterListener() != 0);
	assert(data != 0);

	doFlushPending();

	getFormatterListener()->comment(data);

	if(getTraceListeners() > 0)
	{
		GenerateEvent ge(GenerateEvent::EVENTTYPE_COMMENT,
                                          data);
		fireGenerateEvent(ge);
	}
}


void
XSLTEngineImpl::entityReference(const XMLCh* const	name)
{
	assert(getFormatterListener() != 0);
	assert(name != 0);

	doFlushPending();

	getFormatterListener()->entityReference(name);

	if(getTraceListeners() > 0)
	{
		GenerateEvent ge(GenerateEvent::EVENTTYPE_ENTITYREF,
                                          name);

		fireGenerateEvent(ge);
	}
}



void
XSLTEngineImpl::cdata(
			const XMLCh* const	ch,
			const unsigned int 	start,
			const unsigned int 	length)
{
	assert(getFormatterListener() != 0);
	assert(ch != 0);

	setMustFlushPendingStartDocument(true);

	flushPending();

	if(m_stylesheetRoot->hasCDATASectionElements() == true &&
	   0 != m_cdataStack.size())
	{
		getFormatterListener()->cdata(ch, length);

		if(getTraceListeners() > 0)
		{
			GenerateEvent ge(GenerateEvent::EVENTTYPE_CDATA, ch, start,
					length);

			fireGenerateEvent(ge);
		}
	}
	else
	{
		getFormatterListener()->characters(ch, length);

		if(getTraceListeners() > 0)
		{
			GenerateEvent ge(GenerateEvent::EVENTTYPE_CHARACTERS, ch,
					start, length);

			fireGenerateEvent(ge);
		}
	}
}



void
XSLTEngineImpl::cloneToResultTree(
			XalanNode&				node,
			XalanNode::NodeType		nodeType,
			bool					isLiteral,
			bool					overrideStrip,
			bool					shouldCloneAttributes)
{
	assert(nodeType == node.getNodeType());

	switch(nodeType)
	{
	case XalanNode::TEXT_NODE:
		{
			bool	stripWhiteSpace = false;

			// If stripWhiteSpace is false, then take this as an override and 
			// just preserve the space, otherwise use the XSL whitespace rules.
			if(!overrideStrip)
			{
				stripWhiteSpace = isLiteral ? true : false;
			  // was: stripWhiteSpace = isLiteral ? true : shouldStripSourceNode(node);
			}

			const XalanText& 	tx =
#if defined(XALAN_OLD_STYLE_CASTS)
				(const XalanText&)node;
#else
				static_cast<const XalanText&>(node);
#endif

			const bool	isIgnorableWhitespace = tx.isIgnorableWhitespace();

			if(stripWhiteSpace == false || isIgnorableWhitespace == false)
			{
				assert(tx.getParentNode() == 0 ||
					   tx.getParentNode()->getNodeType() != XalanNode::DOCUMENT_NODE);

				const XalanDOMString&	data = tx.getData();

				if(0 != length(data))
				{
					if(isIgnorableWhitespace == true)
					{
						ignorableWhitespace(toCharArray(data), length(data));
					}
					else
					{
						characters(toCharArray(data), 0, length(data));
					}
				}
			}			
		}
		break;

	case XalanNode::ELEMENT_NODE:
		startElement(c_wstr(node.getNodeName()));

		if(shouldCloneAttributes == true)
		{
			copyAttributesToAttList(
									m_stylesheetRoot,
									node,
									getPendingAttributesImpl());

			copyNamespaceAttributes(node);
		}
		break;

	case XalanNode::CDATA_SECTION_NODE:
		{
			const XalanDOMString& 	data = node.getNodeValue();

			cdata(toCharArray(data), 0, length(data));
		}
		break;

	case XalanNode::ATTRIBUTE_NODE:
		addResultAttribute(
				getPendingAttributesImpl(),
#if defined(XALAN_OLD_STYLE_CASTS)
				DOMServices::getNameOfNode((const XalanAttr&)node),
#else
				DOMServices::getNameOfNode(static_cast<const XalanAttr&>(node)),
#endif
				node.getNodeValue());
		break;

	case XalanNode::COMMENT_NODE:
		comment(c_wstr(node.getNodeValue()));
		break;

	case XalanNode::DOCUMENT_FRAGMENT_NODE:
		error("No clone of a document fragment!");
		break;
	
	case XalanNode::ENTITY_REFERENCE_NODE:
		entityReference(c_wstr(node.getNodeName()));
		break;

	case XalanNode::PROCESSING_INSTRUCTION_NODE:
		processingInstruction(
				c_wstr(node.getNodeName()),
				c_wstr(node.getNodeValue()));
		break;

	// Can't really do this, but we won't throw an error so that copy-of will
	// work
	case XalanNode::DOCUMENT_NODE:
	case XalanNode::DOCUMENT_TYPE_NODE:
	break;

	default:
		error("Cannot create item in result tree: " + node.getNodeName());
	break;

	}
}



void
XSLTEngineImpl::outputResultTreeFragment(
			StylesheetExecutionContext&		executionContext,
			const XObject&					theTree)
{
	const ResultTreeFragBase&	docFrag = theTree.rtree(executionContext);

	const XalanNodeList* const	nl = docFrag.getChildNodes();
	assert(nl != 0);

	const unsigned int			nChildren = nl->getLength();

	for(unsigned int i = 0; i < nChildren; i++)
	{
		XalanNode*				pos = nl->item(i);
		assert(pos != 0);

		XalanNode::NodeType		posNodeType = pos->getNodeType();

		XalanNode* const		top = pos;

		while(0 != pos)
		{
			flushPending();

			cloneToResultTree(*pos, posNodeType, false, false, true);

			XalanNode*	nextNode = pos->getFirstChild();

			while(0 == nextNode)
			{
				if(XalanNode::ELEMENT_NODE == posNodeType)
				{
					endElement(c_wstr(pos->getNodeName()));
				}

				if(top == pos)
					break;

				nextNode = pos->getNextSibling();

				if(0 == nextNode)
				{
					pos = pos->getParentNode();

					if(0 == pos)
					{
						nextNode = 0;

						break;
					}
					else
					{
						assert(0 != pos);

						posNodeType = pos->getNodeType();

						if(top == pos)
						{
							if(XalanNode::ELEMENT_NODE == posNodeType)
							{
								endElement(c_wstr(pos->getNodeName()));
							}

							nextNode = 0;

							break;
						}
					}
				}
			}

			pos = nextNode;

			if (pos != 0)
			{
				posNodeType = pos->getNodeType();
			}
		}
	}
}



bool
XSLTEngineImpl::isCDataResultElem(const XalanDOMString&		elementName) const
{
	assert(m_executionContext != 0);

	if(m_stylesheetRoot->hasCDATASectionElements() == false)
	{
		return false;
	}
	else
	{
		bool	fResult = false;

		const unsigned int	indexOfNSSep = indexOf(elementName, XalanUnicode::charColon);

		if(indexOfNSSep == length(elementName))
		{
			fResult = m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(s_emptyString, elementName));
		}
		else
		{
			typedef StylesheetExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;

			GetAndReleaseCachedString	elemLocalNameGuard(*m_executionContext);
			GetAndReleaseCachedString	prefixGuard(*m_executionContext);

			XalanDOMString&		elemLocalName = elemLocalNameGuard.get();
			XalanDOMString&		prefix = prefixGuard.get();

			substring(elementName, prefix, 0, indexOfNSSep);
			substring(elementName, elemLocalName, indexOfNSSep + 1);

			if(equals(prefix, DOMServices::s_XMLString))
			{
				fResult =
					m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(DOMServices::s_XMLNamespaceURI, elementName));
			}
			else
			{
				const XalanDOMString* const		elemNS =
					getResultNamespaceForPrefix(prefix);

				if(elemNS == 0)
				{
					error("Prefix must resolve to a namespace: " + prefix);
				}
				else
				{
					fResult =
						m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(*elemNS, elementName));
				}
			}
		}

		return fResult;
	}
}
	


const XalanDOMString*
XSLTEngineImpl::getResultNamespaceForPrefix(const XalanDOMString&	prefix) const
{
	return m_resultNamespacesStack.getNamespaceForPrefix(prefix);
}
  


const XalanDOMString*
XSLTEngineImpl::getResultPrefixForNamespace(const XalanDOMString&	theNamespace) const
{
	return m_resultNamespacesStack.getPrefixForNamespace(theNamespace);
}



inline bool
isPrefixUsed(
			const XalanDOMString&	thePrefix,
			unsigned int			thePrefixLength,
			const XalanDOMChar*		theName,
			unsigned int			theNameLength)
{
	assert(thePrefixLength != 0);

	// The name must be greater than the length of the prefix + 1, since
	// there must be a ':' to separate the prefix from the local part...
	if (theNameLength <= thePrefixLength + 1)
	{
		return false;
	}
	else
	{
		assert(theName != 0);

		const unsigned int	theIndex = indexOf(
			theName,
			XalanUnicode::charColon);

		// OK, if the index of the ':' is the same as the length of the prefix,
		// and theElementName starts with thePrefix, then the prefix is in use.
		if (theIndex == thePrefixLength &&
			startsWith(theName, thePrefix) == true)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}



inline bool
isPrefixUsed(
			const XalanDOMString&	thePrefix,
			unsigned int			thePrefixLength,
			const XalanDOMString&	theName)
{
	return isPrefixUsed(thePrefix, thePrefixLength, c_wstr(theName), length(theName));
}



inline bool
isPrefixUsedOrDeclared(
			const XalanDOMString&	thePrefix,
			unsigned int			thePrefixLength,
			const XalanDOMChar*		theName,
			unsigned int			theNameLength)
{
	if (isPrefixUsed(thePrefix, thePrefixLength, theName, theNameLength) == true)
	{
		return true;
	}
	else
	{
		const unsigned int	theDeclarationLength =
			thePrefixLength + DOMServices::s_XMLNamespaceWithSeparatorLength;

		// If this is a namespace declaration for this prefix, then all of
		// these conditions must be true...
		if (theDeclarationLength == theNameLength &&
			startsWith(theName, DOMServices::s_XMLNamespaceWithSeparator) == true &&
			endsWith(theName, c_wstr(thePrefix)) == true)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}



inline bool
isPendingAttributePrefix(
			const AttributeList&		thePendingAttributes,
			const XalanDOMString&		thePrefix,
			unsigned int				thePrefixLength)
{
	const unsigned int	thePendingAttributesCount =
				thePendingAttributes.getLength();

	if (thePendingAttributesCount == 0)
	{
		// No attributes, no problem...
		return false;
	}
	else
	{
		bool	fResult = false;

		// Check each attribute...
		for (unsigned int i = 0; i < thePendingAttributesCount; ++i)
		{
			const XalanDOMChar* const	thePendingAttributeName =
							thePendingAttributes.getName(i);
			assert(thePendingAttributeName != 0);

			if (isPrefixUsedOrDeclared(
					thePrefix,
					thePrefixLength,
					thePendingAttributeName,
					length(thePendingAttributeName)) == true)
			{
				fResult = true;

				break;
			}
		}

		return fResult;
	}
}



bool
XSLTEngineImpl::isPendingResultPrefix(const XalanDOMString&		thePrefix) const
{
	const unsigned int	thePrefixLength = length(thePrefix);
	assert(thePrefixLength > 0);

	// The element name must be greater than the length of the prefix + 1, since
	// there must be a ':' to separate the prefix from the local part...
	if (isPrefixUsed(thePrefix, thePrefixLength, getPendingElementName()) == true)
	{
		return true;
	}
	else
	{
		// The element is not using the prefix, so check the
		// pending attributes...
		return isPendingAttributePrefix(
						getPendingAttributes(),
						thePrefix,
						thePrefixLength);
	}
}



void
XSLTEngineImpl::addResultNamespace(
			const XalanNode&	theNode,
			AttributeListImpl&	thePendingAttributes,
			bool				fOnlyIfPrefixNotPresent)
{
	assert(theNode.getNodeType() == XalanNode::ATTRIBUTE_NODE);

	const XalanDOMString& 	aname = theNode.getNodeName();

	const bool	isPrefix = startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator);

	const XalanDOMString 	prefix = isPrefix == true ?
			substring(aname, DOMServices::s_XMLNamespaceWithSeparatorLength) : XalanDOMString();

	if (equals(aname, DOMServices::s_XMLNamespace) || isPrefix) 
	{
		if (fOnlyIfPrefixNotPresent == true)
		{
			if (m_resultNamespacesStack.prefixIsPresentLocal(prefix) == false)
			{
				const XalanDOMString* const 	desturi = getResultNamespaceForPrefix(prefix);
				const XalanDOMString&			srcURI = theNode.getNodeValue();

				if(desturi == 0 || equals(srcURI, *desturi) == false)
				{
					addResultAttribute(thePendingAttributes, aname, srcURI);
				}
			}
		}
		else
		{
			const XalanDOMString* const 	desturi = getResultNamespaceForPrefix(prefix);
			const XalanDOMString&			srcURI = theNode.getNodeValue();

			if(desturi == 0 || equals(srcURI, *desturi) == false)
			{
				addResultAttribute(thePendingAttributes, aname, srcURI);
			}
		}
	}
}



void
XSLTEngineImpl::copyNamespaceAttributes(const XalanNode&	src) 
{
	const XalanNode*	parent = &src;

	while (parent != 0 &&
		   parent->getNodeType() == XalanNode::ELEMENT_NODE) 
	{
		const XalanNamedNodeMap* const	nnm =
				parent->getAttributes();
		assert(nnm != 0);

		const unsigned int	nAttrs = nnm->getLength();

		assert(m_outputContextStack.size() > 0);

		AttributeListImpl&	thePendingAttributes =
				getPendingAttributesImpl();

		for (unsigned int i = 0;  i < nAttrs; i++) 
		{
			const XalanNode* const	attr = nnm->item(i);
			assert(attr != 0);

			addResultNamespace(*attr, thePendingAttributes, true);
		}

		parent = parent->getParentNode();
	}
}



const XObjectPtr
XSLTEngineImpl::evalXPathStr(
			const XalanDOMString&	str,
			XPathExecutionContext&	executionContext)
{
	assert(executionContext.getPrefixResolver() != 0);

	XPath* const	theXPath = m_xpathFactory.create();

	XPathGuard	theGuard(m_xpathFactory,
						 theXPath);

    m_xpathProcessor->initXPath(*theXPath,
								str,
								*executionContext.getPrefixResolver(),
								getLocatorFromStack());

    return theXPath->execute(executionContext.getCurrentNode(),
							 *executionContext.getPrefixResolver(),
							 executionContext);
}



const XObjectPtr
XSLTEngineImpl::evalXPathStr(
			const XalanDOMString&	str,
			XalanNode*				contextNode,
			const PrefixResolver&	prefixResolver,
			XPathExecutionContext&	executionContext)
{
	XPath* const	theXPath = m_xpathFactory.create();

	XPathGuard	theGuard(m_xpathFactory,
						 theXPath);

    m_xpathProcessor->initXPath(*theXPath,
								str,
								prefixResolver,
								getLocatorFromStack());

    return theXPath->execute(contextNode, prefixResolver, executionContext);
}



const XObjectPtr
XSLTEngineImpl::evalXPathStr(
			const XalanDOMString&	str,
			XalanNode*				contextNode,
			const XalanElement&		prefixResolver,
			XPathExecutionContext&	executionContext)
{
	ElementPrefixResolverProxy	theProxy(&prefixResolver,
										 m_xpathEnvSupport,
										 m_domSupport);

	return evalXPathStr(str, contextNode, theProxy, executionContext);
}




/**
 * Create and initialize an xpath and return it.
 */
const XPath*
XSLTEngineImpl::createMatchPattern(
			const XalanDOMString&	str,
			const PrefixResolver&	resolver)
{
	XPath* const	xpath = m_xpathFactory.create();

	m_xpathProcessor->initMatchPattern(*xpath, str, resolver, getLocatorFromStack());

	return xpath;
}



void
XSLTEngineImpl::returnXPath(const XPath*	xpath)
{
	m_xpathFactory.returnObject(xpath);
}



inline void
XSLTEngineImpl::copyAttributeToTarget(
			const XalanDOMString&	attrName,
			const XalanDOMString&	attrValue,
			AttributeListImpl&		attrList)
{
	// TODO: Find out about empty attribute template expression handling.
	if(0 != length(attrValue))
	{
		addResultAttribute(attrList, attrName, attrValue);
	}
}



void
XSLTEngineImpl::copyAttributesToAttList(
			const Stylesheet* 	stylesheetTree,
			const XalanNode& 	node,
			AttributeListImpl&	attList)
{
	assert(m_stylesheetRoot != 0);
	assert(stylesheetTree != 0);

	const XalanNamedNodeMap* const	attributes =
		node.getAttributes();

	if (attributes != 0)
	{
		const unsigned int	nAttributes = attributes->getLength();

		for(unsigned int i = 0; i < nAttributes; ++i)  
		{	
			const XalanNode* const 	attr = attributes->item(i);
			assert(attr != 0);

			copyAttributeToTarget(
				attr->getNodeName(),
				attr->getNodeValue(),
				attList);
		}
	}
}



bool
XSLTEngineImpl::shouldStripSourceNode(
			XPathExecutionContext&	executionContext,
			const XalanNode&		textNode) const
{
	if (m_stylesheetRoot == 0)
	{
		return false;
	}
	else
	{
		bool	strip = false; // return value

		if((m_stylesheetRoot->getWhitespacePreservingElements().size() > 0 ||
			m_stylesheetRoot->getWhitespaceStrippingElements().size() > 0))
		{
			const XalanNode::NodeType	type = textNode.getNodeType();

			if(XalanNode::TEXT_NODE == type || XalanNode::CDATA_SECTION_NODE == type)
			{
				const XalanText& 	theTextNode =
#if defined(XALAN_OLD_STYLE_CASTS)
						(const XalanText&)textNode;
#else
						static_cast<const XalanText&>(textNode);
#endif

				if(!theTextNode.isIgnorableWhitespace())
				{
					const XalanDOMString&	data = theTextNode.getData();

					if(0 == length(data))
					{
						return true;
					}
					else if(!isXMLWhitespace(data))
					{
						return false;
					}
				}

				XalanNode*	parent = DOMServices::getParentOfNode(textNode);

				while(0 != parent)
				{
					if(parent->getNodeType() == XalanNode::ELEMENT_NODE)
					{
						const XalanElement*	const	parentElem =
#if defined(XALAN_OLD_STYLE_CASTS)
							(const XalanElement*)parent;
#else
							static_cast<const XalanElement*>(parent);
#endif

						XPath::eMatchScore	highPreserveScore = XPath::eMatchScoreNone;
						XPath::eMatchScore	highStripScore = XPath::eMatchScoreNone;

						ElementPrefixResolverProxy	theProxy(parentElem, m_xpathEnvSupport, m_domSupport);

						{
							// $$$ ToDo:  All of this should be moved into a member of
							// Stylesheet, so as not to expose these two data members...
							typedef Stylesheet::XPathVectorType		XPathVectorType;

							const XPathVectorType&	theElements =
								m_stylesheetRoot->getWhitespacePreservingElements();

							const XPathVectorType::size_type	nTests =
								theElements.size();

							for(XPathVectorType::size_type i = 0; i < nTests; i++)
							{
								const XPath* const	matchPat = theElements[i];
								assert(matchPat != 0);

								const XPath::eMatchScore	score = matchPat->getMatchScore(parent, theProxy, executionContext);

								if(score > highPreserveScore)
									highPreserveScore = score;
							}
						}

						{
							typedef Stylesheet::XPathVectorType		XPathVectorType;

							const XPathVectorType&	theElements =
								m_stylesheetRoot->getWhitespaceStrippingElements();

							const XPathVectorType::size_type	nTests =
								theElements.size();

							for(XPathVectorType::size_type i = 0; i < nTests; i++)
							{
								const XPath* const	matchPat =
									theElements[i];
								assert(matchPat != 0);

								const XPath::eMatchScore	score = matchPat->getMatchScore(parent, theProxy, executionContext);

								if(score > highStripScore)
									highStripScore = score;
							}
						}

						if(highPreserveScore > XPath::eMatchScoreNone ||
						   highStripScore > XPath::eMatchScoreNone)
						{
							if(highPreserveScore > highStripScore)
							{
								strip = false;
							}
							else if(highStripScore > highPreserveScore)
							{
								strip = true;
							}
							else
							{
								warn("Match conflict between xsl:strip-space and xsl:preserve-space");
							}
							break;
						}
					}

					parent = parent->getParentNode();
				}
			}
		}

		return strip;
	}
}



XMLParserLiaison&
XSLTEngineImpl::getXMLParserLiaison() const
{
	return m_parserLiaison;
}



const XalanDOMString
XSLTEngineImpl::getUniqueNamespaceValue()
{
	XalanDOMString	theResult;

	getUniqueNamespaceValue(theResult);

	return theResult;
}



void
XSLTEngineImpl::getUniqueNamespaceValue(XalanDOMString&		theValue)
{
	append(theValue, s_uniqueNamespacePrefix);

	UnsignedLongToDOMString(m_uniqueNSValue++, theValue);
}



XalanDocument*
XSLTEngineImpl::getDOMFactory() const
{
	if(m_domResultTreeFactory == 0)
	{
#if defined(XALAN_NO_MUTABLE)
		((XSLTEngineImpl*)this)->m_domResultTreeFactory = m_parserLiaison.createDOMFactory();
#else
		m_domResultTreeFactory = m_parserLiaison.createDOMFactory();
#endif
	}

	return m_domResultTreeFactory;
}



void
XSLTEngineImpl::setStylesheetParam(
			const XalanDOMString&	theName,
			const XalanDOMString&	expression)
{
	const XalanQNameByValue		qname(theName, 0, m_xpathEnvSupport, m_domSupport);

	m_topLevelParams.push_back(ParamVectorType::value_type(qname, expression));
}



void
XSLTEngineImpl::setStylesheetParam(
			const XalanDOMString&	theName,
			XObjectPtr				theValue)
{
	const XalanQNameByValue		qname(theName, 0, m_xpathEnvSupport, m_domSupport);

	m_topLevelParams.push_back(ParamVectorType::value_type(qname, theValue));
}



void
XSLTEngineImpl::resolveTopLevelParams(StylesheetExecutionContext&	executionContext)
{
	executionContext.pushTopLevelVariables(m_topLevelParams);
}



FormatterListener*
XSLTEngineImpl::getFormatterListener() const
{
	return getFormatterListenerImpl();
}



void
XSLTEngineImpl::setFormatterListener(FormatterListener*		flistener)
{
	if (getHasPendingStartDocument() == true && getFormatterListener() != 0)
	{
		setMustFlushPendingStartDocument(true);

		flushPending();
	}

	setFormatterListenerImpl(flistener);
}



void
XSLTEngineImpl::fireCharacterGenerateEvent(
			const XalanNode&	theNode,
			bool				isCDATA)
{
	fireCharacterGenerateEvent(DOMServices::getNodeData(theNode), isCDATA);
}



void
XSLTEngineImpl::fireCharacterGenerateEvent(
			const XObjectPtr&	theXObject,
			bool				isCDATA)
{
	fireCharacterGenerateEvent(theXObject->str(), isCDATA);
}



void
XSLTEngineImpl::fireCharacterGenerateEvent(
			const XalanDOMString&	theString,
			bool					isCDATA)
{
	fireCharacterGenerateEvent(c_wstr(theString), 0, length(theString), isCDATA);
}



void
XSLTEngineImpl::fireCharacterGenerateEvent(
			const XMLCh*	ch,
			unsigned int	start,
			unsigned int	length,
			bool			isCDATA)
{
	const GenerateEvent		ge(
		isCDATA == true ? GenerateEvent::EVENTTYPE_CDATA : GenerateEvent::EVENTTYPE_CHARACTERS,
		ch,
		start,
		length);

	fireGenerateEvent(ge);
}



void
XSLTEngineImpl::installFunctions()
{
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("current")), FunctionCurrent());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("document")), FunctionDocument());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("element-available")), FunctionElementAvailable());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("function-available")), FunctionFunctionAvailable());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("format-number")), FunctionFormatNumber());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("generate-id")), FunctionGenerateID());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("key")), FunctionKey());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("system-property")), FunctionSystemProperty());
	XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("unparsed-entity-uri")), FunctionUnparsedEntityURI());
}



void
XSLTEngineImpl::uninstallFunctions()
{
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("current")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("document")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("element-available")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("function-available")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("format-number")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("generate-id")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("key")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("system-property")));
	XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("unparsed-entity-uri")));
}



void
XSLTEngineImpl::initializeAttributeKeysTable(AttributeKeysMapType&	theAttributeKeys)
{
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_METHOD] = Constants::TATTRNAME_OUTPUT_METHOD;
	theAttributeKeys[Constants::ATTRNAME_AMOUNT] = Constants::TATTRNAME_AMOUNT;
	theAttributeKeys[Constants::ATTRNAME_ANCESTOR] = Constants::TATTRNAME_ANCESTOR;
	theAttributeKeys[Constants::ATTRNAME_ARCHIVE] = Constants::TATTRNAME_ARCHIVE;
	theAttributeKeys[Constants::ATTRNAME_ATTRIBUTE] = Constants::TATTRNAME_ATTRIBUTE;
	theAttributeKeys[Constants::ATTRNAME_ATTRIBUTE_SET] = Constants::TATTRNAME_ATTRIBUTE_SET;
	theAttributeKeys[Constants::ATTRNAME_CASEORDER] = Constants::TATTRNAME_CASEORDER;
	theAttributeKeys[Constants::ATTRNAME_CLASS] = Constants::TATTRNAME_CLASS;
	theAttributeKeys[Constants::ATTRNAME_CLASSID] = Constants::TATTRNAME_CLASSID;
	theAttributeKeys[Constants::ATTRNAME_CODEBASE] = Constants::TATTRNAME_CODEBASE;
	theAttributeKeys[Constants::ATTRNAME_CODETYPE] = Constants::TATTRNAME_CODETYPE;
	theAttributeKeys[Constants::ATTRNAME_CONDITION] = Constants::TATTRNAME_CONDITION;
	theAttributeKeys[Constants::ATTRNAME_COPYTYPE] = Constants::TATTRNAME_COPYTYPE;
	theAttributeKeys[Constants::ATTRNAME_COUNT] = Constants::TATTRNAME_COUNT;
	theAttributeKeys[Constants::ATTRNAME_DATATYPE] = Constants::TATTRNAME_DATATYPE;
	theAttributeKeys[Constants::ATTRNAME_DEFAULT] = Constants::TATTRNAME_DEFAULT;
	theAttributeKeys[Constants::ATTRNAME_DEFAULTSPACE] = Constants::TATTRNAME_DEFAULTSPACE;
	theAttributeKeys[Constants::ATTRNAME_DEPTH] = Constants::TATTRNAME_DEPTH;
	theAttributeKeys[Constants::ATTRNAME_DIGITGROUPSEP] = Constants::TATTRNAME_DIGITGROUPSEP;
	theAttributeKeys[Constants::ATTRNAME_DISABLE_OUTPUT_ESCAPING] = Constants::TATTRNAME_DISABLE_OUTPUT_ESCAPING;
	theAttributeKeys[Constants::ATTRNAME_ELEMENT] = Constants::TATTRNAME_ELEMENT;
	theAttributeKeys[Constants::ATTRNAME_ELEMENTS] = Constants::TATTRNAME_ELEMENTS;
	theAttributeKeys[Constants::ATTRNAME_EXPR] = Constants::TATTRNAME_EXPR;
	theAttributeKeys[Constants::ATTRNAME_EXTENSIONELEMENTPREFIXES] = Constants::TATTRNAME_EXTENSIONELEMENTPREFIXES;
	theAttributeKeys[Constants::ATTRNAME_FORMAT] = Constants::TATTRNAME_FORMAT;
	theAttributeKeys[Constants::ATTRNAME_FROM] = Constants::TATTRNAME_FROM;
	theAttributeKeys[Constants::ATTRNAME_GROUPINGSEPARATOR] = Constants::TATTRNAME_GROUPINGSEPARATOR;
	theAttributeKeys[Constants::ATTRNAME_GROUPINGSIZE] = Constants::TATTRNAME_GROUPINGSIZE;
	theAttributeKeys[Constants::ATTRNAME_HREF] = Constants::TATTRNAME_HREF;
	theAttributeKeys[Constants::ATTRNAME_ID] = Constants::TATTRNAME_ID;
	theAttributeKeys[Constants::ATTRNAME_IMPORTANCE] = Constants::TATTRNAME_IMPORTANCE;
	theAttributeKeys[Constants::ATTRNAME_INDENTRESULT] = Constants::TATTRNAME_INDENTRESULT;
	theAttributeKeys[Constants::ATTRNAME_LANG] = Constants::TATTRNAME_LANG;
	theAttributeKeys[Constants::ATTRNAME_LETTERVALUE] = Constants::TATTRNAME_LETTERVALUE;
	theAttributeKeys[Constants::ATTRNAME_LEVEL] = Constants::TATTRNAME_LEVEL;
	theAttributeKeys[Constants::ATTRNAME_MATCH] = Constants::TATTRNAME_MATCH;
	theAttributeKeys[Constants::ATTRNAME_METHOD] = Constants::TATTRNAME_METHOD;
	theAttributeKeys[Constants::ATTRNAME_MODE] = Constants::TATTRNAME_MODE;
	theAttributeKeys[Constants::ATTRNAME_NAME] = Constants::TATTRNAME_NAME;
	theAttributeKeys[Constants::ATTRNAME_NAMESPACE] = Constants::TATTRNAME_NAMESPACE;
	theAttributeKeys[Constants::ATTRNAME_NDIGITSPERGROUP] = Constants::TATTRNAME_NDIGITSPERGROUP;
	theAttributeKeys[Constants::ATTRNAME_NS] = Constants::TATTRNAME_NS;
	theAttributeKeys[Constants::ATTRNAME_ONLY] = Constants::TATTRNAME_ONLY;
	theAttributeKeys[Constants::ATTRNAME_ORDER] = Constants::TATTRNAME_ORDER;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_CDATA_SECTION_ELEMENTS] = Constants::TATTRNAME_OUTPUT_CDATA_SECTION_ELEMENTS;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_DOCTYPE_PUBLIC] = Constants::TATTRNAME_OUTPUT_DOCTYPE_PUBLIC;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_DOCTYPE_SYSTEM] = Constants::TATTRNAME_OUTPUT_DOCTYPE_SYSTEM;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_ENCODING] = Constants::TATTRNAME_OUTPUT_ENCODING;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_INDENT] = Constants::TATTRNAME_OUTPUT_INDENT;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_MEDIATYPE] = Constants::TATTRNAME_OUTPUT_MEDIATYPE;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_STANDALONE] = Constants::TATTRNAME_OUTPUT_STANDALONE;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_VERSION] = Constants::TATTRNAME_OUTPUT_VERSION;
	theAttributeKeys[Constants::ATTRNAME_OUTPUT_OMITXMLDECL] = Constants::TATTRNAME_OUTPUT_OMITXMLDECL;
	theAttributeKeys[Constants::ATTRNAME_PRIORITY] = Constants::TATTRNAME_PRIORITY;
	theAttributeKeys[Constants::ATTRNAME_REFID] = Constants::TATTRNAME_REFID;
	theAttributeKeys[Constants::ATTRNAME_RESULTNS] = Constants::TATTRNAME_RESULTNS;
	theAttributeKeys[Constants::ATTRNAME_SELECT] = Constants::TATTRNAME_SELECT;
	theAttributeKeys[Constants::ATTRNAME_SEQUENCESRC] = Constants::TATTRNAME_SEQUENCESRC;
	theAttributeKeys[Constants::ATTRNAME_STYLE] = Constants::TATTRNAME_STYLE;
	theAttributeKeys[Constants::ATTRNAME_TEST] = Constants::TATTRNAME_TEST;
	theAttributeKeys[Constants::ATTRNAME_TOSTRING] = Constants::TATTRNAME_TOSTRING;
	theAttributeKeys[Constants::ATTRNAME_TYPE] = Constants::TATTRNAME_TYPE;
	theAttributeKeys[Constants::ATTRNAME_USE] = Constants::TATTRNAME_USE;
	theAttributeKeys[Constants::ATTRNAME_USEATTRIBUTESETS] = Constants::TATTRNAME_USEATTRIBUTESETS;
	theAttributeKeys[Constants::ATTRNAME_VALUE] = Constants::TATTRNAME_VALUE;

	theAttributeKeys[Constants::ATTRNAME_XMLNSDEF] = Constants::TATTRNAME_XMLNSDEF;
	theAttributeKeys[Constants::ATTRNAME_XMLNS] = Constants::TATTRNAME_XMLNS;
	theAttributeKeys[Constants::ATTRNAME_XMLSPACE] = Constants::TATTRNAME_XMLSPACE;
}



void
XSLTEngineImpl::initializeElementKeysTable(ElementKeysMapType&	theElementKeys)
{
	theElementKeys[Constants::ELEMNAME_APPLY_TEMPLATES_STRING] = Constants::ELEMNAME_APPLY_TEMPLATES;
	theElementKeys[Constants::ELEMNAME_WITHPARAM_STRING] = Constants::ELEMNAME_WITHPARAM;
	theElementKeys[Constants::ELEMNAME_CONSTRUCT_STRING] = Constants::ELEMNAME_CONSTRUCT;
	theElementKeys[Constants::ELEMNAME_CONTENTS_STRING] = Constants::ELEMNAME_CONTENTS;
	theElementKeys[Constants::ELEMNAME_COPY_STRING] = Constants::ELEMNAME_COPY;
	theElementKeys[Constants::ELEMNAME_COPY_OF_STRING] = Constants::ELEMNAME_COPY_OF;

	theElementKeys[Constants::ELEMNAME_ATTRIBUTESET_STRING] = Constants::ELEMNAME_DEFINEATTRIBUTESET;

	theElementKeys[Constants::ELEMNAME_USE_STRING] = Constants::ELEMNAME_USE;

	theElementKeys[Constants::ELEMNAME_VARIABLE_STRING] = Constants::ELEMNAME_VARIABLE;
	theElementKeys[Constants::ELEMNAME_PARAMVARIABLE_STRING] = Constants::ELEMNAME_PARAMVARIABLE;

	theElementKeys[Constants::ELEMNAME_DISPLAYIF_STRING] = Constants::ELEMNAME_DISPLAYIF;
	theElementKeys[Constants::ELEMNAME_EMPTY_STRING] = Constants::ELEMNAME_EMPTY;
	theElementKeys[Constants::ELEMNAME_EVAL_STRING] = Constants::ELEMNAME_EVAL;
	theElementKeys[Constants::ELEMNAME_CALLTEMPLATE_STRING] = Constants::ELEMNAME_CALLTEMPLATE;
	theElementKeys[Constants::ELEMNAME_TEMPLATE_STRING] = Constants::ELEMNAME_TEMPLATE;
	theElementKeys[Constants::ELEMNAME_STYLESHEET_STRING] = Constants::ELEMNAME_STYLESHEET;
	theElementKeys[Constants::ELEMNAME_TRANSFORM_STRING] = Constants::ELEMNAME_STYLESHEET;
	theElementKeys[Constants::ELEMNAME_IMPORT_STRING] = Constants::ELEMNAME_IMPORT;
	theElementKeys[Constants::ELEMNAME_INCLUDE_STRING] = Constants::ELEMNAME_INCLUDE;
	theElementKeys[Constants::ELEMNAME_FOREACH_STRING] = Constants::ELEMNAME_FOREACH;
	theElementKeys[Constants::ELEMNAME_VALUEOF_STRING] = Constants::ELEMNAME_VALUEOF;
	theElementKeys[Constants::ELEMNAME_KEY_STRING] = Constants::ELEMNAME_KEY;
	theElementKeys[Constants::ELEMNAME_STRIPSPACE_STRING] = Constants::ELEMNAME_STRIPSPACE;
	theElementKeys[Constants::ELEMNAME_PRESERVESPACE_STRING] = Constants::ELEMNAME_PRESERVESPACE;
	theElementKeys[Constants::ELEMNAME_NUMBER_STRING] = Constants::ELEMNAME_NUMBER;
	theElementKeys[Constants::ELEMNAME_IF_STRING] = Constants::ELEMNAME_IF;
	theElementKeys[Constants::ELEMNAME_CHOOSE_STRING] = Constants::ELEMNAME_CHOOSE;
	theElementKeys[Constants::ELEMNAME_WHEN_STRING] = Constants::ELEMNAME_WHEN;
	theElementKeys[Constants::ELEMNAME_OTHERWISE_STRING] = Constants::ELEMNAME_OTHERWISE;
	theElementKeys[Constants::ELEMNAME_TEXT_STRING] = Constants::ELEMNAME_TEXT;
	theElementKeys[Constants::ELEMNAME_ELEMENT_STRING] = Constants::ELEMNAME_ELEMENT;
	theElementKeys[Constants::ELEMNAME_ATTRIBUTE_STRING] = Constants::ELEMNAME_ATTRIBUTE;
	theElementKeys[Constants::ELEMNAME_SORT_STRING] = Constants::ELEMNAME_SORT;
	theElementKeys[Constants::ELEMNAME_PI_STRING] = Constants::ELEMNAME_PI;
	theElementKeys[Constants::ELEMNAME_COMMENT_STRING] = Constants::ELEMNAME_COMMENT;
   
	theElementKeys[Constants::ELEMNAME_COUNTER_STRING] = Constants::ELEMNAME_COUNTER;
	theElementKeys[Constants::ELEMNAME_COUNTERS_STRING] = Constants::ELEMNAME_COUNTERS;
	theElementKeys[Constants::ELEMNAME_COUNTERINCREMENT_STRING] = Constants::ELEMNAME_COUNTERINCREMENT;
	theElementKeys[Constants::ELEMNAME_COUNTERRESET_STRING] = Constants::ELEMNAME_COUNTERRESET;
	theElementKeys[Constants::ELEMNAME_COUNTERSCOPE_STRING] = Constants::ELEMNAME_COUNTERSCOPE;
	
	theElementKeys[Constants::ELEMNAME_APPLY_IMPORTS_STRING] = Constants::ELEMNAME_APPLY_IMPORTS;
	
	theElementKeys[Constants::ELEMNAME_EXTENSION_STRING] = Constants::ELEMNAME_EXTENSION;
	theElementKeys[Constants::ELEMNAME_MESSAGE_STRING] = Constants::ELEMNAME_MESSAGE;
	theElementKeys[Constants::ELEMNAME_LOCALE_STRING] = Constants::ELEMNAME_LOCALE;
	theElementKeys[Constants::ELEMNAME_FALLBACK_STRING] = Constants::ELEMNAME_FALLBACK;
	theElementKeys[Constants::ELEMNAME_OUTPUT_STRING] = Constants::ELEMNAME_OUTPUT;

	theElementKeys[Constants::ELEMNAME_DECIMALFORMAT_STRING] = Constants::ELEMNAME_DECIMALFORMAT;
	theElementKeys[Constants::ELEMNAME_NSALIAS_STRING] = Constants::ELEMNAME_NSALIAS;
}



void
XSLTEngineImpl::initializeXSLT4JElementKeys(ElementKeysMapType&		theElementKeys)
{
	theElementKeys[Constants::ELEMNAME_COMPONENT_STRING] = Constants::ELEMNAME_COMPONENT;
	theElementKeys[Constants::ELEMNAME_SCRIPT_STRING] = Constants::ELEMNAME_SCRIPT;
}



static XalanDOMString							s_XSLNameSpaceURL;

static XalanDOMString							s_XSLT4JNameSpaceURL;

static XalanDOMString							s_uniqueNamespacePrefix;

static XSLTEngineImpl::AttributeKeysMapType		s_attributeKeys;

static XSLTEngineImpl::ElementKeysMapType		s_elementKeys;

static XSLTEngineImpl::ElementKeysMapType		s_XSLT4JElementKeys;



const double			XSLTEngineImpl::s_XSLTVerSupported(1.0);

const XalanDOMString&	XSLTEngineImpl::s_XSLNameSpaceURL = ::s_XSLNameSpaceURL;

const XalanDOMString&	XSLTEngineImpl::s_XSLT4JNameSpaceURL = ::s_XSLT4JNameSpaceURL;

const XalanDOMString&	XSLTEngineImpl::s_uniqueNamespacePrefix = ::s_uniqueNamespacePrefix;


const XSLTEngineImpl::AttributeKeysMapType&		XSLTEngineImpl::s_attributeKeys = ::s_attributeKeys;

const XSLTEngineImpl::ElementKeysMapType&		XSLTEngineImpl::s_elementKeys = ::s_elementKeys;

const XSLTEngineImpl::ElementKeysMapType&		XSLTEngineImpl::s_XSLT4JElementKeys = ::s_XSLT4JElementKeys;



void
XSLTEngineImpl::initialize()
{
	::s_XSLNameSpaceURL = XALAN_STATIC_UCODE_STRING("http://www.w3.org/1999/XSL/Transform");

	::s_XSLT4JNameSpaceURL = XALAN_STATIC_UCODE_STRING("http://xml.apache.org/xslt");

	::s_uniqueNamespacePrefix = XALAN_STATIC_UCODE_STRING("ns");

	installFunctions();

	initializeAttributeKeysTable(::s_attributeKeys);

	initializeElementKeysTable(::s_elementKeys);

	initializeXSLT4JElementKeys(::s_XSLT4JElementKeys);
}



void
XSLTEngineImpl::terminate()
{
	ElementKeysMapType().swap(::s_XSLT4JElementKeys);

	ElementKeysMapType().swap(::s_elementKeys);

	AttributeKeysMapType().swap(::s_attributeKeys);

	uninstallFunctions();

	releaseMemory(::s_uniqueNamespacePrefix);

	releaseMemory(::s_XSLT4JNameSpaceURL);

	releaseMemory(::s_XSLNameSpaceURL);
}
