blob: 553f7af038494e2a0e68378d204af338900d929e [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.
*/
#include "XalanTransformer.hpp"
#include <algorithm>
#include <iostream>
#include <cstring>
#include <xercesc/sax/SAXParseException.hpp>
#include <xalanc/XalanDOM/XalanDOMException.hpp>
#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
#include <xalanc/PlatformSupport/DOMStringPrintWriter.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/XalanOutputStreamPrintWriter.hpp>
#include <xalanc/XPath/XObjectFactoryDefault.hpp>
#include <xalanc/XPath/XPathFactoryBlock.hpp>
#include <xalanc/XSLT/StylesheetConstructionContextDefault.hpp>
#include <xalanc/XSLT/StylesheetExecutionContextDefault.hpp>
#include <xalanc/XSLT/StylesheetRoot.hpp>
#include <xalanc/XSLT/XSLTEngineImpl.hpp>
#include <xalanc/XSLT/XSLTInit.hpp>
#include <xalanc/XSLT/XSLTProcessorEnvSupportDefault.hpp>
#include <xalanc/XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
#include <xalanc/XalanSourceTree/XalanSourceTreeParserLiaison.hpp>
#include <xalanc/XalanExtensions/XalanExtensions.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTCommon.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTDynamic.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTMath.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTSet.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTString.hpp>
#include <xalanc/XalanEXSLT/XalanEXSLTDateTime.hpp>
//#define XALAN_USE_ICU
#if defined(XALAN_USE_ICU)
#include <xalanc/ICUBridge/ICUBridgeCleanup.hpp>
#include <xalanc/ICUBridge/ICUBridgeCollationCompareFunctor.hpp>
#include <xalanc/ICUBridge/ICUFormatNumberFunctor.hpp>
#endif
#include "XalanCompiledStylesheetDefault.hpp"
#include "XalanDefaultDocumentBuilder.hpp"
#include "XalanDefaultParsedSource.hpp"
#include "XalanTransformerOutputStream.hpp"
#include "XalanTransformerProblemListener.hpp"
#include "XercesDOMParsedSource.hpp"
namespace XALAN_CPP_NAMESPACE {
const XSLTInputSource* XalanTransformer::s_emptyInputSource = 0;
const XSLTInit* XalanTransformer::s_xsltInit = 0;
static MemoryManager* s_initMemoryManager = 0;
XalanTransformer::XalanTransformer(MemoryManager& theManager):
m_memoryManager(theManager),
m_compiledStylesheets(m_memoryManager),
m_parsedSources(m_memoryManager),
m_params(m_memoryManager),
m_functions(m_memoryManager),
m_traceListeners(m_memoryManager),
m_errorMessage(1, '\0', m_memoryManager),
m_useValidation(false),
m_entityResolver(0),
m_xmlEntityResolver(0),
m_errorHandler(0),
m_externalSchemaLocation(m_memoryManager),
m_externalNoNamespaceSchemaLocation(m_memoryManager),
m_problemListener(0),
m_errorStream(0),
m_warningStream(&std::cerr),
m_outputEncoding(m_memoryManager),
m_topXObjectFactory(XObjectFactoryDefault::create(m_memoryManager)),
m_stylesheetExecutionContext(StylesheetExecutionContextDefault::create(m_memoryManager))
{
#if defined(XALAN_USE_ICU)
// Create a collation function for the ICU, and have it
// cache collators...
XalanMemMgrAutoPtr<ICUBridgeCollationCompareFunctor> theICUFunctor(m_memoryManager, ICUBridgeCollationCompareFunctor::create(m_memoryManager, true));
m_stylesheetExecutionContext->installCollationCompareFunctor(theICUFunctor.get());
XalanMemMgrAutoPtr<ICUFormatNumberFunctor> theFormatNumberFunctor(m_memoryManager, ICUFormatNumberFunctor::create(m_memoryManager));
m_stylesheetExecutionContext->installFormatNumberFunctor(theFormatNumberFunctor.get());
theICUFunctor.release();
theFormatNumberFunctor.release();
#endif
}
XalanTransformer::~XalanTransformer()
{
// Clean up Top-Level Parameters
clearStylesheetParams();
using std::for_each;
// Clean up the XalanCompiledStylesheet vector.
for_each(
m_compiledStylesheets.begin(),
m_compiledStylesheets.end(),
DeleteFunctor<XalanCompiledStylesheet>(m_memoryManager));
// Clean up the XalanParsedSource vector.
for_each(
m_parsedSources.begin(),
m_parsedSources.end(),
DeleteFunctor<XalanParsedSource>(m_memoryManager));
// Clean up the Function map.
for_each(
m_functions.begin(),
m_functions.end(),
MapValueDeleteFunctor<FunctionMapType>(m_memoryManager));
#if defined(XALAN_USE_ICU)
// Uninstall the ICU collation compare functor, and destroy it...
XalanDestroy(
m_memoryManager,
m_stylesheetExecutionContext->uninstallCollationCompareFunctor());
// Uninstall the ICU format number functor, and destroy it...
XalanDestroy(
m_memoryManager,
m_stylesheetExecutionContext->uninstallFormatNumberFunctor());
#endif
XalanDestroy(
m_memoryManager,
*m_topXObjectFactory);
XalanDestroy(
m_memoryManager,
*m_stylesheetExecutionContext);
}
void
XalanTransformer::initialize(MemoryManager& theManager)
{
// Initialize Xalan.
XalanMemMgrAutoPtr<XSLTInit> initGuard(theManager, XSLTInit::create(theManager));
XalanAutoPtr<XSLTInputSource> inputSourceGuard(new (&theManager) XSLTInputSource(theManager));
EnsureFunctionsInstallation instalGuard(theManager);
instalGuard.install();
instalGuard.release();
s_xsltInit = initGuard.releasePtr();
s_emptyInputSource = inputSourceGuard.release();
s_initMemoryManager = &theManager;
}
void
XalanTransformer::terminate()
{
assert(s_initMemoryManager != 0);
{
const EnsureFunctionsInstallation uninstallGuard(*s_initMemoryManager);
}
delete s_emptyInputSource;
XalanDestroy(
*s_initMemoryManager,
const_cast<XSLTInit*>(s_xsltInit));
s_emptyInputSource = 0;
s_xsltInit = 0;
s_initMemoryManager = 0;
}
void
XalanTransformer::ICUCleanUp()
{
#if defined(XALAN_USE_ICU)
ICUBridgeCleanup::cleanup();
#endif
}
#if defined(XALAN_USE_ICU)
void
ICUStartUp(MemoryManager& theManager)
{
ICUBridgeCleanup::startup(theManager);
}
#else
void
ICUStartUp(MemoryManager& /*theManager*/)
{
}
#endif
bool
XalanTransformer::getICUAvailable() const
{
#if defined(XALAN_USE_ICU)
return true;
#else
return false;
#endif
}
static void
addTraceListeners(
const XalanTransformer::TraceListenerVectorType& theTraceListeners,
XSLTEngineImpl& theEngine)
{
if (theTraceListeners.empty() == false)
{
typedef XalanTransformer::TraceListenerVectorType TraceListenerVectorType;
TraceListenerVectorType::const_iterator theEnd = theTraceListeners.end();
for(TraceListenerVectorType::const_iterator i = theTraceListeners.begin(); i != theEnd; ++i)
{
theEngine.addTraceListener(*i);
}
theEngine.setTraceSelects(true);
}
}
int
XalanTransformer::transform(
const XSLTInputSource& theInputSource,
const XalanCompiledStylesheet* theCompiledStylesheet,
const XSLTResultTarget& theResultTarget)
{
const XalanParsedSource* theParsedSource = 0;
const int theResult = parseSource(theInputSource, theParsedSource);
if (theResult != 0)
{
return theResult;
}
else
{
assert(theParsedSource != 0);
// Make sure the parsed source is destroyed when
// the transformation is finished...
EnsureDestroyParsedSource theGuard(*this, theParsedSource);
// Do the transformation...
return transform(
*theParsedSource,
theCompiledStylesheet,
theResultTarget);
}
}
int
XalanTransformer::transform(
const XSLTInputSource& theInputSource,
const XSLTInputSource& theStylesheetSource,
const XSLTResultTarget& theResultTarget)
{
// Parse the source document.
const XalanParsedSource* theParsedSource = 0;
const int theResult = parseSource(theInputSource, theParsedSource);
if (theResult != 0)
{
return theResult;
}
else
{
assert(theParsedSource != 0);
// Make sure the parsed source is destroyed when
// the transformation is finished...
EnsureDestroyParsedSource theGuard(*this, theParsedSource);
// Do the transformation...
return transform(
*theParsedSource,
theStylesheetSource,
theResultTarget);
}
}
int
XalanTransformer::transform(
const XSLTInputSource& theInputSource,
const XSLTInputSource& theStylesheetSource,
void* theOutputHandle,
XalanOutputHandlerType theOutputHandler,
XalanFlushHandlerType theFlushHandler)
{
// Set to output target to the callback
XalanTransformerOutputStream theOutputStream(m_memoryManager, theOutputHandle, theOutputHandler, theFlushHandler);
XalanOutputStreamPrintWriter thePrintWriter(theOutputStream);
XSLTResultTarget theResultTarget(&thePrintWriter, m_memoryManager);
// Do the transformation...
return transform(
theInputSource,
theStylesheetSource,
theResultTarget);
}
int
XalanTransformer::transform(
const XalanParsedSource& theParsedSource,
const XalanCompiledStylesheet* theCompiledStylesheet,
void* theOutputHandle,
XalanOutputHandlerType theOutputHandler,
XalanFlushHandlerType theFlushHandler)
{
// Set to output target to the callback
XalanTransformerOutputStream theOutputStream(m_memoryManager, theOutputHandle, theOutputHandler, theFlushHandler);
XalanOutputStreamPrintWriter thePrintWriter(theOutputStream);
XSLTResultTarget theResultTarget(&thePrintWriter, m_memoryManager);
// Do the transformation...
return transform(
theParsedSource,
theCompiledStylesheet,
theResultTarget);
}
int
XalanTransformer::transform(
const XSLTInputSource& theInputSource,
void* theOutputHandle,
XalanOutputHandlerType theOutputHandler,
XalanFlushHandlerType theFlushHandler)
{
assert(s_emptyInputSource != 0);
// Set to output target to the callback
XalanTransformerOutputStream theOutputStream(m_memoryManager, theOutputHandle, theOutputHandler, theFlushHandler);
XalanOutputStreamPrintWriter thePrintWriter(theOutputStream);
XSLTResultTarget theResultTarget(&thePrintWriter, m_memoryManager);
// Do the transformation...
return transform(
theInputSource,
*s_emptyInputSource,
theResultTarget);
}
using xercesc::XMLException;
using xercesc::SAXParseException;
using xercesc::SAXException;
static const XalanDOMString&
FormatSAXParseException(
XPathExecutionContext& theExecutionContext,
const SAXParseException& theException,
XalanDOMString& theErrorMessage)
{
assert(theException.getMessage() != 0);
const XalanDOMChar theDummy = 0;
const XalanDOMChar* const theSystemID = theException.getSystemId();
typedef XPathExecutionContext::GetCachedString GetCachedString;
const GetCachedString theGuard(theExecutionContext);
XalanDOMString& theExceptionType = theGuard.get();
theExceptionType.assign("SAXParseException");
XSLException::defaultFormat(
theException.getMessage(),
theSystemID == 0 ? &theDummy : theSystemID,
theException.getLineNumber(),
theException.getColumnNumber(),
theExceptionType.c_str(),
theErrorMessage);
return theErrorMessage;
}
static void
FormatSAXParseException(
XPathExecutionContext& theExecutionContext,
const SAXParseException& theException,
CharVectorType& theErrorMessage)
{
typedef XPathExecutionContext::GetCachedString GetCachedString;
const GetCachedString theGuard(theExecutionContext);
TranscodeToLocalCodePage(
FormatSAXParseException(
theExecutionContext,
theException,
theGuard.get()),
theErrorMessage,
true);
}
static void
FormatXalanDOMException(
XPathExecutionContext& theExecutionContext,
const XalanDOMException& theException,
CharVectorType& theErrorMessage)
{
typedef XPathExecutionContext::GetCachedString GetCachedString;
const GetCachedString theGuard1(theExecutionContext);
const GetCachedString theGuard2(theExecutionContext);
const XalanDOMString& theMessage =
XalanMessageLoader::getMessage(
theGuard1.get(),
XalanMessages::XalanDOMExceptionCaught_1Param,
NumberToDOMString(
theException.getExceptionCode(),
theGuard2.get()));
TranscodeToLocalCodePage(theMessage, theErrorMessage, true);
}
static void
LoadErrorMessage(
XPathExecutionContext& theExecutionContext,
XalanMessages::Codes theCode,
CharVectorType& theMessage)
{
typedef XPathExecutionContext::GetCachedString GetCachedString;
const GetCachedString theGuard(theExecutionContext);
const XalanDOMString& theMessageString =
XalanMessageLoader::getMessage(
theGuard.get(),
theCode);
try
{
theMessageString.transcode(theMessage);
}
catch(...)
{
const char* const theAlternateErrorMessage =
"An error occurred transcoding an error message.";
const XalanDOMString::size_type theLength =
length(theAlternateErrorMessage);
theMessage.resize(theLength + 1);
using std::strncpy;;
strncpy(
&*theMessage.begin(),
theAlternateErrorMessage,
theLength);
}
}
int
XalanTransformer::compileStylesheet(
const XSLTInputSource& theStylesheetSource,
const XalanCompiledStylesheet*& theCompiledStylesheet)
{
// Clear the error message.
m_errorMessage.resize(1, '\0');
// Store error messages from problem listener.
XalanDOMString theErrorMessage(m_memoryManager);
int theResult = 0;
try
{
// Create some support objects that are necessary for running the processor...
XalanSourceTreeDOMSupport theDOMSupport;
XalanSourceTreeParserLiaison theParserLiaison(theDOMSupport, m_memoryManager);
theParserLiaison.setEntityResolver(m_entityResolver);
theParserLiaison.setXMLEntityResolver(m_xmlEntityResolver);
theParserLiaison.setErrorHandler(m_errorHandler);
// Hook the two together...
theDOMSupport.setParserLiaison(&theParserLiaison);
// Create some more support objects...
XSLTProcessorEnvSupportDefault theXSLTProcessorEnvSupport(m_memoryManager);
XObjectFactoryDefault theXObjectFactory(m_memoryManager);
XPathFactoryBlock theXPathFactory(m_memoryManager);
// Create a processor...
XSLTEngineImpl theProcessor(
m_memoryManager,
theParserLiaison,
theXSLTProcessorEnvSupport,
theDOMSupport,
theXObjectFactory,
theXPathFactory);
// Create a problem listener and send output to a XalanDOMString.
DOMStringPrintWriter thePrintWriter(theErrorMessage);
XalanTransformerProblemListener theProblemListener( m_memoryManager, m_warningStream, &thePrintWriter);
if (m_problemListener == 0)
{
theProcessor.setProblemListener(&theProblemListener);
}
else
{
theProcessor.setProblemListener(m_problemListener);
}
// Allocate the memory now, to avoid leaking if push_back() fails.
m_compiledStylesheets.reserve(m_compiledStylesheets.size() + 1);
// Create a new XalanCompiledStylesheet.
theCompiledStylesheet =
XalanCompiledStylesheetDefault::create(
m_memoryManager,
theStylesheetSource,
theProcessor,
m_errorHandler,
m_entityResolver);
// Store it in a vector.
m_compiledStylesheets.push_back(theCompiledStylesheet);
}
catch(const XSLException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
}
theResult = -1;
}
catch(const SAXParseException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
FormatSAXParseException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
}
theResult = -2;
}
catch(const SAXException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
}
theResult = -2;
}
catch(const XMLException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
}
theResult = -3;
}
catch(const XalanDOMException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
FormatXalanDOMException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
}
theResult = -4;
}
return theResult;
}
int
XalanTransformer::destroyStylesheet(const XalanCompiledStylesheet* theStylesheet)
{
using std::find;
const CompiledStylesheetPtrVectorType::iterator i =
find(
m_compiledStylesheets.begin(),
m_compiledStylesheets.end(),
theStylesheet);
if (i == m_compiledStylesheets.end())
{
LoadErrorMessage(
*m_stylesheetExecutionContext,
XalanMessages::InvalidCompiledStylesheetProvided,
m_errorMessage);
return -1;
}
else
{
m_compiledStylesheets.erase(i);
XalanDestroy(
m_memoryManager,
const_cast<XalanCompiledStylesheet*>(theStylesheet));
return 0;
}
}
int
XalanTransformer::parseSource(
const XSLTInputSource& theInputSource,
const XalanParsedSource*& theParsedSource,
bool useXercesDOM)
{
// Clear the error message.
m_errorMessage.clear();
m_errorMessage.push_back(0);
int theResult = 0;
try
{
// Allocate the memory now, to avoid leaking if push_back() fails.
m_parsedSources.reserve(m_parsedSources.size() + 1);
if(useXercesDOM == true)
{
theParsedSource =
XercesDOMParsedSource::create(
m_memoryManager,
theInputSource,
m_useValidation,
m_errorHandler,
m_entityResolver,
m_xmlEntityResolver,
getExternalSchemaLocation(),
getExternalNoNamespaceSchemaLocation());
}
else
{
theParsedSource =
XalanDefaultParsedSource::create(
m_memoryManager,
theInputSource,
m_useValidation,
m_errorHandler,
m_entityResolver,
m_xmlEntityResolver,
getExternalSchemaLocation(),
getExternalNoNamespaceSchemaLocation());
}
// Store it in a vector.
m_parsedSources.push_back(theParsedSource);
}
catch(const XSLException& e)
{
XalanDOMString theBuffer(m_memoryManager);
e.defaultFormat(theBuffer);
TranscodeToLocalCodePage(theBuffer, m_errorMessage, true);
theResult = -1;
}
catch(const SAXParseException& e)
{
FormatSAXParseException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
theResult = -2;
}
catch(const SAXException& e)
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
theResult = -2;
}
catch(const XMLException& e)
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
theResult = -3;
}
catch(const XalanDOMException& e)
{
FormatXalanDOMException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
theResult = -4;
}
return theResult;
}
int
XalanTransformer::destroyParsedSource(const XalanParsedSource* theParsedSource)
{
using std::find;
const ParsedSourcePtrVectorType::iterator i =
find(
m_parsedSources.begin(),
m_parsedSources.end(),
theParsedSource);
if (i == m_parsedSources.end())
{
LoadErrorMessage(
*m_stylesheetExecutionContext,
XalanMessages::InvalidParsedSourceProvided,
m_errorMessage);
return -1;
}
else
{
m_parsedSources.erase(i);
assert(theParsedSource != 0);
XalanDestroy(
m_memoryManager,
const_cast<XalanParsedSource*>(theParsedSource));
return 0;
}
}
void
XalanTransformer::setStylesheetParam(
const XalanDOMString& qname,
const XalanDOMString& expression)
{
m_params[qname].m_expression = expression;
}
void
XalanTransformer::setStylesheetParam(
const XalanDOMString& qname,
XObjectPtr object)
{
m_params[qname].m_value = object;
}
void
XalanTransformer::setStylesheetParam(
const char* qname,
XObjectPtr object)
{
setStylesheetParam(
XalanDOMString(qname, m_memoryManager),
object);
}
void
XalanTransformer::setStylesheetParam(
const char* qname,
const char* expression)
{
setStylesheetParam(
XalanDOMString(qname, m_memoryManager),
XalanDOMString(expression, m_memoryManager));
}
void
XalanTransformer::setStylesheetParam(
const char* qname,
double number)
{
setStylesheetParam(
XalanDOMString(qname, m_memoryManager),
m_topXObjectFactory->createNumber(number));
}
void
XalanTransformer::setStylesheetParam(
const XalanDOMString& qname,
double number)
{
setStylesheetParam(
qname,
m_topXObjectFactory->createNumber(number));
}
void
XalanTransformer::setStylesheetParam(
const char* qname,
XalanNode* nodeset)
{
setStylesheetParam(
XalanDOMString(qname, m_memoryManager),
m_topXObjectFactory->createNodeSet(nodeset));
}
void
XalanTransformer::setStylesheetParam(
const XalanDOMString& qname,
XalanNode* nodeset)
{
setStylesheetParam(
qname,
m_topXObjectFactory->createNodeSet(nodeset));
}
bool
XalanTransformer::removeTraceListener(TraceListener* theTraceListener)
{
using std::find;
const TraceListenerVectorType::iterator i =
find(
m_traceListeners.begin(),
m_traceListeners.end(),
theTraceListener);
if (i == m_traceListeners.end())
{
return false;
}
else
{
m_traceListeners.erase(i);
return true;
}
}
XalanDocumentBuilder*
XalanTransformer::createDocumentBuilder(const XalanDOMString& theURI)
{
m_parsedSources.reserve(m_parsedSources.size() + 1);
XalanDocumentBuilder* const theNewBuilder = XalanDefaultDocumentBuilder::create( m_memoryManager, theURI);
m_parsedSources.push_back(theNewBuilder);
return theNewBuilder;
}
void
XalanTransformer::destroyDocumentBuilder(XalanDocumentBuilder* theDocumentBuilder)
{
destroyParsedSource(theDocumentBuilder);
}
void
XalanTransformer::installExternalFunction(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
const Function& function)
{
const XalanQNameByValue theQName(theNamespace, functionName, m_memoryManager);
Function*& theFunction =
m_functions[theQName];
Function* const theOldFunction =
theFunction;
theFunction = function.clone(m_memoryManager);
XalanDestroy<Function>(
m_memoryManager,
theOldFunction);
}
void
XalanTransformer::installExternalFunctionGlobal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName,
const Function& function)
{
XSLTProcessorEnvSupportDefault::installExternalFunctionGlobal(
theNamespace,
functionName,
function);
}
void
XalanTransformer::uninstallExternalFunction(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName)
{
const XalanQNameByValue theQName(theNamespace, functionName, m_memoryManager);
FunctionMapType::iterator i =
m_functions.find(theQName);
if (i != m_functions.end())
{
Function* const theFunction = (*i).second;
assert(theFunction != 0);
m_functions.erase(i);
XalanDestroy(
m_memoryManager,
*theFunction);
}
}
void
XalanTransformer::uninstallExternalFunctionGlobal(
const XalanDOMString& theNamespace,
const XalanDOMString& functionName)
{
XSLTProcessorEnvSupportDefault::uninstallExternalFunctionGlobal(
theNamespace,
functionName);
}
int
XalanTransformer::getIndent() const
{
return m_stylesheetExecutionContext->getIndent();
}
void
XalanTransformer::setIndent(int indentAmount)
{
m_stylesheetExecutionContext->setIndent(indentAmount);
}
XalanTransformer::eEscapeURLs
XalanTransformer::getEscapeURLs() const
{
eEscapeURLs escapeValue = eEscapeURLsDefault;
switch(m_stylesheetExecutionContext->getEscapeURLs())
{
case StylesheetExecutionContextDefault::eEscapeURLsDefault:
break;
case StylesheetExecutionContextDefault::eEscapeURLsNo:
escapeValue = eEscapeURLsNo;
break;
case StylesheetExecutionContextDefault::eEscapeURLsYes:
escapeValue = eEscapeURLsYes;
break;
default:
assert(false);
break;
}
return escapeValue;
}
void
XalanTransformer::setEscapeURLs(eEscapeURLs value)
{
StylesheetExecutionContextDefault::eEscapeURLs escapeValue =
StylesheetExecutionContextDefault::eEscapeURLsDefault;
switch(value)
{
case eEscapeURLsDefault:
break;
case eEscapeURLsNo:
escapeValue = StylesheetExecutionContextDefault::eEscapeURLsNo;
break;
case eEscapeURLsYes:
escapeValue = StylesheetExecutionContextDefault::eEscapeURLsYes;
break;
default:
assert(false);
break;
}
m_stylesheetExecutionContext->setEscapeURLs(escapeValue);
}
XalanTransformer::eOmitMETATag
XalanTransformer::getOmitMETATag() const
{
eOmitMETATag omitValue = eOmitMETATagDefault;
switch(m_stylesheetExecutionContext->getOmitMETATag())
{
case StylesheetExecutionContextDefault::eOmitMETATagDefault:
break;
case StylesheetExecutionContextDefault::eOmitMETATagNo:
omitValue = eOmitMETATagNo;
break;
case StylesheetExecutionContextDefault::eOmitMETATagYes:
omitValue = eOmitMETATagYes;
break;
default:
assert(false);
break;
}
return omitValue;
}
void
XalanTransformer::setOmitMETATag(eOmitMETATag value)
{
StylesheetExecutionContextDefault::eOmitMETATag omitValue =
StylesheetExecutionContextDefault::eOmitMETATagDefault;
switch(value)
{
case eOmitMETATagDefault:
break;
case eOmitMETATagNo:
omitValue = StylesheetExecutionContextDefault::eOmitMETATagNo;
break;
case eOmitMETATagYes:
omitValue = StylesheetExecutionContextDefault::eOmitMETATagYes;
break;
default:
assert(false);
break;
}
m_stylesheetExecutionContext->setOmitMETATag(omitValue);
}
void
XalanTransformer::reset()
{
try
{
// Reset objects.
m_stylesheetExecutionContext->setXPathEnvSupport(0);
m_stylesheetExecutionContext->setDOMSupport(0);
m_stylesheetExecutionContext->setXObjectFactory(0);
m_stylesheetExecutionContext->setXSLTProcessor(0);
m_stylesheetExecutionContext->reset();
// JIRA-451 Preserve top-level parameters across reset()
// The reset() is done to prepare for a new transformation
// by reusing the m_stylesheetExecutionContext.
//
// Absense of clearStylesheetParams() makes the top-level params
// sticky across transformations. The clearStylesheetParams()
// purges the top-level parameters from the XalanTransformer
// instance.
//
// Presence of clearStylesheetParams() will require the application
// to submit a new set of top-level parameters to the XalanTransformer
// if needed for the next doTransform() operation.
//
// clearStylesheetParams();
}
catch(...)
{
}
}
XalanTransformer::EnsureReset::~EnsureReset()
{
m_transformer.m_stylesheetExecutionContext->reset();
m_transformer.reset();
}
int
XalanTransformer::doTransform(
const XalanParsedSource& theParsedXML,
const XalanCompiledStylesheet* theCompiledStylesheet,
const XSLTInputSource* theStylesheetSource,
const XSLTResultTarget& theResultTarget)
{
int theResult = 0;
// Clear the error message.
m_errorMessage.resize(1, '\0');
// Store error messages from problem listener.
XalanDOMString theErrorMessage(m_memoryManager);
try
{
XalanDocument* const theSourceDocument = theParsedXML.getDocument();
assert(theSourceDocument != 0);
// Create the helper object that is necessary for running the processor...
XalanMemMgrAutoPtr<XalanParsedSourceHelper> theHelper(m_memoryManager, theParsedXML.createHelper(m_memoryManager));
assert(theHelper.get() != 0);
DOMSupport& theDOMSupport = theHelper->getDOMSupport();
XMLParserLiaison& theParserLiaison = theHelper->getParserLiaison();
theParserLiaison.setExecutionContext(*m_stylesheetExecutionContext);
theParserLiaison.setEntityResolver(m_entityResolver);
theParserLiaison.setXMLEntityResolver(m_xmlEntityResolver);
theParserLiaison.setErrorHandler(m_errorHandler);
theParserLiaison.setUseValidation(m_useValidation);
// Create some more support objects...
XSLTProcessorEnvSupportDefault theXSLTProcessorEnvSupport(m_memoryManager);
const XalanDOMString& theSourceURI = theParsedXML.getURI();
if (theSourceURI.empty() == false)
{
theXSLTProcessorEnvSupport.setSourceDocument(theSourceURI, theSourceDocument);
}
// Set the functions if any.
{
for (FunctionMapType::const_iterator i = m_functions.begin();
i != m_functions.end(); ++i)
{
assert((*i).second != 0);
theXSLTProcessorEnvSupport.installExternalFunctionLocal(
(*i).first.getNamespace(),
(*i).first.getLocalPart(),
*(*i).second);
}
}
XObjectFactoryDefault theXObjectFactory(m_memoryManager);
XPathFactoryBlock theXPathFactory(m_memoryManager);
// Create a processor...
XSLTEngineImpl theProcessor(
m_memoryManager,
theParserLiaison,
theXSLTProcessorEnvSupport,
theDOMSupport,
theXObjectFactory,
theXPathFactory);
theXSLTProcessorEnvSupport.setProcessor(&theProcessor);
const EnsureReset theReset(*this);
// Set up the stylesheet execution context.
m_stylesheetExecutionContext->setXPathEnvSupport(&theXSLTProcessorEnvSupport);
m_stylesheetExecutionContext->setDOMSupport(&theDOMSupport);
m_stylesheetExecutionContext->setXObjectFactory(&theXObjectFactory);
m_stylesheetExecutionContext->setXSLTProcessor(&theProcessor);
// Create a problem listener and send output to a XalanDOMString. Do this before
// pushing params, since there could be a problem resolving a QName.
DOMStringPrintWriter thePrintWriter(theErrorMessage);
XalanTransformerProblemListener theProblemListener(m_memoryManager, m_warningStream, &thePrintWriter);
if (m_problemListener == 0)
{
theProcessor.setProblemListener(&theProblemListener);
}
else
{
theProcessor.setProblemListener(m_problemListener);
}
{
typedef ParamMapType::const_iterator const_iterator;
theProcessor.clearStylesheetParams();
// Set the parameters if any.
for (const_iterator i = m_params.begin();
i != m_params.end();
++i)
{
const XalanDOMString& theName = (*i).first;
const XalanParamHolder& theCurrent= (*i).second;
const XalanDOMString& theExpression = theCurrent.m_expression;
XObjectPtr theObject = theCurrent.m_value;
if (theExpression.length() > 0)
{
theProcessor.setStylesheetParam(theName, theExpression);
}
else
{
theProcessor.setStylesheetParam(theName, theObject);
}
}
}
// Create an input source for the source document...
XSLTInputSource theDocumentInputSource(theSourceDocument, m_memoryManager);
// Set the system ID, so relative URIs are resolved properly...
theDocumentInputSource.setSystemId(theSourceURI.c_str());
addTraceListeners(m_traceListeners, theProcessor);
// We may need to change the output encoding, so
// we make a copy of the result target.
XSLTResultTarget tempResultTarget(theResultTarget, m_memoryManager);
if (tempResultTarget.getEncoding().length() == 0 && m_outputEncoding.length() != 0)
{
tempResultTarget.setEncoding(m_outputEncoding);
}
if (theCompiledStylesheet != 0)
{
assert(theStylesheetSource == 0 &&
theCompiledStylesheet->getStylesheetRoot() != 0);
m_stylesheetExecutionContext->setStylesheetRoot(theCompiledStylesheet->getStylesheetRoot());
// Do the transformation...
theProcessor.process(
theDocumentInputSource,
tempResultTarget,
*m_stylesheetExecutionContext);
}
else
{
assert(theStylesheetSource != 0);
// Create a stylesheet construction context,
// using the stylesheet's factory support objects.
StylesheetConstructionContextDefault theStylesheetConstructionContext(
m_memoryManager,
theProcessor,
theXPathFactory);
// Do the transformation...
theProcessor.process(
theDocumentInputSource,
*theStylesheetSource,
tempResultTarget,
theStylesheetConstructionContext,
*m_stylesheetExecutionContext);
}
}
catch(const XSLException& e)
{
if (theErrorMessage.empty() == true)
{
e.defaultFormat(theErrorMessage);
}
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
theResult = -1;
}
catch(const SAXParseException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
FormatSAXParseException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
}
theResult = -2;
}
catch(const SAXException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
}
theResult = -2;
}
catch(const XMLException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
TranscodeToLocalCodePage(e.getMessage(), m_errorMessage, true);
}
theResult = -3;
}
catch(const XalanDOMException& e)
{
if (theErrorMessage.empty() == false)
{
TranscodeToLocalCodePage(theErrorMessage, m_errorMessage, true);
}
else
{
FormatXalanDOMException(
*m_stylesheetExecutionContext,
e,
m_errorMessage);
}
theResult = -4;
}
return theResult;
}
void
XalanTransformer::EnsureFunctionsInstallation::install()
{
XalanExtensionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTCommonFunctionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTDynamicFunctionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTMathFunctionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTSetFunctionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTStringFunctionsInstaller::installGlobal(m_memoryManagement);
XalanEXSLTDateTimeFunctionsInstaller::installGlobal(m_memoryManagement);
}
XalanTransformer::EnsureFunctionsInstallation::~EnsureFunctionsInstallation()
{
if ( !m_release)
{
XalanExtensionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTCommonFunctionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTDynamicFunctionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTMathFunctionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTSetFunctionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTStringFunctionsInstaller::uninstallGlobal(m_memoryManagement);
XalanEXSLTDateTimeFunctionsInstaller::uninstallGlobal(m_memoryManagement);
#if defined(XALAN_USE_ICU)
XPath::uninstallFunction(XPathFunctionTable::s_formatNumber);
#endif
}
}
}