blob: 9c5bd958680f001937aef0fbf0b7dbdf440c7c9d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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);
}
}