| /* |
| * 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 "StylesheetHandler.hpp" |
| |
| |
| |
| #include <algorithm> |
| |
| |
| |
| #include <xercesc/sax/Locator.hpp> |
| #include <xercesc/sax/SAXParseException.hpp> |
| |
| |
| |
| #include <xalanc/Include/STLHelper.hpp> |
| |
| |
| |
| #include <xalanc/XalanDOM/XalanDOMException.hpp> |
| |
| |
| |
| #include <xalanc/PlatformSupport/AttributeListImpl.hpp> |
| #include <xalanc/PlatformSupport/DOMStringHelper.hpp> |
| #include <xalanc/PlatformSupport/DoubleSupport.hpp> |
| #include <xalanc/PlatformSupport/StringTokenizer.hpp> |
| #include <xalanc/PlatformSupport/XalanLocator.hpp> |
| #include <xalanc/PlatformSupport/XalanMessageLoader.hpp> |
| |
| |
| |
| #include <xalanc/DOMSupport/DOMServices.hpp> |
| |
| |
| |
| #include "Constants.hpp" |
| #include "ElemTemplateElement.hpp" |
| #include "ElemTextLiteral.hpp" |
| #include "Stylesheet.hpp" |
| #include "StylesheetConstructionContext.hpp" |
| #include "StylesheetRoot.hpp" |
| #include "XalanSpaceNodeTester.hpp" |
| |
| |
| |
| #include <xalanc/Include/XalanMemMgrAutoPtr.hpp> |
| |
| |
| |
| namespace XALAN_CPP_NAMESPACE { |
| |
| |
| |
| typedef StylesheetConstructionContext::GetCachedString GetCachedString; |
| |
| |
| |
| StylesheetHandler::StylesheetHandler( |
| Stylesheet& stylesheetTree, |
| StylesheetConstructionContext& constructionContext) : |
| FormatterListener(OUTPUT_METHOD_OTHER), |
| m_stylesheet(stylesheetTree), |
| m_constructionContext(constructionContext), |
| m_elemEmptyAllocator(constructionContext.getMemoryManager(), eElemEmptyAllocatorBlockSize), |
| m_elemTextAllocator(constructionContext.getMemoryManager(), eElemTextBlockSize), |
| m_elemStack(constructionContext.getMemoryManager()), |
| m_whiteSpaceElems(constructionContext.getMemoryManager()), |
| m_pTemplate(0), |
| m_lastPopped(*this), |
| m_inTemplate(false), |
| m_foundStylesheet(false), |
| m_foundNotImport(false), |
| m_elementLocalName(constructionContext.getMemoryManager()), |
| m_accumulateText(constructionContext.getMemoryManager()), |
| m_includeBase(stylesheetTree.getBaseIdentifier(), constructionContext.getMemoryManager()), |
| m_inExtensionElementStack(constructionContext.getMemoryManager()), |
| m_preserveSpaceStack(constructionContext.getMemoryManager()), |
| m_locatorsPushed(0), |
| m_globalVariableNames(constructionContext.getMemoryManager()), |
| m_inScopeVariableNamesStack(constructionContext.getMemoryManager()) |
| { |
| m_inScopeVariableNamesStack.reserve(eVariablesStackDefault); |
| } |
| |
| |
| |
| StylesheetHandler::~StylesheetHandler() |
| { |
| doCleanup(); |
| } |
| |
| |
| |
| void StylesheetHandler::setDocumentLocator(const Locator* const locator) |
| { |
| m_constructionContext.pushLocatorOnStack(locator); |
| |
| ++m_locatorsPushed; |
| } |
| |
| |
| |
| void |
| StylesheetHandler::startDocument() |
| { |
| } |
| |
| |
| |
| void |
| StylesheetHandler::endDocument() |
| { |
| m_constructionContext.popLocatorStack(); |
| |
| if (m_locatorsPushed > 0) |
| { |
| --m_locatorsPushed; |
| } |
| |
| m_inExtensionElementStack.clear(); |
| } |
| |
| |
| |
| bool |
| StylesheetHandler::isAttrOK( |
| const XalanDOMChar* attrName, |
| const AttributeListType& atts, |
| XalanSize_t which) |
| { |
| return m_stylesheet.isAttrOK(attrName, atts, which, m_constructionContext); |
| } |
| |
| |
| |
| bool |
| StylesheetHandler::processSpaceAttr( |
| const XalanDOMChar* elementName, |
| const XalanDOMChar* aname, |
| const AttributeListType& atts, |
| XalanSize_t which, |
| const Locator* locator, |
| bool& fPreserve) |
| { |
| if (m_constructionContext.isXMLSpaceAttribute(aname, m_stylesheet, locator) == false) |
| { |
| fPreserve = false; |
| |
| return false; |
| } |
| else |
| { |
| const XalanDOMChar* const spaceVal = atts.getValue(which); |
| |
| if (equals(spaceVal, Constants::ATTRVAL_DEFAULT)) |
| { |
| fPreserve = false; |
| } |
| else if (equals(spaceVal, Constants::ATTRVAL_PRESERVE)) |
| { |
| fPreserve = true; |
| } |
| else |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::ElementHasIllegalAttributeValue_3Param, |
| elementName, |
| Constants::ATTRNAME_XMLSPACE.c_str(), |
| spaceVal), |
| locator); |
| } |
| |
| return true; |
| } |
| } |
| |
| |
| |
| bool |
| StylesheetHandler::processSpaceAttr( |
| const XalanDOMChar* elementName, |
| const AttributeListType& atts, |
| const Locator* locator, |
| bool& fPreserve) |
| { |
| const XalanSize_t len = atts.getLength(); |
| |
| for (XalanSize_t i = 0; i < len; ++i) |
| { |
| if (processSpaceAttr( |
| elementName, |
| atts.getName(i), |
| atts, |
| i, |
| locator, |
| fPreserve) == true) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| |
| void |
| StylesheetHandler::startElement( |
| const XMLCh* const name, |
| AttributeListType& atts) |
| { |
| m_inExtensionElementStack.push_back(false); |
| |
| if (m_preserveSpaceStack.empty() == true) |
| { |
| m_preserveSpaceStack.push_back(false); |
| } |
| else |
| { |
| m_preserveSpaceStack.push_back(m_preserveSpaceStack.back()); |
| } |
| |
| try |
| { |
| // By default, space is not preserved... |
| bool fPreserveSpace = false; |
| bool fSpaceAttrProcessed = false; |
| |
| processAccumulatedText(); |
| |
| m_whiteSpaceElems.clear(); |
| |
| const Locator* const locator = m_constructionContext.getLocatorFromStack(); |
| |
| // First push namespaces |
| m_stylesheet.pushNamespaces(atts); |
| |
| const XalanDOMString::size_type nameLength = length(name); |
| const XalanDOMString::size_type index = indexOf(name, XalanUnicode::charColon); |
| |
| const GetCachedString theGuard2(m_constructionContext); |
| XalanDOMString& buffer = theGuard2.get(); |
| |
| const XalanDOMString* ns = getNamespaceFromStack(name, buffer); |
| |
| if(ns == 0) |
| { |
| if (index < nameLength) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::PrefixIsNotDeclared_1Param, |
| name), |
| locator); |
| } |
| else |
| { |
| ns = &s_emptyString; |
| } |
| } |
| assert(ns != 0); |
| |
| if (index < nameLength) |
| { |
| m_elementLocalName.assign(name + index + 1, nameLength - index - 1); |
| } |
| else |
| { |
| m_elementLocalName.assign(name, nameLength); |
| } |
| |
| ElemTemplateElement* elem = 0; |
| |
| const ElemTemplateStackType::size_type origStackSize = m_elemStack.size(); |
| |
| if (equals(*ns, m_constructionContext.getXSLTNamespaceURI())) |
| { |
| if (!m_stylesheet.getXSLTNamespaceURI().empty()) |
| m_stylesheet.setXSLTNamespaceURI(*ns); |
| |
| const StylesheetConstructionContext::eElementToken xslToken = |
| m_constructionContext.getElementToken(m_elementLocalName); |
| |
| if (!m_inTemplate) |
| { |
| processTopLevelElement(name, atts, xslToken, locator, fPreserveSpace, fSpaceAttrProcessed); |
| } |
| else |
| { |
| switch(xslToken) |
| { |
| case StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES: |
| case StylesheetConstructionContext::ELEMNAME_ATTRIBUTE: |
| case StylesheetConstructionContext::ELEMNAME_CALL_TEMPLATE: |
| case StylesheetConstructionContext::ELEMNAME_CHOOSE: |
| case StylesheetConstructionContext::ELEMNAME_COMMENT: |
| case StylesheetConstructionContext::ELEMNAME_COPY: |
| case StylesheetConstructionContext::ELEMNAME_COPY_OF: |
| case StylesheetConstructionContext::ELEMNAME_ELEMENT: |
| case StylesheetConstructionContext::ELEMNAME_FALLBACK: |
| case StylesheetConstructionContext::ELEMNAME_FOR_EACH: |
| case StylesheetConstructionContext::ELEMNAME_IF: |
| case StylesheetConstructionContext::ELEMNAME_MESSAGE: |
| case StylesheetConstructionContext::ELEMNAME_NUMBER: |
| case StylesheetConstructionContext::ELEMNAME_VALUE_OF: |
| case StylesheetConstructionContext::ELEMNAME_WITH_PARAM: |
| case StylesheetConstructionContext::ELEMNAME_PI: |
| elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_PARAM: |
| elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| |
| checkForOrAddVariableName(elem->getNameAttribute(), locator); |
| |
| assert(elem != 0); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_SORT: |
| { |
| if (m_elemStack.empty() == true) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| Constants::ELEMNAME_SORT_WITH_PREFIX_STRING), |
| locator); |
| } |
| |
| ElemTemplateElement* const theElement = |
| m_elemStack.back(); |
| assert(theElement != 0); |
| |
| theElement->processSortElement( |
| m_constructionContext, |
| m_stylesheet, |
| atts, |
| locator); |
| |
| m_elemStack.push_back( |
| m_elemEmptyAllocator.create( |
| m_constructionContext, |
| m_stylesheet, |
| &Constants::ELEMNAME_SORT_WITH_PREFIX_STRING)); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS: |
| { |
| if (m_elemStack.empty() == true) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| Constants::ELEMNAME_APPLY_IMPORTS_WITH_PREFIX_STRING), |
| locator); |
| } |
| |
| ElemTemplateElement* const theElement = |
| m_elemStack.back(); |
| assert(theElement != 0); |
| |
| const int parentToken = |
| theElement->getXSLToken(); |
| |
| if (parentToken == StylesheetConstructionContext::ELEMNAME_FOR_EACH) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| Constants::ELEMNAME_APPLY_IMPORTS_WITH_PREFIX_STRING), |
| locator); |
| } |
| |
| elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_VARIABLE: |
| { |
| elem = |
| m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| |
| checkForOrAddVariableName(elem->getNameAttribute(), locator); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_WHEN: |
| { |
| ElemTemplateElement* const parent = m_elemStack.back(); |
| |
| if(StylesheetConstructionContext::ELEMNAME_CHOOSE != parent->getXSLToken()) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::NotParentedBy_2Param, |
| Constants::ELEMNAME_WHEN_WITH_PREFIX_STRING, |
| Constants::ELEMNAME_CHOOSE_WITH_PREFIX_STRING), |
| locator); |
| } |
| else |
| { |
| ElemTemplateElement* const lastChild = parent->getLastChildElem(); |
| |
| if(0 == lastChild || |
| StylesheetConstructionContext::ELEMNAME_WHEN == lastChild->getXSLToken() || |
| lastChild->isWhitespace() == true) |
| { |
| elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| } |
| else |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| Constants::ELEMNAME_WHEN_WITH_PREFIX_STRING), |
| locator); |
| } |
| } |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_OTHERWISE: |
| { |
| ElemTemplateElement* parent = m_elemStack.back(); |
| |
| if(StylesheetConstructionContext::ELEMNAME_CHOOSE != parent->getXSLToken()) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::NotParentedBy_2Param, |
| Constants::ELEMNAME_OTHERWISE_WITH_PREFIX_STRING, |
| Constants::ELEMNAME_CHOOSE_WITH_PREFIX_STRING), |
| locator); |
| } |
| else |
| { |
| ElemTemplateElement* lastChild = parent->getLastChildElem(); |
| |
| if(0 == lastChild || |
| StylesheetConstructionContext::ELEMNAME_WHEN == lastChild->getXSLToken() || |
| lastChild->isWhitespace() == true) |
| { |
| elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| } |
| else |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| Constants::ELEMNAME_OTHERWISE_WITH_PREFIX_STRING), |
| locator); |
| } |
| } |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_TEXT: |
| m_elemStack.push_back( |
| m_elemTextAllocator.create( |
| m_constructionContext, |
| m_stylesheet, |
| atts, |
| XalanLocator::getLineNumber(locator), |
| XalanLocator::getColumnNumber(locator))); |
| |
| // This fixes Bugzilla 26354, but it's really a workaround |
| // for the bizarre way we handle literal text in the |
| // stylesheet. We should examine this strategy, because |
| // an xml:space attribute on an xsl:text element results |
| // in building a stylesheet that tries to parent an |
| // ElemTextLiteral instance to an ElemText instance, which |
| // should not ever happen. |
| fSpaceAttrProcessed = true; |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_TEMPLATE: |
| case StylesheetConstructionContext::ELEMNAME_ATTRIBUTE_SET: |
| case StylesheetConstructionContext::ELEMNAME_EXTENSION: |
| case StylesheetConstructionContext::ELEMNAME_EXTENSION_HANDLER: |
| case StylesheetConstructionContext::ELEMNAME_KEY: |
| case StylesheetConstructionContext::ELEMNAME_IMPORT: |
| case StylesheetConstructionContext::ELEMNAME_INCLUDE: |
| case StylesheetConstructionContext::ELEMNAME_PRESERVE_SPACE: |
| case StylesheetConstructionContext::ELEMNAME_STRIP_SPACE: |
| case StylesheetConstructionContext::ELEMNAME_DECIMAL_FORMAT: |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInsideTemplate_1Param, |
| name), |
| locator); |
| } |
| break; |
| |
| default: |
| { |
| // If this stylesheet is declared to be of a higher version than the one |
| // supported, don't flag an error. |
| if(m_constructionContext.getXSLTVersionSupported() < m_stylesheet.getXSLTVerDeclared()) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| warn( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::UnknownXSLElement_1Param, |
| name), |
| locator); |
| |
| elem = m_constructionContext.createElement( |
| StylesheetConstructionContext::ELEMNAME_FORWARD_COMPATIBLE, |
| m_stylesheet, |
| name, |
| atts, |
| locator); |
| } |
| else |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::UnknownXSLElement_1Param, |
| name), |
| locator); |
| } |
| } |
| } |
| |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| } |
| } |
| else if (!m_inTemplate && startsWith(*ns, m_constructionContext.getXalanXSLNameSpaceURL())) |
| { |
| processExtensionElement(name, m_elementLocalName, atts, locator); |
| } |
| else |
| { |
| if(!m_inTemplate) |
| { |
| // If it's a top level |
| if (!m_foundStylesheet) |
| { |
| elem = initWrapperless(name, atts, locator); |
| } |
| else if (ns->empty() == true && m_elemStack.size() == 1) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| name), |
| locator); |
| } |
| else |
| { |
| m_inExtensionElementStack.back() = true; |
| } |
| } |
| else |
| { |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| |
| // BEGIN SANJIVA CODE |
| // is this an extension element call? |
| ExtensionNSHandler* nsh = 0; |
| |
| if (!ns->empty() && |
| ((nsh = m_stylesheet.lookupExtensionNSHandler(*ns)) != 0)) |
| { |
| elem = m_constructionContext.createElement( |
| m_stylesheet, |
| name, |
| atts, |
| *nsh, |
| locator); |
| assert(m_inExtensionElementStack.empty() == false); |
| |
| m_inExtensionElementStack.back() = true; |
| } |
| else |
| { |
| elem = m_constructionContext.createElement( |
| StylesheetConstructionContext::ELEMNAME_LITERAL_RESULT, |
| m_stylesheet, |
| name, |
| atts, |
| locator); |
| } |
| |
| assert(elem != 0); |
| } |
| } |
| |
| if(m_inTemplate && 0 != elem) |
| { |
| if(!m_elemStack.empty()) |
| { |
| appendChildElementToParent(elem, locator); |
| } |
| |
| m_elemStack.push_back(elem); |
| } |
| |
| // If we haven't processed an xml:space attribute already, look for one... |
| if (fSpaceAttrProcessed == false) |
| { |
| fSpaceAttrProcessed = processSpaceAttr(name, atts, locator, fPreserveSpace); |
| } |
| |
| // Only update the stack if we actually processed an xml:space attribute... |
| if (fSpaceAttrProcessed == true) |
| { |
| // Set the preserve value... |
| m_preserveSpaceStack.back() = fPreserveSpace; |
| } |
| |
| // If for some reason something didn't get pushed, push an empty |
| // object. |
| if(origStackSize == m_elemStack.size()) |
| { |
| m_elemStack.push_back(m_elemEmptyAllocator.create(m_constructionContext, m_stylesheet)); |
| } |
| } // end try |
| catch(...) |
| { |
| doCleanup(); |
| |
| throw; |
| } |
| } |
| |
| |
| |
| ElemTemplateElement* |
| StylesheetHandler::initWrapperless( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| const Locator* locator) |
| { |
| assert(m_pTemplate == 0); |
| |
| m_pTemplate = m_stylesheet.initWrapperless(m_constructionContext, locator); |
| assert(m_pTemplate != 0); |
| |
| ElemTemplateElement* const pElem = |
| m_constructionContext.createElement( |
| StylesheetConstructionContext::ELEMNAME_LITERAL_RESULT, |
| m_stylesheet, |
| name, |
| atts, |
| locator); |
| |
| m_pTemplate->appendChildElem(pElem); |
| m_inTemplate = true; |
| |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| |
| m_foundStylesheet = true; |
| |
| // This attempts to optimize for a literal result element with |
| // the name HTML, so we don't have to switch on-the-fly. |
| if(equalsIgnoreCaseASCII(name, Constants::ELEMNAME_HTML_STRING) == true) |
| { |
| // If there's a default namespace, then we must output XML. |
| // Otherwise, we'll set the output method to HTML. |
| if (atts.getValue(DOMServices::s_XMLNamespace.c_str()) == 0) |
| { |
| m_stylesheet.getStylesheetRoot().setIndentResult(true); |
| m_stylesheet.getStylesheetRoot().setOutputMethod(OUTPUT_METHOD_HTML); |
| } |
| } |
| |
| return pElem; |
| } |
| |
| |
| |
| const XalanDOMString* |
| StylesheetHandler::getNamespaceFromStack(const XalanDOMChar* theName, |
| XalanDOMString& theBuffer) const |
| { |
| return m_stylesheet.getNamespaceFromStack(theName, theBuffer); |
| } |
| |
| |
| |
| const XalanDOMString* |
| StylesheetHandler::getNamespaceForPrefixFromStack(const XalanDOMString& thePrefix) const |
| { |
| return m_stylesheet.getNamespaceForPrefixFromStack(thePrefix); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processTopLevelElement( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| int xslToken, |
| const Locator* locator, |
| bool& fPreserveSpace, |
| bool& fSpaceAttrProcessed) |
| { |
| if(m_foundStylesheet && StylesheetConstructionContext::ELEMNAME_IMPORT != xslToken) |
| { |
| m_foundNotImport = true; |
| } |
| |
| switch(xslToken) |
| { |
| case StylesheetConstructionContext::ELEMNAME_TEMPLATE: |
| assert(m_pTemplate == 0); |
| |
| m_pTemplate = |
| m_constructionContext.createElement( |
| StylesheetConstructionContext::ELEMNAME_TEMPLATE, |
| m_stylesheet, |
| atts, |
| locator); |
| |
| m_elemStack.push_back(m_pTemplate); |
| m_inTemplate = true; |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_VARIABLE: |
| case StylesheetConstructionContext::ELEMNAME_PARAM: |
| { |
| ElemTemplateElement* const elem = m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| assert(elem != 0); |
| |
| checkForOrAddVariableName(elem->getNameAttribute(), locator); |
| |
| m_elemStack.push_back(elem); |
| m_inTemplate = true; // fake it out |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| elem->addToStylesheet(m_constructionContext, m_stylesheet); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_PRESERVE_SPACE: |
| case StylesheetConstructionContext::ELEMNAME_STRIP_SPACE: |
| processPreserveStripSpace(name, atts, locator, xslToken); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_KEY: |
| { |
| m_stylesheet.processKeyElement( |
| XalanQName::PrefixResolverProxy(m_stylesheet.getNamespaces(), m_stylesheet.getURI()), |
| atts, |
| locator, |
| m_constructionContext); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_ATTRIBUTE_SET: |
| { |
| m_inTemplate = true; // fake it out |
| m_inScopeVariableNamesStack.resize(m_inScopeVariableNamesStack.size() + 1); |
| |
| ElemTemplateElement* const theAttributeSet = |
| m_constructionContext.createElement( |
| xslToken, |
| m_stylesheet, |
| atts, |
| locator); |
| |
| theAttributeSet->addToStylesheet(m_constructionContext, m_stylesheet); |
| |
| m_elemStack.push_back(theAttributeSet); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_INCLUDE: |
| processInclude(name, atts, locator); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_IMPORT: |
| processImport(name, atts, locator); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_OUTPUT: |
| m_stylesheet.getStylesheetRoot().processOutputSpec(name, atts, m_constructionContext); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_DECIMAL_FORMAT: |
| m_stylesheet.processDecimalFormatElement( |
| m_constructionContext, |
| atts, |
| locator); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_NAMESPACE_ALIAS: |
| m_stylesheet.processNSAliasElement(name, atts, m_constructionContext); |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_WITH_PARAM: |
| case StylesheetConstructionContext::ELEMNAME_ATTRIBUTE: |
| case StylesheetConstructionContext::ELEMNAME_APPLY_TEMPLATES: |
| case StylesheetConstructionContext::ELEMNAME_CHOOSE: |
| case StylesheetConstructionContext::ELEMNAME_COMMENT: |
| case StylesheetConstructionContext::ELEMNAME_COPY: |
| case StylesheetConstructionContext::ELEMNAME_COPY_OF: |
| case StylesheetConstructionContext::ELEMNAME_FOR_EACH: |
| case StylesheetConstructionContext::ELEMNAME_IF: |
| case StylesheetConstructionContext::ELEMNAME_CALL_TEMPLATE: |
| case StylesheetConstructionContext::ELEMNAME_MESSAGE: |
| case StylesheetConstructionContext::ELEMNAME_NUMBER: |
| case StylesheetConstructionContext::ELEMNAME_OTHERWISE: |
| case StylesheetConstructionContext::ELEMNAME_PI: |
| case StylesheetConstructionContext::ELEMNAME_SORT: |
| case StylesheetConstructionContext::ELEMNAME_TEXT: |
| case StylesheetConstructionContext::ELEMNAME_VALUE_OF: |
| case StylesheetConstructionContext::ELEMNAME_WHEN: |
| case StylesheetConstructionContext::ELEMNAME_ELEMENT: |
| case StylesheetConstructionContext::ELEMNAME_APPLY_IMPORTS: |
| if (inExtensionElement() == false) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::IsNotAllowedInThisPosition_1Param, |
| name), |
| locator); |
| } |
| break; |
| |
| case StylesheetConstructionContext::ELEMNAME_STYLESHEET: |
| processStylesheet(name, atts, locator, fPreserveSpace, fSpaceAttrProcessed); |
| break; |
| |
| default: |
| if (inExtensionElement() == false) |
| { |
| if (m_constructionContext.getXSLTVersionSupported() < m_stylesheet.getXSLTVerDeclared()) |
| { |
| // Forward-compatible mode... |
| m_inExtensionElementStack.back() = true; |
| } |
| else |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::UnknownXSLElement_1Param, |
| name), |
| locator); |
| } |
| } |
| break; |
| } |
| } |
| |
| |
| void |
| StylesheetHandler::processStylesheet( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| const Locator* locator, |
| bool& fPreserveSpace, |
| bool& fSpaceAttrProcessed) |
| { |
| m_foundStylesheet = true; |
| |
| const XalanSize_t nAttrs = atts.getLength(); |
| |
| bool fVersionFound = false; |
| |
| for (XalanSize_t i = 0; i < nAttrs; ++i) |
| { |
| const XalanDOMChar* const aname = atts.getName(i); |
| |
| if (equals(aname, Constants::ATTRNAME_EXCLUDE_RESULT_PREFIXES)) |
| { |
| m_stylesheet.processExcludeResultPrefixes(m_constructionContext, atts.getValue(i)); |
| } |
| else if (equals(aname, Constants::ATTRNAME_EXTENSIONELEMENTPREFIXES)) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| XalanDOMString& prefix = theGuard.get(); |
| |
| StringTokenizer tokenizer(atts.getValue(i), |
| Constants::DEFAULT_WHITESPACE_SEPARATOR_STRING); |
| |
| while (tokenizer.hasMoreTokens() == true) |
| { |
| tokenizer.nextToken(prefix); |
| |
| const XalanDOMString* const extns = getNamespaceForPrefixFromStack(prefix); |
| |
| if (extns == 0) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::PrefixIsNotDeclared_1Param, |
| prefix), |
| locator); |
| } |
| |
| m_stylesheet.processExtensionNamespace(m_constructionContext, *extns); |
| } |
| } |
| else if (equals(aname, Constants::ATTRNAME_ID)) |
| { |
| // |
| } |
| else if (equals(aname, Constants::ATTRNAME_VERSION)) |
| { |
| const XalanDOMChar* const versionStr = atts.getValue(i); |
| assert(versionStr != 0); |
| |
| m_stylesheet.setXSLTVerDeclared(DoubleSupport::toDouble(versionStr, getMemoryManager())); |
| |
| fVersionFound = true; |
| } |
| else if (processSpaceAttr(name, aname, atts, i, locator, fPreserveSpace) == true) |
| { |
| fSpaceAttrProcessed = true; |
| } |
| else if (isAttrOK(aname, atts, i) == false) |
| { |
| if (false == m_stylesheet.isWrapperless()) |
| { |
| illegalAttributeError(name, aname, locator); |
| } |
| } |
| |
| if (!m_stylesheet.getNamespaces().empty()) |
| { |
| m_stylesheet.setNamespaceDecls(m_stylesheet.getNamespaces().back()); |
| } |
| } |
| |
| if (fVersionFound == false) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::StylesheetAttribDidNotSpecifyVersionAttrib), |
| locator); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processExtensionElement( |
| const XalanDOMChar* /* name */, |
| const XalanDOMString& /* localName */, |
| const AttributeListType& /* atts */, |
| const Locator* /* locator */) |
| { |
| } |
| |
| |
| |
| void |
| StylesheetHandler::checkForOrAddVariableName( |
| const XalanQName& theVariableName, |
| const Locator* theLocator) |
| { |
| if (inExtensionElement() == true) |
| { |
| // We can't really do anything yet here, because we |
| // don't handle extension elements. It would be |
| // better if we tried to track what was going on |
| // inside extension elements. |
| } |
| else if (m_inTemplate == false) |
| { |
| assert(m_inScopeVariableNamesStack.empty() == true); |
| |
| if (m_globalVariableNames.count(theVariableName) != 0) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::VariableHasBeenDeclared), |
| theLocator); |
| } |
| else |
| { |
| m_globalVariableNames.insert(theVariableName); |
| } |
| } |
| else |
| { |
| assert(m_inScopeVariableNamesStack.empty() == false); |
| |
| QNameSetVectorType::iterator theCurrent = m_inScopeVariableNamesStack.begin(); |
| const QNameSetVectorType::iterator theEnd = m_inScopeVariableNamesStack.end(); |
| |
| while(theCurrent != theEnd) |
| { |
| QNameSetVectorType::value_type& theLocalScope = *theCurrent; |
| |
| if (theLocalScope.count(theVariableName) != 0) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::VariableHasBeenDeclaredInThisTemplate), |
| theLocator); |
| } |
| |
| ++theCurrent; |
| } |
| |
| assert(theCurrent == theEnd); |
| |
| m_inScopeVariableNamesStack.back().insert(theVariableName); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processPreserveStripSpace( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| const Locator* locator, |
| int xslToken) |
| { |
| const XalanSize_t nAttrs = atts.getLength(); |
| |
| bool foundIt = false; |
| |
| const bool isPreserveSpace = |
| StylesheetConstructionContext::ELEMNAME_PRESERVE_SPACE == xslToken ? true : false; |
| |
| for (XalanSize_t i = 0; i < nAttrs; i++) |
| { |
| const XalanDOMChar* const aname = atts.getName(i); |
| |
| if (equals(aname, Constants::ATTRNAME_ELEMENTS)) |
| { |
| foundIt = true; |
| |
| StringTokenizer tokenizer(atts.getValue(i), |
| Constants::DEFAULT_WHITESPACE_SEPARATOR_STRING); |
| |
| const GetCachedString theGuard(m_constructionContext); |
| |
| XalanDOMString& theNameTest = theGuard.get(); |
| |
| const XalanQName::PrefixResolverProxy theProxy(m_stylesheet.getNamespaces(), m_stylesheet.getURI()); |
| |
| while (tokenizer.hasMoreTokens()) |
| { |
| tokenizer.nextToken(theNameTest); |
| |
| m_stylesheet.addWhitespaceElement( |
| XalanSpaceNodeTester( |
| isPreserveSpace == true ? |
| XalanSpaceNodeTester::ePreserve : |
| XalanSpaceNodeTester::eStrip, |
| m_constructionContext, |
| theNameTest, |
| theProxy, |
| locator)); |
| } |
| } |
| else if (!isAttrOK(aname, atts, i)) |
| { |
| illegalAttributeError(name, aname, locator); |
| } |
| } |
| |
| if (!foundIt && inExtensionElement() == false) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::ElementRequiresAttribute_2Param, |
| isPreserveSpace == true ? |
| Constants::ELEMNAME_PRESERVESPACE_WITH_PREFIX_STRING : |
| Constants::ELEMNAME_STRIPSPACE_WITH_PREFIX_STRING, |
| Constants::ATTRNAME_ELEMENTS), |
| locator); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::appendChildElementToParent( |
| ElemTemplateElement* parent, |
| ElemTemplateElement* elem) |
| { |
| assert(elem != 0); |
| |
| appendChildElementToParent(parent, elem, elem->getLocator()); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::appendChildElementToParent( |
| ElemTemplateElement* elem, |
| const Locator* locator) |
| { |
| appendChildElementToParent(m_elemStack.back(), elem, locator); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::appendChildElementToParent( |
| ElemTemplateElement* parent, |
| ElemTemplateElement* elem, |
| const Locator* locator) |
| { |
| assert(parent != 0 && elem != 0); |
| |
| try |
| { |
| parent->appendChildElem(elem); |
| } |
| catch(const XalanDOMException& e) |
| { |
| if (e.getExceptionCode() == XalanDOMException::HIERARCHY_REQUEST_ERR) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| const XalanMessages::Codes theCode = |
| elem->getXSLToken() == StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT ? |
| XalanMessages::ElemOrLTIsNotAllowed_1Param : |
| XalanMessages::ElemIsNotAllowed_1Param; |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| theCode, |
| elem->getElementName()), |
| locator); |
| } |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::doCleanup() |
| { |
| if (m_locatorsPushed > 0) |
| { |
| m_constructionContext.popLocatorStack(); |
| |
| --m_locatorsPushed; |
| } |
| |
| m_lastPopped = 0; |
| } |
| |
| |
| |
| static bool |
| stackContains( |
| const Stylesheet::URLStackType& stack, |
| const XalanDOMString& urlString) |
| { |
| const Stylesheet::URLStackType::size_type n = stack.size(); |
| |
| bool contains = false; |
| |
| for(Stylesheet::URLStackType::size_type i = 0; i < n && contains == false; ++i) |
| { |
| if(equals(stack[i], urlString)) |
| { |
| contains = true; |
| } |
| } |
| |
| return contains; |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processImport( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| const Locator* locator) |
| { |
| const XalanSize_t nAttrs = atts.getLength(); |
| |
| bool foundIt = false; |
| |
| const GetCachedString theGuard4(m_constructionContext); |
| XalanDOMString& hrefUrl = theGuard4.get(); |
| |
| for (XalanSize_t i = 0; i < nAttrs; i++) |
| { |
| const XalanDOMChar* const aname = atts.getName(i); |
| |
| if (equals(aname, Constants::ATTRNAME_HREF)) |
| { |
| foundIt = true; |
| |
| if (m_foundNotImport) |
| { |
| const GetCachedString theError(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theError.get(), |
| XalanMessages::ImportCanOnlyOccur), |
| locator); |
| } |
| |
| const GetCachedString theGuard1(m_constructionContext); |
| |
| XalanDOMString& saved_XSLNameSpaceURL = theGuard1.get(); |
| |
| saved_XSLNameSpaceURL = m_stylesheet.getXSLTNamespaceURI(); |
| |
| const GetCachedString theGuard2(m_constructionContext); |
| |
| XalanDOMString& href = theGuard2.get(); |
| |
| href = atts.getValue(i); |
| |
| const Stylesheet::URLStackType& includeStack = |
| m_stylesheet.getIncludeStack(); |
| assert(includeStack.empty() == false); |
| |
| hrefUrl = m_constructionContext.getURLStringFromString( |
| href, |
| includeStack.back(), |
| hrefUrl); |
| |
| assert(hrefUrl.empty() == false); |
| |
| Stylesheet::URLStackType& importStack = m_stylesheet.getStylesheetRoot().getImportStack(); |
| |
| if (stackContains(importStack, hrefUrl)) |
| { |
| const GetCachedString theError(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theError.get(), |
| XalanMessages::ImportingItself_1Param, |
| hrefUrl), |
| locator); |
| } |
| |
| importStack.push_back(hrefUrl); |
| |
| // This will take care of cleaning up the stylesheet if an exception |
| // is thrown. |
| typedef XalanMemMgrAutoPtr<Stylesheet> AutpPtr; |
| |
| AutpPtr importedStylesheet( |
| m_constructionContext.getMemoryManager(), |
| m_constructionContext.create( |
| m_stylesheet.getStylesheetRoot(), |
| hrefUrl)); |
| |
| StylesheetHandler tp(*importedStylesheet.get(), m_constructionContext); |
| |
| m_constructionContext.parseXML(hrefUrl, &tp, 0); |
| |
| // Add it to the imports, releasing the XalanAutoPtr... |
| m_stylesheet.addImport(importedStylesheet.get()); |
| |
| importedStylesheet.release(); |
| |
| assert(equals(importStack.back(), hrefUrl)); |
| importStack.pop_back(); |
| |
| m_stylesheet.setXSLTNamespaceURI(saved_XSLNameSpaceURL); |
| } |
| else if (!isAttrOK(aname, atts, i)) |
| { |
| illegalAttributeError(name, aname, locator); |
| } |
| } |
| |
| if (!foundIt) |
| { |
| const GetCachedString theError(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theError.get(), |
| XalanMessages::ElementRequiresAttribute_2Param, |
| Constants::ELEMNAME_IMPORT_WITH_PREFIX_STRING, |
| Constants::ATTRNAME_HREF), |
| locator); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processInclude( |
| const XalanDOMChar* name, |
| const AttributeListType& atts, |
| const Locator* locator) |
| { |
| const XalanSize_t nAttrs = atts.getLength(); |
| |
| bool foundIt = false; |
| |
| const GetCachedString theGuard1(m_constructionContext); |
| XalanDOMString& href = theGuard1.get(); |
| |
| const GetCachedString theGuard2(m_constructionContext); |
| XalanDOMString& hrefUrl = theGuard2.get(); |
| |
| for (XalanSize_t i = 0; i < nAttrs; i++) |
| { |
| const XalanDOMChar* const aname = atts.getName(i); |
| |
| if (equals(aname, Constants::ATTRNAME_HREF)) |
| { |
| foundIt = true; |
| |
| PushPopIncludeState theStateHandler(*this); |
| |
| href.assign(atts.getValue(i)); |
| |
| assert(m_stylesheet.getIncludeStack().back().c_str() != 0); |
| |
| m_constructionContext.getURLStringFromString(href, m_stylesheet.getIncludeStack().back(), hrefUrl); |
| |
| if (stackContains(m_stylesheet.getIncludeStack(), hrefUrl)) |
| { |
| const GetCachedString theError(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theError.get(), |
| XalanMessages::IncludingItself_1Param, |
| hrefUrl), |
| locator); |
| } |
| |
| m_stylesheet.getIncludeStack().push_back(hrefUrl); |
| |
| m_constructionContext.parseXML(hrefUrl, this, 0); |
| |
| assert(equals(m_stylesheet.getIncludeStack().back(), hrefUrl)); |
| m_stylesheet.getIncludeStack().pop_back(); |
| } |
| else if (!isAttrOK(aname, atts, i)) |
| { |
| illegalAttributeError(name, aname, locator); |
| } |
| } |
| |
| if (!foundIt) |
| { |
| const GetCachedString theError(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theError.get(), |
| XalanMessages::ElementRequiresAttribute_2Param, |
| Constants::ELEMNAME_INCLUDE_WITH_PREFIX_STRING, |
| Constants::ATTRNAME_HREF), |
| locator); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::endElement(const XMLCh* const /* name */) |
| { |
| processAccumulatedText(); |
| |
| m_whiteSpaceElems.clear(); |
| |
| m_stylesheet.popNamespaces(); |
| |
| assert(m_elemStack.empty() == false); |
| |
| m_lastPopped = m_elemStack.back(); |
| |
| assert(m_lastPopped != 0); |
| |
| m_elemStack.pop_back(); |
| m_lastPopped->setFinishedConstruction(true); |
| |
| const int tok = m_lastPopped->getXSLToken(); |
| |
| if (m_inTemplate == true) |
| { |
| assert(m_inScopeVariableNamesStack.empty() == false); |
| |
| m_inScopeVariableNamesStack.pop_back(); |
| } |
| |
| if (StylesheetConstructionContext::ELEMNAME_TEMPLATE == tok) |
| { |
| m_inTemplate = false; |
| m_pTemplate->addToStylesheet(m_constructionContext, m_stylesheet); |
| m_pTemplate = 0; |
| } |
| else if (StylesheetConstructionContext::ELEMNAME_PARAM == tok || |
| StylesheetConstructionContext::ELEMNAME_VARIABLE == tok) |
| { |
| if(m_lastPopped->getParentNodeElem() == 0) |
| { |
| // Top-level param or variable |
| m_inTemplate = false; |
| } |
| } |
| else if (StylesheetConstructionContext::ELEMNAME_ATTRIBUTE_SET == tok) |
| { |
| m_inTemplate = false; |
| } |
| |
| assert(m_inExtensionElementStack.empty() == false); |
| |
| m_inExtensionElementStack.pop_back(); |
| |
| assert(m_preserveSpaceStack.empty() == false); |
| |
| m_preserveSpaceStack.pop_back(); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::characters( |
| const XMLCh* const chars, |
| const size_type length) |
| { |
| if (m_inTemplate == false && |
| inExtensionElement() == false && |
| isXMLWhitespace(chars, 0, length) == false) |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::CharIsNotAllowedInStylesheet), |
| m_constructionContext.getLocatorFromStack()); |
| |
| } |
| else |
| { |
| accumulateText(chars, length); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::cdata( |
| const XMLCh* const chars, |
| const size_type length) |
| { |
| accumulateText(chars, length); |
| |
| processText(chars, length); |
| |
| m_lastPopped = 0; |
| } |
| |
| |
| |
| void |
| StylesheetHandler::ignorableWhitespace( |
| const XMLCh* const /*chars*/, |
| const size_type /*length*/) |
| { |
| // Ignore! |
| m_lastPopped = 0; |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processingInstruction( |
| const XMLCh* const /*target*/, |
| const XMLCh* const /*data*/) |
| { |
| if (isXMLWhitespace(m_accumulateText) == false) |
| { |
| processAccumulatedText(); |
| } |
| else |
| { |
| m_accumulateText.clear(); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::comment(const XMLCh* const /*data*/) |
| { |
| processAccumulatedText(); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::entityReference(const XMLCh* const /*name*/) |
| { |
| processAccumulatedText(); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::resetDocument() |
| { |
| m_accumulateText.clear(); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::charactersRaw( |
| const XMLCh* const /* chars */, |
| const size_type /* length */) |
| { |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processText( |
| const XMLCh* chars, |
| size_type length) |
| { |
| if (m_inTemplate) |
| { |
| ElemTemplateElement* parent = m_elemStack.back(); |
| assert(parent != 0); |
| |
| assert(m_preserveSpaceStack.empty() == false); |
| |
| bool preserveSpace = m_preserveSpaceStack.back(); |
| bool disableOutputEscaping = false; |
| |
| if (preserveSpace == false && |
| parent->getXSLToken() == StylesheetConstructionContext::ELEMNAME_TEXT) |
| { |
| disableOutputEscaping = static_cast<ElemText*>(parent)->getDisableOutputEscaping(); |
| |
| preserveSpace = true; |
| |
| parent = m_elemStack[m_elemStack.size() - 2]; |
| } |
| |
| const Locator* const locator = m_constructionContext.getLocatorFromStack(); |
| |
| ElemTemplateElement* const elem = |
| m_constructionContext.createElement( |
| m_stylesheet, |
| chars, |
| length, |
| preserveSpace, |
| disableOutputEscaping, |
| locator); |
| assert(elem != 0); |
| |
| const bool isWhite = elem->isWhitespace(); |
| |
| if (preserveSpace || (!preserveSpace && !isWhite)) |
| { |
| while (!m_whiteSpaceElems.empty()) |
| { |
| assert(m_whiteSpaceElems.back() != 0); |
| |
| appendChildElementToParent( |
| parent, |
| m_whiteSpaceElems.back()); |
| |
| m_whiteSpaceElems.pop_back(); |
| } |
| |
| appendChildElementToParent( |
| parent, |
| elem); |
| } |
| else if (isWhite) |
| { |
| bool shouldPush = true; |
| |
| ElemTemplateElement* const last = parent->getLastChildElem(); |
| |
| if (0 != last) |
| { |
| // If it was surrounded by xsl:text, it will count as an element. |
| const bool isPrevCharData = |
| StylesheetConstructionContext::ELEMNAME_TEXT_LITERAL_RESULT == last->getXSLToken(); |
| |
| const bool isLastPoppedXSLText = (m_lastPopped != 0) && |
| (StylesheetConstructionContext::ELEMNAME_TEXT == m_lastPopped->getXSLToken()); |
| |
| if (isPrevCharData == true && isLastPoppedXSLText == false) |
| { |
| appendChildElementToParent( |
| parent, |
| elem); |
| |
| shouldPush = false; |
| } |
| } |
| |
| if (shouldPush) |
| { |
| m_whiteSpaceElems.push_back(elem); |
| } |
| } |
| } |
| // TODO: Flag error if text inside of stylesheet |
| } |
| |
| |
| |
| void |
| StylesheetHandler::accumulateText( |
| const XMLCh* chars, |
| size_type length) |
| { |
| if (m_inTemplate) |
| { |
| m_accumulateText.append(chars, length); |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::processAccumulatedText() |
| { |
| if (m_accumulateText.empty() == false) |
| { |
| processText(m_accumulateText.c_str(), m_accumulateText.length()); |
| |
| m_accumulateText.clear(); |
| } |
| } |
| |
| |
| |
| bool |
| StylesheetHandler::inExtensionElement() const |
| { |
| using std::find; |
| |
| if (!(find( |
| m_inExtensionElementStack.begin(), |
| m_inExtensionElementStack.end(), |
| true) == m_inExtensionElementStack.end())) |
| { |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| |
| |
| void |
| StylesheetHandler::error( |
| const XalanDOMString& theMessage, |
| const Locator* theLocator) const |
| { |
| m_constructionContext.problem( |
| StylesheetConstructionContext::eXSLTProcessor, |
| StylesheetConstructionContext::eError, |
| theMessage, |
| theLocator, |
| 0); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::error( |
| const XalanDOMChar* theMessage1, |
| const XalanDOMChar* theMessage2, |
| const Locator* theLocator) const |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| XalanDOMString& msg = theGuard.get(); |
| |
| msg = theMessage1; |
| msg += theMessage2; |
| |
| error(msg, theLocator); |
| } |
| |
| |
| |
| |
| void |
| StylesheetHandler::error( |
| const XalanDOMChar* theMessage1, |
| const XalanDOMString& theMessage2, |
| const Locator* theLocator) const |
| { |
| error(theMessage1, theMessage2.c_str(), theLocator); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::error( |
| const XalanDOMString& theMessage1, |
| const XalanDOMChar* theMessage2, |
| const Locator* theLocator) const |
| { |
| error(theMessage1.c_str(), theMessage2, theLocator); |
| } |
| |
| |
| |
| |
| void |
| StylesheetHandler::error( |
| const XalanDOMString& theMessage1, |
| const XalanDOMString& theMessage2, |
| const Locator* theLocator) const |
| { |
| error(theMessage1.c_str(), theMessage2.c_str(), theLocator); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::warn( |
| const XalanDOMChar* theMessage1, |
| const XalanDOMString& theMessage2, |
| const Locator* theLocator) const |
| { |
| warn(theMessage1, theMessage2.c_str(), theLocator); |
| } |
| |
| void |
| StylesheetHandler::warn( |
| const XalanDOMString& theMessage, |
| const Locator* theLocator) const |
| { |
| m_constructionContext.problem( |
| StylesheetConstructionContext::eXSLTProcessor, |
| StylesheetConstructionContext::eWarning, |
| theMessage, |
| theLocator, |
| 0); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::warn( |
| const XalanDOMChar* theMessage1, |
| const XalanDOMChar* theMessage2, |
| const Locator* theLocator) const |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| XalanDOMString& msg = theGuard.get(); |
| |
| msg = theMessage1; |
| msg += theMessage2; |
| |
| m_constructionContext.problem( |
| StylesheetConstructionContext::eXSLTProcessor, |
| StylesheetConstructionContext::eWarning, |
| msg, |
| theLocator, |
| 0); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::illegalAttributeError( |
| const XalanDOMChar* theElementName, |
| const XalanDOMChar* theAttributeName, |
| const Locator* theLocator) const |
| |
| { |
| const GetCachedString theGuard(m_constructionContext); |
| |
| error( |
| XalanMessageLoader::getMessage( |
| theGuard.get(), |
| XalanMessages::HasIllegalAttribute_2Param, |
| theElementName, |
| theAttributeName), |
| theLocator); |
| } |
| |
| |
| |
| StylesheetHandler::PushPopIncludeState::PushPopIncludeState(StylesheetHandler& theHandler) : |
| m_handler(theHandler), |
| m_elemStack(theHandler.m_elemStack, theHandler.getMemoryManager()), |
| m_pTemplate(theHandler.m_pTemplate), |
| m_lastPopped(theHandler), |
| m_inTemplate(theHandler.m_inTemplate), |
| m_foundStylesheet(theHandler.m_foundStylesheet), |
| m_XSLNameSpaceURL(theHandler.m_stylesheet.getXSLTNamespaceURI(), theHandler.getMemoryManager()), |
| m_foundNotImport(theHandler.m_foundNotImport), |
| m_namespaceDecls(theHandler.getMemoryManager()), |
| m_namespaces(theHandler.getMemoryManager()), |
| m_namespacesHandler(theHandler.getMemoryManager()), |
| m_inExtensionElementStack(theHandler.getMemoryManager()), |
| m_preserveSpaceStack(theHandler.getMemoryManager()) |
| { |
| m_handler.m_accumulateText.clear(); |
| |
| m_handler.m_elemStack.clear(); |
| m_handler.m_pTemplate = 0; |
| |
| m_lastPopped.swap(theHandler.m_lastPopped); |
| |
| m_handler.m_inTemplate = false; |
| m_handler.m_foundStylesheet = false; |
| m_handler.m_foundNotImport = false; |
| |
| // This is much more efficient, since we're just swapping |
| // underlying data. This clears out the stack as well... |
| m_namespaceDecls.swap(theHandler.m_stylesheet.getNamespaceDecls()); |
| m_namespaces.swap(theHandler.m_stylesheet.getNamespaces()); |
| m_namespacesHandler.swap(theHandler.m_stylesheet.getNamespacesHandler()); |
| m_inExtensionElementStack.swap(theHandler.m_inExtensionElementStack); |
| m_preserveSpaceStack.swap(theHandler.m_preserveSpaceStack); |
| } |
| |
| |
| |
| StylesheetHandler::PushPopIncludeState::~PushPopIncludeState() |
| { |
| m_handler.m_accumulateText.clear(); |
| m_handler.m_elemStack = m_elemStack; |
| m_handler.m_pTemplate = m_pTemplate; |
| |
| m_lastPopped.swap(m_handler.m_lastPopped); |
| |
| m_handler.m_inTemplate = m_inTemplate; |
| m_handler.m_foundStylesheet = m_foundStylesheet; |
| m_handler.m_stylesheet.setXSLTNamespaceURI(m_XSLNameSpaceURL); |
| m_handler.m_foundNotImport = m_foundNotImport; |
| |
| // This is much more efficient, since we're just swapping |
| // underlying data. |
| m_handler.m_stylesheet.getNamespaceDecls().swap(m_namespaceDecls); |
| m_handler.m_stylesheet.getNamespaces().swap(m_namespaces); |
| m_handler.m_stylesheet.getNamespacesHandler().swap(m_namespacesHandler); |
| m_handler.m_inExtensionElementStack.swap(m_inExtensionElementStack); |
| m_handler.m_preserveSpaceStack.swap(m_preserveSpaceStack); |
| } |
| |
| |
| |
| void |
| StylesheetHandler::LastPoppedHolder::cleanup() |
| { |
| if (m_lastPopped != 0) |
| { |
| const int tok = m_lastPopped->getXSLToken(); |
| |
| if (tok == StylesheetConstructionContext::ELEMNAME_UNDEFINED) |
| { |
| m_stylesheetHandler.m_elemEmptyAllocator.destroy(static_cast<ElemEmpty*>(m_lastPopped)); |
| } |
| else if (tok == StylesheetConstructionContext::ELEMNAME_TEXT) |
| { |
| m_stylesheetHandler.m_elemTextAllocator.destroy(static_cast<ElemText*>(m_lastPopped)); |
| } |
| } |
| } |
| |
| |
| |
| const XalanDOMString StylesheetHandler::s_emptyString(XalanMemMgrs::getDummyMemMgr()); |
| |
| |
| |
| void |
| StylesheetHandler::initialize(MemoryManager& /* theManager*/) |
| { |
| } |
| |
| |
| |
| void |
| StylesheetHandler::terminate() |
| { |
| } |
| |
| |
| |
| } |