/*
 * 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.
 */



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



#include <xercesc/sax/DocumentHandler.hpp>
#include <xercesc/sax/EntityResolver.hpp>
#include <xercesc/sax/Locator.hpp>
#include "xercesc/util/XMLEntityResolver.hpp"
#include "xercesc/util/XMLResourceIdentifier.hpp"



#include <xalanc/Include/STLHelper.hpp>



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



#include <xalanc/PlatformSupport/PrintWriter.hpp>
#include <xalanc/PlatformSupport/StringTokenizer.hpp>
#include <xalanc/PlatformSupport/XalanLocator.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>



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



#include <xalanc/XMLSupport/FormatterToHTML.hpp>
#include <xalanc/XMLSupport/FormatterTreeWalker.hpp>
#include <xalanc/XMLSupport/XMLParserLiaison.hpp>
#include <xalanc/XMLSupport/FormatterTreeWalker.hpp>



#include <xalanc/XPath/ElementPrefixResolverProxy.hpp>
#include <xalanc/XPath/XalanQNameByReference.hpp>
#include <xalanc/XPath/XObject.hpp>
#include <xalanc/XPath/XObjectFactory.hpp>
#include <xalanc/XPath/XPathEnvSupport.hpp>
#include <xalanc/XPath/XPathEnvSupportDefault.hpp>
#include <xalanc/XPath/XPathExecutionContextDefault.hpp>
#include <xalanc/XPath/XPathFactory.hpp>
#include <xalanc/XPath/XPathFunctionTable.hpp>
#include <xalanc/XPath/XPathProcessorImpl.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



namespace XALAN_CPP_NAMESPACE {


const XalanDOMString    XSLTEngineImpl::s_emptyString(XalanMemMgrs::getDummyMemMgr());



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

XSLTEngineImpl::XSLTEngineImpl(
            MemoryManager&  theManager,
            XMLParserLiaison&   parserLiaison,
            XPathEnvSupport&    xpathEnvSupport,
            DOMSupport&         domSupport,
            XObjectFactory&     xobjectFactory,
            XPathFactory&       xpathFactory) :
    XSLTProcessor(),
    PrefixResolver(),
    m_resultNameSpacePrefix(theManager),
    m_resultNameSpaceURL(theManager),
    m_xpathFactory(xpathFactory),
    m_xobjectFactory(xobjectFactory),
    m_xpathProcessor(theManager, XPathProcessorImpl::create(theManager)),
    m_cdataStack(theManager),
    m_stylesheetLocatorStack(theManager),
    m_defaultProblemListener(theManager),
    m_problemListener(&m_defaultProblemListener),
    m_stylesheetRoot(0),
    m_traceSelects(false),
    m_quietConflictWarnings(true),
    m_diagnosticsPrintWriter(0),
    m_traceListeners(theManager),
    m_uniqueNSValue(0),
    m_topLevelParams(theManager),
    m_parserLiaison(parserLiaison),
    m_xpathEnvSupport(xpathEnvSupport),
    m_domSupport(domSupport),
    m_executionContext(0),
    m_outputContextStack(theManager),
    m_resultNamespacesStack(theManager),
    m_dummyAttributesList(theManager),
    m_scratchString(theManager),
    m_attributeNamesVisited(theManager),
    m_hasCDATASectionElements(false),
    m_xpathConstructionContext(theManager),
    m_stylesheetParams(theManager)
{
    m_outputContextStack.pushContext();
}



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

    m_stylesheetRoot = 0;

    m_outputContextStack.reset();

    m_outputContextStack.pushContext();

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

    m_resultNamespacesStack.clear();

    m_attributeNamesVisited.clear();

    m_hasCDATASectionElements = false;

    m_xpathConstructionContext.reset();
}



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



void
XSLTEngineImpl::problem(
            eSource                 source,
            eClassification         classification,
            const XalanDOMString&   msg,
            const Locator*          locator,
            const XalanNode*        sourceNode)
{
    if (m_problemListener != 0)
    {
        m_problemListener->problem(
                    source,
                    classification,
                    msg,
                    locator,
                    sourceNode);
    }

    if (classification == ProblemListener::eERROR)
    {
        throw XSLTProcessorException(
                getMemoryManager(),
                msg,
                locator);
    }
}



void
XSLTEngineImpl::problem(
            eSource                 source,
            eClassification         classification,
            const XalanDOMString&   msg,
            const XalanNode*        sourceNode)
{
    if (m_problemListener != 0)
    {
        m_problemListener->problem(
                    source,
                    classification,
                    msg,
                    sourceNode);
    }

    if (classification == ProblemListener::eERROR)
    {
        throw XSLTProcessorException(
                getMemoryManager(),
                msg);
    }
}



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

    if (0 == stylesheetSource.getSystemId())
    {
        XalanMessageLoader::getMessage(
            xslIdentifier,
            XalanMessages::InputXSL);
    }
    else
    {
        xslIdentifier = stylesheetSource.getSystemId();
    }

    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...

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

        XalanDOMString      theCurrentToken(executionContext.getMemoryManager());
        XalanDOMString      theStylesheetURI(executionContext.getMemoryManager());

        bool            isOK = false;

        while(child != 0 && isOK == false && theStylesheetURI.empty() == true)
        {
            if(XalanNode::PROCESSING_INSTRUCTION_NODE == child->getNodeType())
            {
                const XalanDOMString&   nodeName = child->getNodeName();

                if(equals(nodeName, s_stylesheetNodeName))
                {
                    StringTokenizer     tokenizer(child->getNodeValue(), s_piTokenizerString);

                    while(tokenizer.hasMoreTokens() == true && (isOK == false || theStylesheetURI.empty() == true))
                    {
                        tokenizer.nextToken(theCurrentToken);

                        if(equals(theCurrentToken, s_typeString))
                        {
                            tokenizer.nextToken(theCurrentToken);

                            const XalanDOMString::size_type     theLength =
                                    theCurrentToken.length();

                            if (theLength > 2)
                            {
                                theCurrentToken.erase(theLength - 1, 1);
                                theCurrentToken.erase(0, 1);

                                if(equals(theCurrentToken, s_typeValueString1) ||
                                    equals(theCurrentToken, s_typeValueString2) ||
                                    equals(theCurrentToken, s_typeValueString3) ||
                                    equals(theCurrentToken, s_typeValueString4))
                                {
                                    isOK = true;
                                }
                            }
                        }
                        else if(equals(theCurrentToken, s_hrefString))
                        {
                            tokenizer.nextToken(theCurrentToken);

                            const XalanDOMString::size_type     theLength =
                                    theCurrentToken.length();

                            if (theLength > 2)
                            {
                                // Trim of the starting and trailing delimiters...
                                theStylesheetURI.assign(theCurrentToken, 1, theLength - 2);
                            }
                        }
                    }
                }
            }

            child = child->getNextSibling();
        }

        if (isOK == true && theStylesheetURI.empty() == false)
        {
            const CCGetCachedString     theGuard(constructionContext);

            XalanDOMString&             sysid = theGuard.get();

            const XalanDOMChar* const   pxch = inputSource.getSystemId();

            if (pxch != 0)
            {
                sysid.assign(pxch);
            }

            getStylesheetFromPIURL(
                    theStylesheetURI,
                    *sourceTree,
                    sysid,
                    true,
                    constructionContext);
        }
    }

    if(0 == m_stylesheetRoot)
    {
        const ECGetCachedString     theGuard(executionContext);

        error(
            XalanMessageLoader::getMessage(
                theGuard.get(),
                XalanMessages::FailedToProcessStylesheet),
                0,
                sourceTree);
    }
    else if(0 != sourceTree)
    {
        executionContext.setStylesheetRoot(m_stylesheetRoot);

        FormatterListener* const    theFormatter =
                outputTarget.getFormatterListener();

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

        m_hasCDATASectionElements = m_stylesheetRoot->hasCDATASectionElements();

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



void
XSLTEngineImpl::process(
            const XSLTInputSource&          inputSource, 
            XSLTResultTarget&               outputTarget,
            StylesheetExecutionContext&     executionContext)
{
    XalanNode* const    sourceTree = getSourceTreeFromInput(inputSource);

    if(0 != sourceTree)
    {
        if (m_stylesheetRoot == 0)
        {
            const ECGetCachedString     theGuard(executionContext);

            error(
                XalanMessageLoader::getMessage(
                    theGuard.get(),
                    XalanMessages::NoStylesheet),
                    0,
                    sourceTree);
        }

        FormatterListener* const    theFormatter =
                outputTarget.getFormatterListener();

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

        m_hasCDATASectionElements = m_stylesheetRoot->hasCDATASectionElements();

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



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

    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)
    {
        const CCGetCachedString     theGuard(constructionContext);

        XalanDOMString&     xslIdentifier = theGuard.get();

        theStylesheet = constructionContext.create(stylesheetSource);

        StylesheetHandler   stylesheetProcessor(*theStylesheet, constructionContext);

        if(stylesheetNode != 0)
        {
            const XalanNode::NodeType   theType = stylesheetNode->getNodeType();

            if (theType != XalanNode::ELEMENT_NODE && theType != XalanNode::DOCUMENT_NODE)
            {
                const CCGetCachedString     theGuard(constructionContext);

                error(
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::CompilingDOMStylesheetReqDocument),
                        constructionContext.getLocatorFromStack(),
                        0);
            }
            else
            {

                XalanMessageLoader::getMessage(
                    xslIdentifier,
                    XalanMessages::InputXSL);

                FormatterTreeWalker tw(stylesheetProcessor, constructionContext.getMemoryManager());

                if (theType == XalanNode::DOCUMENT_NODE)
                {
                    tw.traverse(stylesheetNode);
                }
                else
                {
                    stylesheetProcessor.startDocument();

                    tw.traverseSubtree(stylesheetNode);

                    stylesheetProcessor.endDocument();
                }
            }
        }
        else
        {
            if (systemID != 0)
            {
                xslIdentifier = systemID;
            }

            m_parserLiaison.parseXMLStream(
                stylesheetSource,
                stylesheetProcessor,
                s_emptyString);
        }

        theStylesheet->postConstruction(constructionContext);
    }

    return theStylesheet;
}



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

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

    if(0 == sourceTree)
    {
        const CCGetCachedString     theGuard1(m_xpathConstructionContext);

        XalanDOMString&     xmlIdentifier = theGuard1.get();

        const XalanDOMChar* const   theSystemID = inputSource.getSystemId();

        if (0 != theSystemID)
        {
            try
            {
                URISupport::getURLStringFromString(theSystemID, xmlIdentifier);
            }
            catch(const xercesc::XMLException&)
            {
                xmlIdentifier = theSystemID;
            }
        }

#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

        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,
            ErrorHandler*           theErrorHandler)
{
    
    XalanDocument*  doc =
            m_xpathEnvSupport.getSourceDocument(urlString);

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

        XMLEntityResolver* const    theXMLResolver = 
            m_parserLiaison.getXMLEntityResolver();

        XalanAutoPtr<InputSource>   resolverInputSource;

        if (theResolver != 0)
        {
            resolverInputSource.reset(theResolver->resolveEntity(0, urlString.c_str()));
        }
        else if (theXMLResolver != 0)
        {
            using xercesc::XMLResourceIdentifier;;

            XMLResourceIdentifier   theIndentifier(
                XMLResourceIdentifier::ExternalEntity,
                urlString.c_str());

            resolverInputSource.reset(
                theXMLResolver->resolveEntity(&theIndentifier));
        }

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

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

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

    return doc;
}



XalanDocument*
XSLTEngineImpl::parseXML(
            const InputSource&  inputSource,
            DocumentHandler*    docHandler,
            XalanDocument*      docToRegister,
            ErrorHandler*       theErrorHandler)
{
    typedef XMLParserLiaison::EnsureResetErrorHandler   EnsureResetErrorHandler;

    EnsureResetErrorHandler     theGuard;

    if (theErrorHandler != 0)
    {
        theGuard.set(
            &m_parserLiaison,
            theErrorHandler);
    }

    if (0 != docHandler)
    {
        m_parserLiaison.parseXMLStream(
            inputSource,
            *docHandler,
            s_emptyString);

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



Stylesheet*
XSLTEngineImpl::getStylesheetFromPIURL(
            const XalanDOMString&           xslURLString,
            XalanNode&                      fragBase,
            const XalanDOMString&           xmlBaseIdent,
            bool                            isRoot,
            StylesheetConstructionContext&  constructionContext)
{
    MemoryManager&          theMemoryManager =
        constructionContext.getMemoryManager();

    Stylesheet*             stylesheet = 0;

    const CCGetCachedString     theGuard(constructionContext);
    XalanDOMString&             stringHolder = theGuard.get();

    const CCGetCachedString     theGuard1(constructionContext);
    XalanDOMString&     localXSLURLString = theGuard1.get();    
    
    trim(xslURLString, localXSLURLString);

    const XalanDOMString::size_type     fragIndex =
        indexOf(localXSLURLString, XalanUnicode::charNumberSign);

    if(fragIndex == 0)
    {
        const CCGetCachedString     theGuard(constructionContext);

        XalanDOMString& fragID = theGuard.get();

        fragID.assign(localXSLURLString);

        const XalanElement*     nsNode = 0;

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

        if (theType == XalanNode::DOCUMENT_NODE)
        {
            const XalanDocument&    doc =
                static_cast<const XalanDocument&>(fragBase);

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

            if  (node->getNodeType() == XalanNode::ELEMENT_NODE) 
            {
                nsNode = static_cast<const XalanElement*>(node);
            }
            else
            {
                const CCGetCachedString     theGuard(constructionContext);

                error(
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::CantFindFragment_1Param,
                        fragID),
                    constructionContext.getLocatorFromStack(),
                    &fragBase);
            }
        }

        // Try a bunch of really ugly stuff to find the fragment.
        // What's the right way to do this?
        const CCGetCachedString     theGuard3(constructionContext);

        XalanDOMString& ds = theGuard3.get();

        ds.append("id(");

        ds += fragID;
        ds.append(")");

        ElementPrefixResolverProxy      theProxy(nsNode, m_xpathEnvSupport, m_domSupport, theMemoryManager);

        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(), theMemoryManager);

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

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

            nl = xobj->nodeset();

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

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

                nl = xobj->nodeset();

                if(nl.getLength() == 0)
                {
                    // Well, hell, maybe it's an XPath...
                    const XObjectPtr    xobj(evalXPathStr(fragID, theExecutionContext));
                    assert(xobj.null() == false);

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

        if (nl.getLength() == 0)
        {
            const CCGetCachedString     theGuard(constructionContext);

            error(
                XalanMessageLoader::getMessage(
                    theGuard.get(),
                    XalanMessages::CantFindFragment_1Param,
                    fragID),
                constructionContext.getLocatorFromStack(),
                &fragBase);
        }

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

        if (XalanNode::ELEMENT_NODE == frag->getNodeType())
        {
            XalanMemMgrAutoPtr<Stylesheet>  theGuard;

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

                stylesheet = theLocalRoot;

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

                theGuard.reset(&theMemoryManager, stylesheet);
            }

            StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext);

            FormatterTreeWalker tw(stylesheetProcessor,  theMemoryManager);

            stylesheetProcessor.startDocument();

            tw.traverseSubtree(frag);

            stylesheetProcessor.endDocument();

            stylesheet->postConstruction(constructionContext);

            theGuard.release();
        }
        else
        {
            const CCGetCachedString     theGuard(constructionContext);

            error(
                XalanMessageLoader::getMessage(
                    theGuard.get(),
                    XalanMessages::NodePointedByFragment_1Param,
                    fragID),
                constructionContext.getLocatorFromStack(),
                &fragBase);
        }
    }
    else
    {
        XalanMemMgrAutoPtr<Stylesheet>  theGuard;

        const XalanDocument* const  theOwnerDocument =
                fragBase.getNodeType() == XalanNode::DOCUMENT_NODE ?
                    static_cast<const XalanDocument*>(&fragBase) :
                    fragBase.getOwnerDocument();
        assert(theOwnerDocument != 0);

        // Catch any XMLExceptions thrown, since we may not
        // be able to resolve the URL.  In that case, the
        // parser will throw an error.  We do this because
        // we don't know what sort of EntityResolvers might
        // be active, so we never want to error out here.
        try
        {
            if (xmlBaseIdent.empty() == true)
            {
                URISupport::getURLStringFromString(
                            localXSLURLString,
                            m_xpathEnvSupport.findURIFromDoc(theOwnerDocument),
                            localXSLURLString);
            }
            else
            {
                URISupport::getURLStringFromString(
                            localXSLURLString,
                            xmlBaseIdent,
                            localXSLURLString);
            }
        }
        catch(const xercesc::XMLException&)
        {
        }

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

            stylesheet = theLocalRoot;

            m_stylesheetRoot = theLocalRoot;
        }
        else
        {
            stylesheet = Stylesheet::create(
                            theMemoryManager,
                            *const_cast<StylesheetRoot*>(m_stylesheetRoot),
                            localXSLURLString,
                            constructionContext);

            theGuard.reset(&theMemoryManager, stylesheet);
        }

        StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext);

        typedef StylesheetConstructionContext::URLAutoPtrType   URLAutoPtrType;

        URLAutoPtrType  xslURL(constructionContext.getURLFromString(localXSLURLString));

        XSLTInputSource     inputSource(xslURL->getURLText(), theMemoryManager);

        m_parserLiaison.parseXMLStream(inputSource, stylesheetProcessor, s_emptyString);

        stylesheet->postConstruction(constructionContext);

        theGuard.release();
    }

    return stylesheet;
}



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
//==========================================================

XSLTEngineImpl::size_type
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)
{
    using std::remove;

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

    m_traceListeners.erase(i);
}



void
XSLTEngineImpl::fireGenerateEvent(const GenerateEvent&  ge)
{
    using std::for_each;

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



void
XSLTEngineImpl::fireSelectEvent(const SelectionEvent&   se)
{
    using std::for_each;

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



void
XSLTEngineImpl::fireTraceEvent(const TracerEvent& te)
{
    using std::for_each;

    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::setDiagnosticsOutput(PrintWriter*   pw)
{
    m_diagnosticsPrintWriter = pw;

    m_problemListener->setPrintWriter(pw);
}



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



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



void
XSLTEngineImpl::traceSelect(
            StylesheetExecutionContext&     executionContext,
            const ElemTemplateElement&      theTemplate,
            const NodeRefListBase&          nl,
            const XPath*                    xpath) const
{
    if (0 != m_diagnosticsPrintWriter)
    {
        const ECGetCachedString     theGuard(executionContext);

        XalanDOMString& msg = theGuard.get();

        msg.assign(theTemplate.getElementName());
        msg.append(": ");

        if(xpath != 0)
        {
            msg += xpath->getExpression().getCurrentPattern();
            msg.append(", ");
        }
        else
        {
            msg.append("*|text(), (default select), ");
        }
        const ECGetCachedString     theGuard1(executionContext);

        XalanDOMString& theBuffer = theGuard1.get();
        NumberToDOMString(static_cast<XMLUInt64>(nl.getLength()), theBuffer);

        msg += theBuffer;
            
        msg.append(" selected");

        const XalanQName* const     mode = executionContext.getCurrentMode();

        if(mode != 0 && mode->isEmpty() == false)
        {
            msg += XalanDOMString(", mode = {", executionContext.getMemoryManager());
            msg += mode->getNamespace();
            msg += XalanDOMString("}", executionContext.getMemoryManager());
            msg += mode->getLocalPart();
        }

        m_diagnosticsPrintWriter->println(msg);
    }
}



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

    if (getHasPendingStartDocument() == false)
    {
        assert(m_cdataStack.empty() == true || m_outputContextStack.size() != 1);

        m_resultNamespacesStack.pushContext();

        setHasPendingStartDocument(true);

        setMustFlushPendingStartDocument(false);

        if (m_hasCDATASectionElements == true)
        {
            m_cdataStack.push_back(false);
        }
    }
    else if (getMustFlushPendingStartDocument() == true)
    {
        getFormatterListenerImpl()->startDocument();

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

            fireGenerateEvent(ge);
        }

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



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

    setMustFlushPendingStartDocument(true);

    flushPending();

    getFormatterListenerImpl()->endDocument();

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

        fireGenerateEvent(ge);
    }

    if (m_hasCDATASectionElements == true)
    {
        m_cdataStack.pop_back();
    }
    assert(m_cdataStack.empty() == true);

    m_resultNamespacesStack.popContext();

    assert(m_resultNamespacesStack.empty() == true);
}



void
XSLTEngineImpl::addResultAttribute(
            AttributeListImpl&      attList,
            const XalanDOMString&   aname,
            const XalanDOMChar*     value,
            size_type               theLength,
            bool                    fromCopy,
            const Locator*          locator)
{
    assert(value != 0);

    // Always exclude the implicit XML declaration...
    if (equals(aname, DOMServices::s_XMLNamespacePrefix) == false) 
    {
        bool    fExcludeAttribute = false;

        if (equals(aname, DOMServices::s_XMLNamespace) == true)
        {
            // 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 (theLength != 0)
            {
                if (currentDefaultNamespace != 0 &&
                    equals(*currentDefaultNamespace, value, theLength) == true)
                {
                        fExcludeAttribute = true;
                }
                else
                {
                    if (fromCopy == false ||
                        m_resultNamespacesStack.prefixIsPresentLocal(s_emptyString) == false)
                    {
                        addResultNamespaceDecl(s_emptyString, value, theLength);
                    }
                    else
                    {
                        reportDuplicateNamespaceNodeError(s_emptyString, locator);
                    }
                }
            }
            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 && currentDefaultNamespace->empty() == false)
                {
                    addResultNamespaceDecl(s_emptyString, value, theLength);
                }
                else
                {
                    fExcludeAttribute = true;
                }
            }
        }
        else if (startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator) == true)
        {
            assert(m_executionContext != 0);

            const ECGetCachedString     prefixGuard(*m_executionContext);

            XalanDOMString&     prefix = prefixGuard.get();

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

            const XalanDOMString* const theNamespace = getResultNamespaceForPrefix(prefix);

            const XalanDOMString::size_type     theLength = length(value);

            if (theNamespace == 0)
            {
                addResultNamespaceDecl(prefix, value, theLength);
            }
            else if (equals(*theNamespace, value, theLength) == false)
            {
                if (fromCopy == false /* ||
                    m_resultNamespacesStack.prefixIsPresentLocal(prefix) == false */)
                {
                    addResultNamespaceDecl(prefix, value, theLength);
                }
                else
                {
                    reportDuplicateNamespaceNodeError(prefix, locator);
                }
            }
            else
            {
                fExcludeAttribute = true;
            }
        }

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



void
XSLTEngineImpl::reportDuplicateNamespaceNodeError(
            const XalanDOMString&   theName,
            const Locator*          locator)
{
    assert(m_executionContext != 0);

    const ECGetCachedString     theGuard(*m_executionContext);

    XalanDOMString&     theMessage =
            theGuard.get();

    if (theName.length() == 0)
    {
        XalanMessageLoader::getMessage(
            theMessage,
            XalanMessages::ErrorCopyingNamespaceNodeForDefault);
    }
    else
    {
        XalanMessageLoader::getMessage(
            theMessage,
            XalanMessages::ErrorCopyingNamespaceNode_1Param,
            theName);
    }

    error(
        theMessage,
        locator,
        m_executionContext->getCurrentNode());
}



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

    const XalanSize_t   n = thePendingAttributes.getLength();

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

    return false;
}



void
XSLTEngineImpl::flushPending()
{
    if(getHasPendingStartDocument() == true && isElementPending() == true)
    {
        assert(getFormatterListenerImpl() != 0);
        assert(m_executionContext != 0);

        if (m_stylesheetRoot->isOutputMethodSet() == false)
        {
            if (equalsIgnoreCaseASCII(
                    getPendingElementName(),
                    Constants::ELEMNAME_HTML_STRING) == true &&
                pendingAttributesHasDefaultNS() == false)
            {
                FormatterListener* const    theFormatter =
                            getFormatterListenerImpl();
                assert(theFormatter != 0);

                Writer* const theWriter = theFormatter->getWriter();

                if (theWriter == 0)
                {
                    const ECGetCachedString     theGuard(*m_executionContext);

                    XalanDOMString&     theMessage =
                        theGuard.get();

                    assert(m_stylesheetRoot->getDefaultRootRule() != 0);

                    const Locator* const theLocator =
                        m_stylesheetRoot->getDefaultRootRule()->getLocator();

                    XalanMessageLoader::getMessage(
                        theMessage,
                        XalanMessages::CannotSwitchToHTMLOutputMethod);

                    warn(
                        theMessage,
                        theLocator,
                        0);
                }
                else if (theFormatter->getOutputFormat() == FormatterListener::OUTPUT_METHOD_XML)
                {
                    // Yuck!!! Ugly hack to switch to HTML on-the-fly.
                    setFormatterListenerImpl(
                        m_executionContext->createFormatterToHTML(
                            *theFormatter->getWriter(),
                            theFormatter->getEncoding(),
                            theFormatter->getMediaType(),
                            theFormatter->getDoctypeSystem(),
                            theFormatter->getDoctypePublic(),
                            m_stylesheetRoot->getHTMLOutputIndent(),
                            theFormatter->getIndent() > 0 ?
                                theFormatter->getIndent() :
                                StylesheetExecutionContext::eDefaultHTMLIndentAmount));

                    if (m_hasCDATASectionElements == true)
                    {
                        m_hasCDATASectionElements = false;
                    }
                }
            }
        }
    }

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

    XalanDOMString&     thePendingElementName = getPendingElementNameImpl();

    if(thePendingElementName.empty() == false &&
       getMustFlushPendingStartDocument() == true)
    {
        assert(getFormatterListenerImpl() != 0);
        assert(m_executionContext != 0);

        if(m_hasCDATASectionElements == true)
        {
            m_cdataStack.push_back(isCDataResultElem(thePendingElementName));
        }

        AttributeListImpl&  thePendingAttributes =
                getPendingAttributesImpl();

        getFormatterListenerImpl()->startElement(
                thePendingElementName.c_str(),
                thePendingAttributes);

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

            fireGenerateEvent(ge);
        }

        thePendingAttributes.clear();

        thePendingElementName.clear();
    }
}



void
XSLTEngineImpl::startElement(const XalanDOMChar*    name)
{
    assert(getFormatterListenerImpl() != 0);
    assert(name != 0);

    flushPending();

    m_resultNamespacesStack.pushContext();

    setPendingElementName(name);

    setMustFlushPendingStartDocument(true);
}



void
XSLTEngineImpl::startElement(
            const XalanDOMChar*     name,
            AttributeListType&      atts)
{
    assert(getFormatterListenerImpl() != 0);
    assert(name != 0);

    flushPending();

    const XalanSize_t   nAtts = atts.getLength();

    assert(m_outputContextStack.empty() == false);

    AttributeListImpl&  thePendingAttributes =
        getPendingAttributesImpl();

    thePendingAttributes.clear();

    for (XalanSize_t 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 XalanDOMChar*  name)
{
    assert(getFormatterListenerImpl() != 0);
    assert(name != 0);

    flushPending();

    getFormatterListenerImpl()->endElement(name);

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

        fireGenerateEvent(ge);
    }

    m_resultNamespacesStack.popContext();

    if(m_hasCDATASectionElements == true)
    {
        assert(m_cdataStack.empty() == false);

        m_cdataStack.pop_back();
    }
}



void
XSLTEngineImpl::characters(
            const XalanDOMChar*     ch,
            size_type               length)
{
    characters(
        ch,
        0,
        length);
}



void
XSLTEngineImpl::characters(
            const XalanDOMChar*     ch,
            size_type               start,
            size_type               length)
{
    assert(getFormatterListenerImpl() != 0);
    assert(ch != 0);
    assert(m_hasCDATASectionElements == m_stylesheetRoot->hasCDATASectionElements());
//    assert(length != 0);

    doFlushPending();

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

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

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



void
XSLTEngineImpl::characters(const XalanNode&     node)
{
    assert(getFormatterListenerImpl() != 0);
    assert(m_hasCDATASectionElements == m_stylesheetRoot->hasCDATASectionElements());

    doFlushPending();

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

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

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



void
XSLTEngineImpl::characters(const XObjectPtr&    xobject)
{
    assert(getFormatterListenerImpl() != 0);
    assert(xobject.null() == false);
    assert(m_hasCDATASectionElements == m_stylesheetRoot->hasCDATASectionElements());

    doFlushPending();

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

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

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



void 
XSLTEngineImpl::charactersRaw(
            const XalanDOMChar*     ch,
            size_type               start,
            size_type               length)
{
    assert(ch != 0);
    assert(length != 0);

    doFlushPending();

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

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



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

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

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



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

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

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



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

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



void
XSLTEngineImpl::ignorableWhitespace(
            const XalanDOMChar*     ch,
            size_type               length)
{
    assert(getFormatterListenerImpl() != 0);
    assert(ch != 0);
    assert(length != 0);

    doFlushPending();

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

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

        fireGenerateEvent(ge);
    }
}



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

    doFlushPending();

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

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

        fireGenerateEvent(ge);
    }
}



void
XSLTEngineImpl::comment(const XalanDOMChar*     data)
{
    assert(getFormatterListenerImpl() != 0);
    assert(data != 0);

    doFlushPending();

    getFormatterListenerImpl()->comment(data);

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



void
XSLTEngineImpl::entityReference(const XalanDOMChar*     name)
{
    assert(getFormatterListenerImpl() != 0);
    assert(name != 0);

    doFlushPending();

    getFormatterListenerImpl()->entityReference(name);

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

        fireGenerateEvent(ge);
    }
}



void
XSLTEngineImpl::cdata(
            const XalanDOMChar*     ch,
            size_type               start,
            size_type               length)
{
    assert(getFormatterListenerImpl() != 0);
    assert(ch != 0);
    assert(length != 0);

    setMustFlushPendingStartDocument(true);

    flushPending();

    getFormatterListenerImpl()->cdata(ch, length);

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

        fireGenerateEvent(ge);
    }
}



void
XSLTEngineImpl::checkDefaultNamespace(
            const XalanDOMString&   theElementName,
            const XalanDOMString&   theElementNamespaceURI)
{
    // Check for elements with no prefix...
    if (indexOf(theElementName, XalanUnicode::charColon) == theElementName.length())
    {
        // Get the current default namespace URI..
        const XalanDOMString* const     theResultNamespace =
            getResultNamespaceForPrefix(s_emptyString);

        // If there is one, and the URIs are different, add a new declaration.  This
        // will also "turn-off" the default namespace, if necessary.
        if (theResultNamespace != 0 && theElementNamespaceURI != *theResultNamespace)
        {
            addResultAttribute(DOMServices::s_XMLNamespace, theElementNamespaceURI, false, 0);
        }
    }
}



void
XSLTEngineImpl::warnCopyTextNodesOnly(
            const XalanNode*    sourceNode,
            const Locator*      locator)
{
    assert(m_executionContext != 0);

    const ECGetCachedString     theGuard(*m_executionContext);

    const XalanDOMString&   theMessage =
        XalanMessageLoader::getMessage(
            theGuard.get(),
            XalanMessages::OnlyTextNodesCanBeCopied);

    warn(
        theMessage,
        locator,
        sourceNode);
}



inline void
XSLTEngineImpl::cloneToResultTree(
            const XalanText&    node,
            bool                overrideStrip)
{
    assert(m_executionContext != 0 && m_stylesheetRoot != 0);
    assert(node.getParentNode() == 0 ||
           node.getParentNode()->getNodeType() != XalanNode::DOCUMENT_NODE);

    if (overrideStrip == true ||
        m_executionContext->shouldStripSourceNode(node) == false)
    {
        const XalanDOMString&   data = node.getData();
//        assert(data.empty() == false);

        characters(data.c_str(), 0, data.length());
    }
}



void
XSLTEngineImpl::cloneToResultTree(
            const XalanNode&    node,
            bool                cloneTextNodesOnly,
            const Locator*      locator)
{
    XalanNode::NodeType     posNodeType = node.getNodeType();

    if (posNodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
    {
        outputResultTreeFragment(
                static_cast<const XalanDocumentFragment&>(node),
            cloneTextNodesOnly,
            locator);
    }
    else if (cloneTextNodesOnly == true &&
        posNodeType != XalanNode::TEXT_NODE)
    {
        warnCopyTextNodesOnly(
            &node,
            locator);
    }
    else
    {
        const XalanNode*    pos = &node;

        while(pos != 0)
        {
            if(posNodeType != XalanNode::ATTRIBUTE_NODE)
            {
                flushPending();
            }

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

            const XalanNode*    nextNode = pos->getFirstChild();

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

                if(&node == pos)
                    break;

                nextNode = pos->getNextSibling();

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

                    posNodeType = pos->getNodeType();

                    if (&node == pos)
                    {
                        if(XalanNode::ELEMENT_NODE == posNodeType)
                        {
                            endElement(pos->getNodeName().c_str());
                        }

                        nextNode = 0;
                        break;
                    }
                }
            }

            pos = nextNode;

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



inline void
createAndAddNamespaceResultAttribute(
            StylesheetExecutionContext&     theExecutionContext,
            const XalanDOMString&           thePrefix,
            const XalanDOMString&           theNamespaceURI,
            XalanDOMString&                 theTempString)
{
    theTempString = DOMServices::s_XMLNamespaceWithSeparator;
    theTempString.append(thePrefix);

    theExecutionContext.addResultAttribute(
        theTempString,
        theNamespaceURI);
}



inline void
createAndAddNamespaceResultAttribute(
            StylesheetExecutionContext&     theExecutionContext,
            const XalanDOMString&           thePrefix,
            const XalanDOMString&           theNamespaceURI)
{
    const XSLTEngineImpl::ECGetCachedString     theCachedString(theExecutionContext);

    createAndAddNamespaceResultAttribute(
        theExecutionContext,
        thePrefix,
        theNamespaceURI,
        theCachedString.get());
}



inline void
createFixedUpResultAttribute(
            StylesheetExecutionContext&     theExecutionContext,
            const XalanDOMString&           theLocalPart,
            const XalanDOMString&           theNamespaceURI,
            const XalanDOMString&           theValue)
{
    typedef StylesheetExecutionContext::GetCachedString     GetCachedString;

    const GetCachedString   theCachedString(theExecutionContext);

    XalanDOMString&     theBuffer = theCachedString.get();

    theExecutionContext.getUniqueNamespaceValue(theBuffer);

    createAndAddNamespaceResultAttribute(
        theExecutionContext,
        theBuffer,
        theNamespaceURI);

    theBuffer += XalanUnicode::charColon;

    theBuffer += theLocalPart;

    theExecutionContext.addResultAttribute(
        theBuffer,
        theValue);
}



void
XSLTEngineImpl::cloneToResultTree(
            const XalanNode&        node,
            XalanNode::NodeType     nodeType,
            bool                    overrideStrip,
            bool                    shouldCloneAttributes,
            bool                    cloneTextNodesOnly,
            const Locator*          locator)
{
    assert(nodeType == node.getNodeType());
    assert(m_executionContext != 0);

    if(cloneTextNodesOnly == true)
    {
        if (nodeType != XalanNode::TEXT_NODE)
        {
            warnCopyTextNodesOnly(
                    &node,
                    locator);
        }
        else
        {
            const XalanText&    tx =
                static_cast<const XalanText&>(node);

            cloneToResultTree(tx, overrideStrip);
        }
    }
    else
    {
        switch(nodeType)
        {
        case XalanNode::TEXT_NODE:
            {
                const XalanText&    tx =
                    static_cast<const XalanText&>(node);

                cloneToResultTree(tx, overrideStrip);
            }
            break;

        case XalanNode::ELEMENT_NODE:
            {
                const XalanDOMString&   theElementName =
                    node.getNodeName();

                startElement(theElementName.c_str());

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

                    copyNamespaceAttributes(node);
                }

                checkDefaultNamespace(theElementName, node.getNamespaceURI());
            }
            break;

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

                cdata(data.c_str(), 0, data.length());
            }
            break;

        case XalanNode::ATTRIBUTE_NODE:
            if (isElementPending() == true)
            {
                addResultAttribute(
                        getPendingAttributesImpl(),
                        node.getNodeName(),
                        node.getNodeValue(),
                        true,
                        locator);
            }
            else
            {
                const ECGetCachedString     theGuard(*m_executionContext);

                const XalanDOMString&   theMessage =
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::AttributeCannotBeAdded);

                warn(
                    theMessage,
                    locator,
                    &node);
            }
            break;

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

        case XalanNode::ENTITY_REFERENCE_NODE:
            entityReference(node.getNodeName().c_str());
            break;

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

        case XalanNode::DOCUMENT_FRAGMENT_NODE:
            assert(false);
            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:
            {
                const ECGetCachedString     theGuard(*m_executionContext);

                const XalanDOMString&   theMessage =
                    XalanMessageLoader::getMessage(
                        theGuard.get(),
                        XalanMessages::CantCreateItemInResultTree);

                warn(
                    theMessage,
                    locator,
                    &node);
            }
        break;
        }
    }
}



void
XSLTEngineImpl::outputToResultTree(
            const XObject&      value,
            bool                outputTextNodesOnly,
            const Locator*      locator)
{
    const XObject::eObjectType  type = value.getType();

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

            characters(s.c_str(), 0, s.length());
        }
        break;

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

            const NodeRefListBase::size_type    nChildren = nl.getLength();

            for(NodeRefListBase::size_type i = 0; i < nChildren; i++)
            {
                XalanNode*          pos = nl.item(i);
                assert(pos != 0);

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

                if (outputTextNodesOnly == true &&
                    posNodeType != XalanNode::TEXT_NODE)
                {
                    warnCopyTextNodesOnly(
                            pos,
                            locator);
                }
                else
                {
                    XalanNode* const    top = pos;

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

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

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

                        XalanNode*  nextNode = pos->getFirstChild();

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

                            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(pos->getNodeName().c_str());
                                    }

                                    nextNode = 0;
                                    break;
                                }
                            }
                        }

                        pos = nextNode;

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

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



void
XSLTEngineImpl::outputResultTreeFragment(
            const XalanDocumentFragment&    theTree,
            bool                            outputTextNodesOnly,
            const Locator*                  locator)
{
    for(XalanNode* child = theTree.getFirstChild(); child != 0; child = child->getNextSibling())
    {
        XalanNode*  pos = child;

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

        if (outputTextNodesOnly == true &&
            posNodeType != XalanNode::TEXT_NODE)
        {
            warnCopyTextNodesOnly(
                    pos,
                    locator);
        }
        else
        {
            XalanNode* const    top = pos;

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

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

                XalanNode*  nextNode = pos->getFirstChild();

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

                    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(pos->getNodeName().c_str());
                                }

                                nextNode = 0;

                                break;
                            }
                        }
                    }
                }

                pos = nextNode;

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



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

    bool    fResult = false;

    // We only want to worry about cdata-section-elements when we're serializing the
    // result tree, which is only when the output context is 1.
    if (m_outputContextStack.size() == 1)
    {
        const XalanDOMString::size_type     indexOfNSSep = indexOf(elementName, XalanUnicode::charColon);

        if(indexOfNSSep == elementName.length())
        {
            const XalanDOMString* const     elemNS =
                        getResultNamespaceForPrefix(s_emptyString);

            if (elemNS != 0)
            {
                fResult = m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(*elemNS, elementName));
            }
            else
            {
                fResult = m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(s_emptyString, elementName));
            }
        }
        else
        {
            const ECGetCachedString     elemLocalNameGuard(*m_executionContext);
            const ECGetCachedString     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,
                            elemLocalName));
            }
            else
            {
                const XalanDOMString* const     elemNS =
                    getResultNamespaceForPrefix(prefix);

                if(elemNS == 0)
                {
                    ECGetCachedString     theGuard(*m_executionContext);

                    error(
                        XalanMessageLoader::getMessage(
                            theGuard.get(),
                            XalanMessages::PrefixIsNotDeclared_1Param,
                            prefix),
                        0,
                        m_executionContext->getCurrentNode());
                }
                else
                {
                    fResult =
                        m_stylesheetRoot->isCDATASectionElementName(
                            XalanQNameByReference(
                                *elemNS,
                                elemLocalName));
                }
            }
        }
    }

    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,
            XalanDOMString::size_type   thePrefixLength,
            const XalanDOMChar*         theName,
            XalanDOMString::size_type   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 XalanDOMString::size_type     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,
            XalanDOMString::size_type   thePrefixLength,
            const XalanDOMString&       theName)
{
    return isPrefixUsed(thePrefix, thePrefixLength, theName.c_str(), theName.length());
}



inline bool
isPrefixUsedOrDeclared(
            const XalanDOMString&       thePrefix,
            XalanDOMString::size_type   thePrefixLength,
            const XalanDOMChar*         theName,
            XalanDOMString::size_type   theNameLength)
{
    if (isPrefixUsed(thePrefix, thePrefixLength, theName, theNameLength) == true)
    {
        return true;
    }
    else
    {
        const XalanDOMString::size_type     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, thePrefix.c_str()) == true)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}



inline bool
isPendingAttributePrefix(
            const AttributeListType&    thePendingAttributes,
            const XalanDOMString&       thePrefix,
            XalanDOMString::size_type   thePrefixLength)
{
    const XalanSize_t   thePendingAttributesCount =
                thePendingAttributes.getLength();

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

        // Check each attribute...
        for (XalanSize_t 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 XalanDOMString::size_type     thePrefixLength = thePrefix.length();
    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 XalanDOMString&   thePrefix,
            const XalanDOMString&   theName,
            const XalanNode&        theNode,
            AttributeListImpl&      thePendingAttributes,
            bool                    fOnlyIfPrefixNotPresent)
{
    if (fOnlyIfPrefixNotPresent == false ||
        m_resultNamespacesStack.prefixIsPresentLocal(thePrefix) == false)
    {
        const XalanDOMString* const     desturi = getResultNamespaceForPrefix(thePrefix);
        const XalanDOMString&           srcURI = theNode.getNodeValue();

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



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

    const XalanDOMString&   aname = theNode.getNodeName();

    if (equals(aname, DOMServices::s_XMLNamespace) == true)
    {
        // Default namespace declaration...
        addResultNamespace(s_emptyString, aname, theNode, thePendingAttributes, fOnlyIfPrefixNotPresent);
    }
    else if (startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator))
    {
        const ECGetCachedString     prefixGuard(*m_executionContext);

        XalanDOMString&     thePrefix = prefixGuard.get();

        substring(aname, thePrefix, DOMServices::s_XMLNamespaceWithSeparatorLength);

        addResultNamespace(thePrefix, aname, theNode, thePendingAttributes, fOnlyIfPrefixNotPresent);
    }
}



void
XSLTEngineImpl::copyNamespaceAttributes(const XalanNode&    src) 
{
    assert(m_attributeNamesVisited.empty() == true);

    const XalanNode*    parent = &src;

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

        const XalanSize_t   nAttrs = nnm->getLength();

        assert(m_outputContextStack.empty() == false);

        AttributeListImpl&  thePendingAttributes =
                getPendingAttributesImpl();

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

            const XalanDOMString&   nodeName = attr->getNodeName();

            using std::find_if;

            if (find_if(
                    m_attributeNamesVisited.begin(),
                    m_attributeNamesVisited.end(),
                    FindStringPointerFunctor(nodeName)) == m_attributeNamesVisited.end())
            {
                addResultNamespace(*attr, thePendingAttributes, true);

                m_attributeNamesVisited.push_back(&nodeName);
            }
        }

        parent = parent->getParentNode();
    }

    m_attributeNamesVisited.clear();
}



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

    XPath* const        theXPath = m_xpathFactory.create();

    const XPathGuard    theGuard(m_xpathFactory, theXPath);

    m_xpathProcessor->initXPath(
            *theXPath,
            m_xpathConstructionContext,
            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();

    const XPathGuard    theGuard(m_xpathFactory, theXPath);

    m_xpathProcessor->initXPath(
            *theXPath,
            m_xpathConstructionContext,
            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, 
                                         executionContext.getMemoryManager());

    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,
            m_xpathConstructionContext,
            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)
{
    addResultAttribute(attrList, attrName, attrValue, false, 0);
}



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

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

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

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

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



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



void
XSLTEngineImpl::getUniqueNamespaceValue(XalanDOMString&     theValue)
{
    do
    {
        m_scratchString.assign(s_uniqueNamespacePrefix);

        NumberToDOMString(m_uniqueNSValue++, m_scratchString);
    } while(getResultNamespaceForPrefix(m_scratchString) != 0);

    theValue.append(m_scratchString);
}



void
XSLTEngineImpl::setStylesheetParam(
            const XalanDOMString&   theName,
            const XalanDOMString&   theExpression)
{
    m_stylesheetParams[theName].m_expression = theExpression;;
}



void
XSLTEngineImpl::setStylesheetParam(
            const XalanDOMString&   theName,
            XObjectPtr              theValue)
{
    m_stylesheetParams[theName].m_value = theValue;
}



void
XSLTEngineImpl::clearStylesheetParams()
{
    m_stylesheetParams.clear();
}



void
XSLTEngineImpl::resolveTopLevelParams(StylesheetExecutionContext&   executionContext)
{
    typedef ParamMapType::const_iterator    const_iterator;

    MemoryManager&  theManager = getMemoryManager();

    assert(m_topLevelParams.size() == 0);

    m_topLevelParams.reserve(m_stylesheetParams.size());

    for (const_iterator i = m_stylesheetParams.begin();
            i != m_stylesheetParams.end();
                ++i)
    {
        const XalanDOMString&   theName = (*i).first;
        const XalanParamHolder& theCurrent = (*i).second;

        const XalanQNameByValue     theQName(theName, theManager, m_stylesheetRoot);

        const XalanDOMString&   theExpression = theCurrent.m_expression;

        if (theExpression.length() > 0)
        {
            const TopLevelArg   theArg(
                                    theManager,
                                    theQName,
                                    theExpression);

            m_topLevelParams.push_back(theArg);
        }
        else
        {
            const TopLevelArg   theArg(
                                    theManager,
                                    theQName,
                                    theCurrent.m_value);

            m_topLevelParams.push_back(theArg);
        }
    }

    executionContext.pushTopLevelVariables(m_topLevelParams);
}



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



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

        flushPending();
    }

    setFormatterListenerImpl(flistener);
}



void
XSLTEngineImpl::fireCharacterGenerateEvent(
            const XalanNode&    theNode,
            bool                isCDATA)
{
    XalanDOMString  theBuffer(getMemoryManager());
    
    DOMServices::getNodeData(theNode, *m_executionContext, theBuffer);

    fireCharacterGenerateEvent(theBuffer, isCDATA);
}



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



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



void
XSLTEngineImpl::fireCharacterGenerateEvent(
            const XalanDOMChar*     ch,
            size_type               start,
            size_type               length,
            bool                    isCDATA)
{
    const GenerateEvent     ge(
        isCDATA == true ? GenerateEvent::EVENTTYPE_CDATA : GenerateEvent::EVENTTYPE_CHARACTERS,
         getMemoryManager(),
        ch,
        start,
        length);

    fireGenerateEvent(ge);
}


void
XSLTEngineImpl::error(
            const XalanDOMString&   theMessage,
            const Locator*          theLocator,
            const XalanNode*        theSourceNode)
{
    problem(
        eXSLTProcessor,
        eError,
        theMessage,
        theLocator,
        theSourceNode);
}



void
XSLTEngineImpl::warn(
            const XalanDOMString&   theMessage,
            const Locator*          theLocator,
            const XalanNode*        theSourceNode)
{
    problem(
        eXSLTProcessor,
        eWarning,
        theMessage,
        theLocator,
        theSourceNode);
}



void
XSLTEngineImpl::message(
            const XalanDOMString&   theMessage,
            const Locator*          theLocator,
            const XalanNode*        theSourceNode)
{
    problem(
        eXSLTProcessor,
        eMessage,
        theMessage,
        theLocator,
        theSourceNode);
}



void
XSLTEngineImpl::installFunctions(MemoryManager& theManager)
{
    XPath::installFunction(XPathFunctionTable::s_current, FunctionCurrent());
    XPath::installFunction(XPathFunctionTable::s_document, FunctionDocument());
    XPath::installFunction(XPathFunctionTable::s_elementAvailable, FunctionElementAvailable());
    XPath::installFunction(XPathFunctionTable::s_functionAvailable, FunctionFunctionAvailable());
    XPath::installFunction(XPathFunctionTable::s_formatNumber, FunctionFormatNumber());
    XPath::installFunction(XPathFunctionTable::s_generateId, FunctionGenerateID());
    XPath::installFunction(XPathFunctionTable::s_key, FunctionKey());

    const FunctionSystemProperty    temp(theManager);

    XPath::installFunction(XPathFunctionTable::s_systemProperty, temp);
    XPath::installFunction(XPathFunctionTable::s_unparsedEntityUri, FunctionUnparsedEntityURI());
}



void
XSLTEngineImpl::uninstallFunctions()
{
    XPath::uninstallFunction(XPathFunctionTable::s_current);
    XPath::uninstallFunction(XPathFunctionTable::s_document);
    XPath::uninstallFunction(XPathFunctionTable::s_elementAvailable);
    XPath::uninstallFunction(XPathFunctionTable::s_functionAvailable);
    XPath::uninstallFunction(XPathFunctionTable::s_formatNumber);
    XPath::uninstallFunction(XPathFunctionTable::s_generateId);
    XPath::uninstallFunction(XPathFunctionTable::s_key);
    XPath::uninstallFunction(XPathFunctionTable::s_systemProperty);
    XPath::uninstallFunction(XPathFunctionTable::s_unparsedEntityUri);
}



}


using xalanc::XalanDOMString;

using xalanc::XalanMemMgrs;

static XalanDOMString   s_XSLNameSpaceURL(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_XalanNamespaceURL(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_uniqueNamespacePrefix(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_stylesheetNodeName(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_typeString(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_hrefString(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_piTokenizerString(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_typeValueString1(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_typeValueString2(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_typeValueString3(XalanMemMgrs::getDummyMemMgr());

static XalanDOMString   s_typeValueString4(XalanMemMgrs::getDummyMemMgr());



namespace XALAN_CPP_NAMESPACE {



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

const XalanDOMString&   XSLTEngineImpl::s_XalanNamespaceURL = ::s_XalanNamespaceURL;

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

const XalanDOMString&   XSLTEngineImpl::s_stylesheetNodeName = ::s_stylesheetNodeName;

const XalanDOMString&   XSLTEngineImpl::s_typeString = ::s_typeString;

const XalanDOMString&   XSLTEngineImpl::s_hrefString = ::s_hrefString;

const XalanDOMString&   XSLTEngineImpl::s_piTokenizerString = ::s_piTokenizerString;

const XalanDOMString&   XSLTEngineImpl::s_typeValueString1 = ::s_typeValueString1;

const XalanDOMString&   XSLTEngineImpl::s_typeValueString2 = ::s_typeValueString2;

const XalanDOMString&   XSLTEngineImpl::s_typeValueString3 = ::s_typeValueString3;

const XalanDOMString&   XSLTEngineImpl::s_typeValueString4 = ::s_typeValueString4;


#if 0
#include <fstream>

void
dumpTable(
            const XSLTEngineImpl::ElementKeysMapType&   theTable,
            std::ostream&                               theSourceStream,
            std::ostream&                               theHeaderStream)
{
    XSLTEngineImpl::ElementKeysMapType::const_iterator  i = theTable.begin();

    while(i != theTable.end())
    {
        theSourceStream << "const XalanDOMChar\tXSLTEngineImpl::s_";

        const XalanDOMString&   theString = (*i).first;

        theHeaderStream << "\t// The string \"" << theString << "\"\n\tstatic const XalanDOMChar\ts_";

        bool    nextCap = false;

        XalanDOMString::const_iterator  j = theString.begin();

        while(*j)
        {
            if (*j == '-')
            {
                nextCap = true;
            }
            else
            {
                assert(*j >= 'a' && *j <= 'z');

                if (nextCap)
                {
                    theSourceStream << char(*j -'a' + 'A');
                    theHeaderStream << char(*j -'a' + 'A');

                    nextCap = false;
                }
                else
                {
                    theSourceStream << char(*j);
                    theHeaderStream << char(*j);
                }
            }

            ++j;
        }

        j = theString.begin();

        theSourceStream << "[] =\n{\n";
        theHeaderStream << "[];\n\n";

        while(*j)
        {
            if (*j == '-')
            {
                theSourceStream << "\tXalanUnicode::charHyphenMinus,\n";
            }
            else
            {
                assert(*j >= 'a' && *j <= 'z');

                theSourceStream << "\tXalanUnicode::charLetter_";

                theSourceStream << char(*j) << ",\n";
            }

            ++j;
        }

        theSourceStream << "\t0\n};\n\n";

        ++i;
    }
}
#endif


void
XSLTEngineImpl::initialize(MemoryManager&      theManager)
{
    ::s_XSLNameSpaceURL.reset( theManager, "http://www.w3.org/1999/XSL/Transform");

    ::s_XalanNamespaceURL.reset( theManager, "http://xml.apache.org/xalan");

    ::s_uniqueNamespacePrefix.reset( theManager, "ns");

    ::s_stylesheetNodeName.reset( theManager, "xml-stylesheet");

    ::s_typeString.reset( theManager, "type");

    XalanDOMString tmpString1(Constants::ATTRNAME_HREF, theManager);

    ::s_hrefString.swap(tmpString1);

    ::s_piTokenizerString.reset( theManager, " \t=");

    ::s_typeValueString1.reset( theManager, "text/xml");

    ::s_typeValueString2.reset( theManager, "text/xsl");

    ::s_typeValueString3.reset( theManager, "application/xml");

    ::s_typeValueString4.reset( theManager, "application/xml+xslt");

    installFunctions(theManager);
}



void
XSLTEngineImpl::terminate()
{
    uninstallFunctions();

    MemoryManager& theManager = XalanMemMgrs::getDummyMemMgr();

    releaseMemory(::s_uniqueNamespacePrefix, theManager);

    releaseMemory(::s_XalanNamespaceURL, theManager);

    releaseMemory(::s_XSLNameSpaceURL, theManager);

    releaseMemory(::s_stylesheetNodeName, theManager);

    releaseMemory(::s_typeString, theManager);

    releaseMemory(::s_hrefString, theManager);

    releaseMemory(::s_piTokenizerString, theManager);

    releaseMemory(::s_typeValueString1, theManager);

    releaseMemory(::s_typeValueString2, theManager);

    releaseMemory(::s_typeValueString3, theManager);

    releaseMemory(::s_typeValueString4, theManager);
}



}
