blob: 1cf8dcff25021989ff2b656e6e478dc8be0356df [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 "ElemTemplateElement.hpp"
#include <cassert>
#include <xercesc/sax/AttributeList.hpp>
#include <xalanc/XalanDOM/XalanAttr.hpp>
#include <xalanc/XalanDOM/XalanDocument.hpp>
#include <xalanc/XalanDOM/XalanDOMException.hpp>
#include <xalanc/PlatformSupport/AttributeListImpl.hpp>
#include <xalanc/PlatformSupport/DOMStringPrintWriter.hpp>
#include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>
#include <xalanc/DOMSupport/DOMServices.hpp>
#include <xalanc/XMLSupport/FormatterToText.hpp>
#include <xalanc/XPath/MutableNodeRefList.hpp>
#include <xalanc/XPath/XObjectFactory.hpp>
#include <xalanc/XPath/XPathExecutionContext.hpp>
#include <xalanc/XPath/XPath.hpp>
#include "Constants.hpp"
#include "ElemCallTemplate.hpp"
#include "ElemForEach.hpp"
#include "ElemTemplate.hpp"
#include "ElemTextLiteral.hpp"
#include "NamespacesHandler.hpp"
#include "NodeSorter.hpp"
#include "Stylesheet.hpp"
#include "StylesheetConstructionContext.hpp"
#include "StylesheetExecutionContext.hpp"
#include "StylesheetRoot.hpp"
#include "SelectionEvent.hpp"
#include "TracerEvent.hpp"
namespace XALAN_CPP_NAMESPACE {
const XalanDOMString ElemTemplateElement::s_emptyString(XalanMemMgrs::getDummyMemMgr());
const XalanQNameByReference ElemTemplateElement::s_emptyQName(s_emptyString, s_emptyString);
ElemTemplateElement::ElemTemplateElement(
StylesheetConstructionContext& constructionContext,
Stylesheet& stylesheetTree,
XalanFileLoc lineNumber,
XalanFileLoc columnNumber,
int xslToken) :
PrefixResolver(),
m_stylesheet(stylesheetTree),
m_namespacesHandler(
constructionContext,
stylesheetTree.getNamespacesHandler(),
stylesheetTree.getNamespaces(),
stylesheetTree.getXSLTNamespaceURI()),
m_xslToken(xslToken),
m_parentNode(0),
m_nextSibling(0),
m_previousSibling(0),
m_firstChild(0),
m_locatorProxy(
lineNumber,
columnNumber,
constructionContext.getPooledString(stylesheetTree.getCurrentIncludeBaseIdentifier())),
m_flags(eCanGenerateAttributes)
{
}
ElemTemplateElement::ElemTemplateElement(
StylesheetConstructionContext& constructionContext,
Stylesheet& stylesheetTree,
int xslToken,
const XalanDOMString& baseURI,
XalanFileLoc lineNumber,
XalanFileLoc columnNumber) :
PrefixResolver(),
m_stylesheet(stylesheetTree),
m_namespacesHandler(constructionContext.getMemoryManager()),
m_xslToken(xslToken),
m_parentNode(0),
m_nextSibling(0),
m_previousSibling(0),
m_firstChild(0),
m_locatorProxy(
lineNumber,
columnNumber,
constructionContext.getPooledString(baseURI)),
m_flags(eCanGenerateAttributes)
{
}
ElemTemplateElement::~ElemTemplateElement()
{
}
const Locator*
ElemTemplateElement::getLocator() const
{
return &m_locatorProxy;
}
bool
ElemTemplateElement::isWhitespace() const
{
return false;
}
bool
ElemTemplateElement::isAttrOK(
const XalanDOMChar* attrName,
const AttributeListType& atts,
XalanSize_t which,
StylesheetConstructionContext& constructionContext) const
{
return m_stylesheet.isAttrOK(attrName, atts, which, constructionContext);
}
bool
ElemTemplateElement::processSpaceAttr(
const XalanDOMChar* elementName,
const XalanDOMChar* aname,
const AttributeListType& atts,
XalanSize_t which,
StylesheetConstructionContext& constructionContext)
{
if(constructionContext.isXMLSpaceAttribute(
aname,
getStylesheet(),
getLocator()) == false)
{
return false;
}
else
{
const XalanDOMChar* const spaceVal = atts.getValue(which);
if(equals(spaceVal, Constants::ATTRVAL_PRESERVE) == true)
{
m_flags |= eSpacePreserve;
}
else if (equals(spaceVal, Constants::ATTRVAL_DEFAULT) == false)
{
error(
constructionContext,
XalanMessages::ElementHasIllegalAttributeValue_3Param,
elementName,
aname,
spaceVal);
}
return true;
}
}
bool
ElemTemplateElement::isValidNCName(const XalanDOMString& s)
{
return XalanQName::isValidNCName(s);
}
#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
const ElemTemplateElement*
ElemTemplateElement::startElement(StylesheetExecutionContext& executionContext) const
{
if(0 != executionContext.getTraceListeners())
{
executionContext.fireTraceEvent(
TracerEvent(executionContext, *this));
}
return 0;
}
void
ElemTemplateElement::endElement(StylesheetExecutionContext& /*executionContext*/) const
{
}
void
ElemTemplateElement::execute(StylesheetExecutionContext& executionContext) const
{
const ElemTemplateElement* const invoker =
getParentNodeElem();
const ElemTemplateElement* currentElement = this;
const ElemTemplateElement* nextElement = 0;
executionContext.pushInvoker(invoker);
while (currentElement != 0)
{
nextElement = currentElement->startElement(executionContext);
while (0 == nextElement)
{
currentElement->endElement(executionContext);
if (currentElement->getInvoker(executionContext) == invoker)
{
nextElement = 0;
break;
}
const ElemTemplateElement* const localInvoker =
currentElement->getInvoker(executionContext);
assert(localInvoker != 0);
nextElement =
localInvoker->getNextChildElemToExecute(
executionContext,
currentElement);
if (0 == nextElement)
{
currentElement = currentElement->getInvoker(executionContext);
}
}
currentElement = nextElement;
}
executionContext.popInvoker();
}
void
ElemTemplateElement::executeChildren(StylesheetExecutionContext& executionContext) const
{
const ElemTemplateElement* element = beginExecuteChildren(executionContext);
while (element != 0)
{
element->execute(executionContext);
element = getNextChildElemToExecute(executionContext,element);
}
endExecuteChildren(executionContext);
}
const ElemTemplateElement*
ElemTemplateElement::beginExecuteChildren(StylesheetExecutionContext& executionContext) const
{
if (hasParams() == true || hasVariables() == true)
{
assert(hasDirectTemplate() == false);
executionContext.pushElementFrame(this);
}
return getFirstChildElemToExecute(executionContext);
}
void
ElemTemplateElement::endExecuteChildren(StylesheetExecutionContext& executionContext) const
{
if (hasParams() == true || hasVariables() == true)
{
executionContext.popElementFrame();
}
else if (hasDirectTemplate() == true)
{
executionContext.popInvoker();
executionContext.popContextMarker();
}
}
const ElemTemplateElement*
ElemTemplateElement::beginChildrenToString(
StylesheetExecutionContext& executionContext,
XalanDOMString& result) const
{
if (hasSingleTextChild() == true)
{
assert(m_textLiteralChild != 0);
result.assign(m_textLiteralChild->getText(), m_textLiteralChild->getLength());
return 0;
}
else
{
result.reserve(result.length() + 1024);
executionContext.beginFormatToText(result);
return beginExecuteChildren(executionContext);
}
}
void
ElemTemplateElement::endChildrenToString(
StylesheetExecutionContext& executionContext) const
{
if (hasSingleTextChild() == false)
{
endExecuteChildren(executionContext);
executionContext.endFormatToText();
}
}
const ElemTemplateElement*
ElemTemplateElement::getInvoker(StylesheetExecutionContext& /*executionContext*/) const
{
return getParentNodeElem();
}
#endif
#if defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
void
ElemTemplateElement::execute(StylesheetExecutionContext& executionContext) const
{
if(0 != executionContext.getTraceListeners())
{
executionContext.fireTraceEvent(
TracerEvent(executionContext, *this));
}
}
void
ElemTemplateElement::executeChildren(StylesheetExecutionContext& executionContext) const
{
if (hasChildren() == true)
{
if (hasDirectTemplate() == true)
{
assert(m_directTemplate != 0);
// This is temporary, until we can process stylesheet in such a way that we
// can detect variable references...
const StylesheetExecutionContext::PushAndPopContextMarker thePushAndPop(executionContext);
m_directTemplate->execute(executionContext);
}
else
{
if (hasParams() == true || hasVariables() == true)
{
const StylesheetExecutionContext::PushAndPopElementFrame thePushAndPop(executionContext, this);
for (ElemTemplateElement* node = m_firstChild; node != 0; node = node->m_nextSibling)
{
node->execute(executionContext);
}
}
else
{
for (ElemTemplateElement* node = m_firstChild; node != 0; node = node->m_nextSibling)
{
node->execute(executionContext);
}
}
}
}
}
void
ElemTemplateElement::executeChildren(
StylesheetExecutionContext& executionContext,
XalanNode* sourceNode) const
{
if (hasChildren() == true)
{
XalanNode* const theCurrentNode = executionContext.getCurrentNode();
if (theCurrentNode == sourceNode)
{
executeChildren(executionContext);
}
else
{
const XPathExecutionContext::CurrentNodePushAndPop theCurrentNodePushAndPop(executionContext, sourceNode);
executeChildren(executionContext);
}
}
}
XalanDOMString&
ElemTemplateElement::doChildrenToString(
StylesheetExecutionContext& executionContext,
XalanDOMString& result) const
{
reserve(result, length(result) + 1024);
// Create a print writer and formatter to generate the children as
// a string.
DOMStringPrintWriter thePrintWriter(result);
// Borrow a FormatterToText, and don't normalize CR/LF, since we don't want
// this text to be normalized. Finally, have the formatter handle any ignorable
// whitespace events.
StylesheetExecutionContext::BorrowReturnFormatterToText theFormatter(
executionContext,
thePrintWriter,
false,
true);
// Create an object to set and restore the execution state.
StylesheetExecutionContext::OutputContextPushPop theOutputContextPushPop(
executionContext,
theFormatter.get());
theFormatter->startDocument();
executeChildren(executionContext);
theFormatter->endDocument();
return result;
}
const XalanDOMString&
ElemTemplateElement::childrenToString(
StylesheetExecutionContext& executionContext,
XalanDOMString& result) const
{
if (hasSingleTextChild() == true)
{
assert(m_textLiteralChild != 0);
assign(result, m_textLiteralChild->getText(), m_textLiteralChild->getLength());
}
else
{
doChildrenToString(executionContext, result);
}
return result;
}
void
ElemTemplateElement::childrenToResultAttribute(
StylesheetExecutionContext& executionContext,
const XalanDOMString& theName) const
{
if (hasSingleTextChild() == true)
{
executionContext.addResultAttribute(
theName,
m_textLiteralChild->getText());
}
else
{
const StylesheetExecutionContext::GetCachedString theResult(executionContext);
childrenToString(executionContext, theResult.get());
executionContext.addResultAttribute(
theName,
theResult.get());
}
}
void
ElemTemplateElement::childrenToResultComment(StylesheetExecutionContext& executionContext) const
{
const StylesheetExecutionContext::GetCachedString theGuard(executionContext);
XalanDOMString& theData = theGuard.get();
childrenToString(executionContext, theData);
XalanDOMString::iterator theEnd =
theData.end();
XalanDOMString::iterator theCurrent =
theData.begin();
// We need to fix up any occurrences of the sequence '--' in
// the comment's data by inserting a space between them. Also,
// if the data ends with a '-', then we must append a space to
// the data.
while(theCurrent != theEnd)
{
const XalanDOMChar theChar = *theCurrent;
if (theChar == XalanUnicode::charHyphenMinus)
{
XalanDOMString::iterator theNext =
theCurrent + 1;
if (theNext == theEnd ||
*theNext == XalanUnicode::charHyphenMinus)
{
theCurrent =
theData.insert(
theNext,
XalanUnicode::charSpace);
theEnd = theData.end();
}
}
++theCurrent;
}
executionContext.comment(theData.c_str());
}
void
ElemTemplateElement::childrenToResultPI(
StylesheetExecutionContext& executionContext,
const XalanDOMString& theTarget) const
{
const StylesheetExecutionContext::GetCachedString theGuard(executionContext);
XalanDOMString& theData = theGuard.get();
childrenToString(executionContext, theData);
XalanDOMString::iterator theEnd =
theData.end();
XalanDOMString::iterator theCurrent =
theData.begin();
// We need to fix up any occurrences of the sequence '?>' in
// the PI's data by inserting a space between them.
while(theCurrent != theEnd)
{
const XalanDOMChar theChar = *theCurrent;
if (theChar == XalanUnicode::charQuestionMark)
{
XalanDOMString::iterator theNext =
theCurrent + 1;
if (theNext != theEnd &&
*theNext == XalanUnicode::charGreaterThanSign)
{
theCurrent =
theData.insert(
theNext,
XalanUnicode::charSpace);
theEnd = theData.end();
// Move forward, since we're not interested in
// the '>' character.
++theCurrent;
}
}
++theCurrent;
}
executionContext.processingInstruction(
theTarget.c_str(),
theData.c_str());
}
#endif
typedef StylesheetExecutionContext::GetCachedString ECGetCachedString;
typedef StylesheetConstructionContext::GetCachedString CCGetCachedString;
void
ElemTemplateElement::error(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode),
getLocator(),
theContext.getCurrentNode());
}
void
ElemTemplateElement::error(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMString& theToken) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken),
getLocator(),
theContext.getCurrentNode());
}
void
ElemTemplateElement::error(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode,
const Locator* theLocator) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode),
theLocator,
theContext.getCurrentNode());
}
void
ElemTemplateElement::warn(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eWarning,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode),
getLocator(),
theContext.getCurrentNode());
}
void
ElemTemplateElement::warn(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode,
const Locator* theLocator) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eWarning,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode),
theLocator,
theContext.getCurrentNode());
}
void
ElemTemplateElement::warn(
StylesheetExecutionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMString& theToken) const
{
const ECGetCachedString theGuard(theContext);
theContext.problem(
StylesheetExecutionContext::eXSLTProcessor,
StylesheetExecutionContext::eWarning,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken),
getLocator(),
theContext.getCurrentNode());
}
void
ElemTemplateElement::warn(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMChar* theToken1,
const XalanDOMChar* theToken2,
const XalanDOMChar* theToken3)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eWarning,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken1,
theToken2,
theToken3),
getLocator(),
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode),
getLocator(),
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMString& theToken,
const Locator* theLocator)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken),
theLocator,
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMString& theToken)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken),
getLocator(),
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMString& theToken1,
const XalanDOMString& theToken2)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken1,
theToken2),
getLocator(),
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMChar* theToken1,
const XalanDOMChar* theToken2)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken1,
theToken2),
getLocator(),
0);
}
void
ElemTemplateElement::error(
StylesheetConstructionContext& theContext,
XalanMessages::Codes theCode,
const XalanDOMChar* theToken1,
const XalanDOMChar* theToken2,
const XalanDOMChar* theToken3)
{
const CCGetCachedString theGuard(theContext);
theContext.problem(
StylesheetConstructionContext::eXSLTProcessor,
StylesheetConstructionContext::eError,
XalanMessageLoader::getMessage(
theGuard.get(),
theCode,
theToken1,
theToken2,
theToken3),
getLocator(),
0);
}
const XalanQName&
ElemTemplateElement::getNameAttribute() const
{
return s_emptyQName;
}
void
ElemTemplateElement::addToStylesheet(
StylesheetConstructionContext& /* constructionContext */,
Stylesheet& /* theStylesheet */)
{
// An illegal call to addToStylesheet() was made during compilation of the stylesheet.
assert ( false );
}
void
ElemTemplateElement::processSortElement(
StylesheetConstructionContext& constructionContext,
Stylesheet& /* theStylesheet */,
const AttributeListType& /* atts */,
const Locator* locator)
{
error(
constructionContext,
XalanMessages::ElementIsNotAllowedAtThisPosition_1Param,
Constants::ELEMNAME_SORT_WITH_PREFIX_STRING,
locator);
}
void
ElemTemplateElement::setDefaultTemplate(bool value)
{
m_flags |= eDefaultTemplate;
for (ElemTemplateElement* node = m_firstChild; node != 0; node = node->m_nextSibling)
{
node->setDefaultTemplate(value);
}
}
ElemTemplateElement*
ElemTemplateElement::getFirstChildElem() const
{
return m_firstChild;
}
void
ElemTemplateElement::setFirstChildElem(ElemTemplateElement* theElement)
{
m_firstChild = theElement;
}
ElemTemplateElement*
ElemTemplateElement::getLastChildElem() const
{
ElemTemplateElement* lastChild = 0;
for (ElemTemplateElement* node = m_firstChild; node != 0; node = node->m_nextSibling)
{
lastChild = node;
}
return lastChild;
}
ElemTemplateElement*
ElemTemplateElement::getNextSiblingElem() const
{
return m_nextSibling;
}
void
ElemTemplateElement::setNextSiblingElem(ElemTemplateElement* theSibling)
{
m_nextSibling = theSibling;
}
ElemTemplateElement*
ElemTemplateElement::getPreviousSiblingElem() const
{
return m_previousSibling;
}
void
ElemTemplateElement::setPreviousSiblingElem(ElemTemplateElement* theSibling)
{
m_previousSibling = theSibling;
}
ElemTemplateElement*
ElemTemplateElement::getParentNodeElem() const
{
return m_parentNode;
}
void
ElemTemplateElement::setParentNodeElem(ElemTemplateElement* theParent)
{
m_parentNode = theParent;
}
ElemTemplateElement*
ElemTemplateElement::appendChildElem(ElemTemplateElement* newChild)
{
assert(newChild != 0);
assert(newChild->getXSLToken() != StylesheetConstructionContext::ELEMNAME_TEXT);
assert(newChild->getXSLToken() != StylesheetConstructionContext::ELEMNAME_UNDEFINED);
if (childTypeAllowed(newChild->getXSLToken()) == false)
{
throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
}
else if(0 == m_firstChild)
{
m_firstChild = newChild;
newChild->setPreviousSiblingElem(0);
}
else
{
ElemTemplateElement* const last = getLastChildElem();
assert(last != 0);
last->setNextSiblingElem(newChild);
newChild->setPreviousSiblingElem(last);
}
newChild->setParentNodeElem(this);
newChild->setNextSiblingElem(0);
return newChild;
}
const XPath*
ElemTemplateElement::getXPath(XalanSize_t /* index */) const
{
return 0;
}
#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
const ElemTemplateElement*
ElemTemplateElement::findTemplateToTransformChild(
StylesheetExecutionContext& executionContext,
const ElemTemplateElement& xslInstruction,
const ElemTemplateElement* theTemplate,
XalanNode* child) const
{
assert(child != 0);
return findTemplateToTransformChild(
executionContext,
xslInstruction,
theTemplate,
child,
child->getNodeType());
}
const ElemTemplateElement*
ElemTemplateElement::findTemplateToTransformChild(
StylesheetExecutionContext& executionContext,
const ElemTemplateElement& xslInstruction,
const ElemTemplateElement* theTemplate,
XalanNode* child,
XalanNode::NodeType nodeType) const
{
assert(child != 0);
if(0 == theTemplate)
{
// Find the XSL template that is the best match for the
// element...
const bool isApplyImports = xslInstruction.getXSLToken() ==
StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS;
assert(isApplyImports == false || executionContext.getCurrentTemplate() != 0);
const Stylesheet* stylesheetTree = isApplyImports == true ?
&executionContext.getCurrentTemplate()->getStylesheet() :
&getStylesheet().getStylesheetRoot();
theTemplate = stylesheetTree->findTemplate(
executionContext,
child,
nodeType,
*executionContext.getCurrentMode(),
isApplyImports);
}
if(0 == theTemplate)
{
switch(nodeType)
{
case XalanNode::DOCUMENT_FRAGMENT_NODE:
case XalanNode::ELEMENT_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultRule();
break;
case XalanNode::CDATA_SECTION_NODE:
case XalanNode::TEXT_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultTextRule();
break;
case XalanNode::ATTRIBUTE_NODE:
if (DOMServices::isNamespaceDeclaration(static_cast<const XalanAttr&>(*child)) == false)
{
theTemplate = getStylesheet().getStylesheetRoot().getDefaultTextRule();
}
break;
case XalanNode::DOCUMENT_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultRootRule();
break;
default:
break;
}
}
if(0 != theTemplate)
{
if(theTemplate == getStylesheet().getStylesheetRoot().getDefaultTextRule())
{
switch(nodeType)
{
case XalanNode::CDATA_SECTION_NODE:
case XalanNode::TEXT_NODE:
executionContext.cloneToResultTree(
*child,
XalanNode::TEXT_NODE,
true,
false,
getLocator());
break;
case XalanNode::ATTRIBUTE_NODE:
{
const XalanDOMString& val = child->getNodeValue();
const XalanDOMString::size_type len = val.length();
if (len > 0)
{
executionContext.characters(
val.c_str(),
0,
len);
}
}
break;
default:
assert(false);
break;
}
}
else
{
if(0 != executionContext.getTraceListeners())
{
const TracerEvent te(executionContext,
*theTemplate);
executionContext.fireTraceEvent(te);
}
return theTemplate;
}
}
return 0;
}
#else
void
ElemTemplateElement::transformChild(
StylesheetExecutionContext& executionContext,
const ElemTemplateElement& xslInstruction,
const ElemTemplateElement* theTemplate,
XalanNode* child) const
{
assert(child != 0);
transformChild(
executionContext,
xslInstruction,
theTemplate,
child,
child->getNodeType());
}
void
ElemTemplateElement::transformChild(
StylesheetExecutionContext& executionContext,
const ElemTemplateElement& xslInstruction,
const ElemTemplateElement* theTemplate,
XalanNode* child,
XalanNode::NodeType nodeType) const
{
assert(child != 0);
if(0 == theTemplate)
{
// Find the XSL template that is the best match for the
// element...
const bool isApplyImports = xslInstruction.getXSLToken() ==
StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS;
assert(isApplyImports == false || executionContext.getCurrentTemplate() != 0);
const Stylesheet* stylesheetTree = isApplyImports == true ?
&executionContext.getCurrentTemplate()->getStylesheet() :
&getStylesheet().getStylesheetRoot();
theTemplate = stylesheetTree->findTemplate(
executionContext,
child,
nodeType,
*executionContext.getCurrentMode(),
isApplyImports);
}
if(0 == theTemplate)
{
switch(nodeType)
{
case XalanNode::DOCUMENT_FRAGMENT_NODE:
case XalanNode::ELEMENT_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultRule();
break;
case XalanNode::CDATA_SECTION_NODE:
case XalanNode::TEXT_NODE:
case XalanNode::ATTRIBUTE_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultTextRule();
break;
case XalanNode::DOCUMENT_NODE:
theTemplate = getStylesheet().getStylesheetRoot().getDefaultRootRule();
break;
default:
break;
}
}
if(0 != theTemplate)
{
if(theTemplate == getStylesheet().getStylesheetRoot().getDefaultTextRule())
{
switch(nodeType)
{
case XalanNode::CDATA_SECTION_NODE:
case XalanNode::TEXT_NODE:
executionContext.cloneToResultTree(
*child,
XalanNode::TEXT_NODE,
true,
false,
getLocator());
break;
case XalanNode::ATTRIBUTE_NODE:
{
const XalanDOMString& val = child->getNodeValue();
const XalanDOMString::size_type len = length(val);
if (len > 0)
{
executionContext.characters(
val.c_str(),
0,
len);
}
}
break;
default:
assert(false);
break;
}
}
else
{
if(0 != executionContext.getTraceListeners())
{
const TracerEvent te(executionContext,
*theTemplate);
executionContext.fireTraceEvent(te);
}
theTemplate->executeChildren(executionContext, child);
}
}
}
#endif
void
ElemTemplateElement::postConstruction(
StylesheetConstructionContext& constructionContext,
const NamespacesHandler& theParentHandler)
{
namespacesPostConstruction(
constructionContext,
theParentHandler,
m_namespacesHandler);
if (hasChildren() == true)
{
for (ElemTemplateElement* node = m_firstChild; node != 0; node = node->m_nextSibling)
{
node->postConstruction(constructionContext, m_namespacesHandler);
const int theToken = node->getXSLToken();
if (hasVariables() == false &&
(theToken == StylesheetConstructionContext::ELEMNAME_VARIABLE ||
theToken == StylesheetConstructionContext::ELEMNAME_PARAM))
{
m_flags |= eHasVariables;
}
if (hasParams() == false &&
theToken == StylesheetConstructionContext::ELEMNAME_WITH_PARAM)
{
m_flags |= eHasParams;
}
}
assert(m_firstChild != 0);
const int theToken = m_firstChild->getXSLToken();
// There are opportunities for optimization if there's only one
// xsl:text child node. See childrenToString()...
if (theToken == StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT &&
m_firstChild->getNextSiblingElem() == 0)
{
m_flags |= eHasSingleTextChild;
}
else if (theToken == StylesheetConstructionContext::ELEMNAME_CALL_TEMPLATE &&
m_firstChild->getNextSiblingElem() == 0)
{
// Just a single xsl:call-template child, so we don't need to
// execute it if it has no params -- we can just execute the
// template directly...
if (m_firstChild->hasParams() == false)
{
m_flags |= eHasDirectTemplate;
ElemCallTemplate* const theCallTemplateChild =
static_cast<ElemCallTemplate*>(m_firstChild);
m_directTemplate = theCallTemplateChild->getTemplate();
}
}
else if (canGenerateAttributes() == false &&
theToken != StylesheetConstructionContext::ELEMNAME_LITERAL_RESULT)
{
m_flags |= eCanGenerateAttributes;
}
}
}
void
ElemTemplateElement::namespacesPostConstruction(
StylesheetConstructionContext& constructionContext,
const NamespacesHandler& theParentHandler,
NamespacesHandler& theHandler)
{
theHandler.postConstruction(
constructionContext,
true,
getElementName(),
&theParentHandler);
}
const XalanDOMString*
ElemTemplateElement::getNamespaceForPrefix(const XalanDOMString& prefix) const
{
return getNamespaceForPrefixInternal(prefix);
}
bool
ElemTemplateElement::processPrefixControl(
StylesheetConstructionContext& constructionContext,
const Stylesheet& stylesheetTree,
const XalanDOMString& localName,
const XalanDOMChar* attrValue)
{
if(equals(localName, Constants::ATTRNAME_EXTENSIONELEMENTPREFIXES))
{
m_namespacesHandler.processExtensionElementPrefixes(
constructionContext,
attrValue,
stylesheetTree.getNamespaces());
return true;
}
else if (equals(localName, Constants::ATTRNAME_EXCLUDE_RESULT_PREFIXES))
{
m_namespacesHandler.processExcludeResultPrefixes(
constructionContext,
attrValue,
stylesheetTree.getNamespaces());
return true;
}
else
{
return false;
}
}
const XalanDOMString*
ElemTemplateElement::getNamespaceForPrefixInternal(const XalanDOMString& prefix) const
{
const XalanDOMString* nameSpace = 0;
if(getFinishedConstruction() == false)
{
nameSpace = getStylesheet().getNamespaceForPrefixFromStack(prefix);
}
else
{
if (equals(prefix, DOMServices::s_XMLString) == true)
{
nameSpace = &DOMServices::s_XMLNamespaceURI;
}
else
{
nameSpace = getNamespacesHandler().getNamespace(prefix);
if(nameSpace == 0)
{
if (m_parentNode != 0)
{
nameSpace = m_parentNode->getNamespaceForPrefixInternal(prefix);
}
// Try one last time with the stylesheet...
if (nameSpace == 0)
{
nameSpace = getStylesheet().getNamespaceForPrefix(prefix);
}
}
}
}
return nameSpace;
}
const XalanDOMString&
ElemTemplateElement::getURI() const
{
return m_locatorProxy.getURI();
}
ElemTemplateElement::LocatorProxy::LocatorProxy(
XalanFileLoc theLineNumber,
XalanFileLoc theColumnNumber,
const XalanDOMString& theURI) :
m_lineNumber(theLineNumber),
m_columnNumber(theColumnNumber),
m_uri(theURI)
{
}
ElemTemplateElement::LocatorProxy::~LocatorProxy()
{
}
XalanFileLoc
ElemTemplateElement::LocatorProxy::getLineNumber() const
{
return m_lineNumber;
}
XalanFileLoc
ElemTemplateElement::LocatorProxy::getColumnNumber() const
{
return m_columnNumber;
}
const XMLCh*
ElemTemplateElement::LocatorProxy::getPublicId() const
{
return 0;
}
const XMLCh*
ElemTemplateElement::LocatorProxy::getSystemId() const
{
return m_uri.size() == 0 ? 0 : m_uri.c_str();
}
bool
ElemTemplateElement::childTypeAllowed(int /* xslToken */) const
{
return true;
}
#if !defined(XALAN_RECURSIVE_STYLESHEET_EXECUTION)
const ElemTemplateElement*
ElemTemplateElement::getNextChildElemToExecute(StylesheetExecutionContext& executionContext,
const ElemTemplateElement* currentElem) const
{
if (hasDirectTemplate() == true)
{
return 0;
}
assert(currentElem != 0);
const ElemTemplateElement* nextElement;
while((nextElement = currentElem->getNextSiblingElem()) != 0
&& !executeChildElement(executionContext, nextElement))
{
currentElem = nextElement;
}
return nextElement;
}
const ElemTemplateElement*
ElemTemplateElement::getFirstChildElemToExecute(StylesheetExecutionContext& executionContext) const
{
if (hasDirectTemplate() == true)
{
assert(m_directTemplate != 0);
executionContext.pushContextMarker();
executionContext.pushInvoker(this);
return m_directTemplate;
}
const ElemTemplateElement * firstElement = getFirstChildElem();
if (firstElement != 0 && !executeChildElement(executionContext, firstElement))
{
firstElement = ElemTemplateElement::getNextChildElemToExecute(executionContext,firstElement);
}
return firstElement;
}
bool
ElemTemplateElement::executeChildElement(
StylesheetExecutionContext& /*executionContext*/,
const ElemTemplateElement* /*element*/) const
{
return true;
}
#endif
}