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