| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 1999, International |
| * Business Machines, Inc., http://www.ibm.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| |
| |
| // Class header file. |
| #include "XSLTEngineImpl.hpp" |
| |
| |
| |
| #include <sax/DocumentHandler.hpp> |
| #include <sax/EntityResolver.hpp> |
| #include <sax/Locator.hpp> |
| #include <sax/SAXException.hpp> |
| #include <util/PlatformUtils.hpp> |
| #include <framework/URLInputSource.hpp> |
| |
| |
| |
| #include <Include/STLHelper.hpp> |
| |
| |
| |
| #include <XalanDOM/XalanDOMException.hpp> |
| #include <XalanDOM/XalanNode.hpp> |
| #include <XalanDOM/XalanAttr.hpp> |
| #include <XalanDOM/XalanComment.hpp> |
| #include <XalanDOM/XalanCDATASection.hpp> |
| #include <XalanDOM/XalanNodeList.hpp> |
| #include <XalanDOM/XalanNamedNodeMap.hpp> |
| #include <XalanDOM/XalanProcessingInstruction.hpp> |
| #include <XalanDOM/XalanText.hpp> |
| |
| |
| |
| #include <PlatformSupport/PrintWriter.hpp> |
| #include <PlatformSupport/StringTokenizer.hpp> |
| #include <PlatformSupport/XalanUnicode.hpp> |
| |
| |
| |
| #include <DOMSupport/DOMServices.hpp> |
| #include <DOMSupport/DOMSupport.hpp> |
| |
| |
| |
| #include <XMLSupport/FormatterToDOM.hpp> |
| #include <XMLSupport/FormatterToText.hpp> |
| #include <XMLSupport/FormatterToXML.hpp> |
| #include <XMLSupport/FormatterToHTML.hpp> |
| #include <XMLSupport/FormatterTreeWalker.hpp> |
| #include <XMLSupport/XMLParserLiaison.hpp> |
| #include <XMLSupport/FormatterTreeWalker.hpp> |
| |
| |
| |
| #include <XPath/ElementPrefixResolverProxy.hpp> |
| #include <XPath/XalanQNameByReference.hpp> |
| #include <XPath/ResultTreeFrag.hpp> |
| #include <XPath/XObject.hpp> |
| #include <XPath/XObjectFactory.hpp> |
| #include <XPath/XPathEnvSupport.hpp> |
| #include <XPath/XPathEnvSupportDefault.hpp> |
| #include <XPath/XPathExecutionContextDefault.hpp> |
| #include <XPath/XPathFactory.hpp> |
| #include <XPath/XPathProcessorImpl.hpp> |
| #include <XPath/XResultTreeFrag.hpp> |
| |
| |
| |
| #include "Constants.hpp" |
| #include "ElemWithParam.hpp" |
| #include "FunctionCurrent.hpp" |
| #include "FunctionDocument.hpp" |
| #include "FunctionElementAvailable.hpp" |
| #include "FunctionFunctionAvailable.hpp" |
| #include "FunctionFormatNumber.hpp" |
| #include "FunctionGenerateID.hpp" |
| #include "FunctionKey.hpp" |
| #include "FunctionSystemProperty.hpp" |
| #include "FunctionUnparsedEntityURI.hpp" |
| #include "GenerateEvent.hpp" |
| #include "ProblemListener.hpp" |
| #include "ProblemListenerDefault.hpp" |
| #include "Stylesheet.hpp" |
| #include "StylesheetConstructionContext.hpp" |
| #include "StylesheetExecutionContext.hpp" |
| #include "StylesheetHandler.hpp" |
| #include "StylesheetRoot.hpp" |
| #include "TraceListener.hpp" |
| #include "XSLTInputSource.hpp" |
| #include "XSLTProcessorException.hpp" |
| #include "XSLTResultTarget.hpp" |
| |
| |
| |
| //#define XALAN_VQ_SPECIAL_TRACE |
| #if defined(XALAN_VQ_SPECIAL_TRACE) |
| #include "C:/Program Files/Rational/Quantify/pure.h" |
| #endif |
| |
| |
| |
| const XalanDOMString XSLTEngineImpl::s_emptyString; |
| |
| |
| |
| //========================================================== |
| // SECTION: Constructors |
| //========================================================== |
| |
| XSLTEngineImpl::XSLTEngineImpl( |
| XMLParserLiaison& parserLiaison, |
| XPathEnvSupport& xpathEnvSupport, |
| DOMSupport& domSupport, |
| XObjectFactory& xobjectFactory, |
| XPathFactory& xpathFactory) : |
| XSLTProcessor(), |
| DocumentHandler(), |
| PrefixResolver(), |
| m_useDOMResultTreeFactory(false), |
| m_domResultTreeFactory(0), |
| m_resultNameSpacePrefix(), |
| m_resultNameSpaceURL(), |
| m_xpathFactory(xpathFactory), |
| m_xobjectFactory(xobjectFactory), |
| m_xpathProcessor(new XPathProcessorImpl), |
| m_cdataStack(), |
| m_stylesheetLocatorStack(), |
| m_defaultProblemListener(), |
| m_problemListener(&m_defaultProblemListener), |
| m_stylesheetRoot(0), |
| m_traceSelects(false), |
| m_quietConflictWarnings(false), |
| m_diagnosticsPrintWriter(0), |
| m_durationsTable(), |
| m_traceListeners(), |
| m_uniqueNSValue(0), |
| m_topLevelParams(), |
| m_parserLiaison(parserLiaison), |
| m_xpathEnvSupport(xpathEnvSupport), |
| m_domSupport(domSupport), |
| m_executionContext(0), |
| m_outputContextStack(), |
| m_resultNamespacesStack(), |
| m_dummyAttributesList() |
| { |
| m_outputContextStack.pushContext(); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::reset() |
| { |
| m_topLevelParams.clear(); |
| m_durationsTable.clear(); |
| m_stylesheetLocatorStack.clear(); |
| m_cdataStack.clear(); |
| |
| if (m_domResultTreeFactory != 0) |
| { |
| m_parserLiaison.destroyDocument(m_domResultTreeFactory); |
| m_domResultTreeFactory = 0; |
| } |
| |
| m_stylesheetRoot = 0; |
| |
| m_outputContextStack.reset(); |
| |
| m_outputContextStack.pushContext(); |
| |
| m_xpathEnvSupport.reset(); |
| m_xpathFactory.reset(); |
| m_xobjectFactory.reset(); |
| m_domSupport.reset(); |
| |
| m_resultNamespacesStack.clear(); |
| } |
| |
| |
| |
| XSLTEngineImpl::~XSLTEngineImpl() |
| { |
| reset(); |
| } |
| |
| |
| |
| //========================================================== |
| // SECTION: Main API Functions |
| //========================================================== |
| |
| |
| |
| static const XalanDOMChar s_dummyString = 0; |
| |
| |
| void |
| XSLTEngineImpl::process( |
| const XSLTInputSource& inputSource, |
| const XSLTInputSource& stylesheetSource, |
| XSLTResultTarget& outputTarget, |
| StylesheetConstructionContext& constructionContext, |
| StylesheetExecutionContext& executionContext) |
| { |
| XalanDOMString xslIdentifier; |
| |
| if (0 == stylesheetSource.getSystemId()) |
| { |
| xslIdentifier = XalanDOMString(XALAN_STATIC_UCODE_STRING("Input XSL")); |
| } |
| else |
| { |
| xslIdentifier = stylesheetSource.getSystemId(); |
| } |
| |
| bool totalTimeID = true; |
| |
| pushTime(&totalTimeID); |
| |
| XalanNode* sourceTree = getSourceTreeFromInput(inputSource); |
| |
| m_stylesheetRoot = processStylesheet(stylesheetSource, constructionContext); |
| |
| if(0 != sourceTree && m_stylesheetRoot == 0) |
| { |
| // Didn't get a stylesheet from the input source, so look for a |
| // stylesheet processing instruction... |
| XalanDOMString stylesheetURI; |
| |
| // The PI must be a child of the document... |
| XalanNode* child = sourceTree->getFirstChild(); |
| |
| #if !defined(XALAN_NO_NAMESPACES) |
| using std::vector; |
| #endif |
| |
| vector<XalanDOMString> hrefs; |
| |
| // $$$ ToDo: is this first one style valid? |
| const XalanDOMString stylesheetNodeName1(XALAN_STATIC_UCODE_STRING("xml-stylesheet")); |
| const XalanDOMString stylesheetNodeName2(XALAN_STATIC_UCODE_STRING("xml:stylesheet")); |
| |
| // $$$ ToDo: This code is much like that in getStyleSheetURIFromDoc(). |
| // Why is it repeated??? |
| // $$$ ToDo: Move these embedded strings from inside these loops |
| // out here... |
| // $$$ ToDo: These loops are a mess of repeated use of the |
| // same data values. |
| while(child != 0) |
| { |
| if(XalanNode::PROCESSING_INSTRUCTION_NODE == child->getNodeType()) |
| { |
| const XalanDOMString nodeName(child->getNodeName()); |
| |
| if(equals(nodeName, stylesheetNodeName1) || |
| equals(nodeName, stylesheetNodeName2)) |
| { |
| bool isOK = true; |
| |
| StringTokenizer tokenizer(child->getNodeValue(), XALAN_STATIC_UCODE_STRING(" \t=")); |
| |
| while(tokenizer.hasMoreTokens()) |
| { |
| if(equals(tokenizer.nextToken(), XALAN_STATIC_UCODE_STRING("type"))) |
| { |
| XalanDOMString typeVal = tokenizer.nextToken(); |
| |
| typeVal = substring(typeVal, 1, length(typeVal) - 1); |
| |
| if(!equals(typeVal, XALAN_STATIC_UCODE_STRING("text/xsl"))) |
| { |
| isOK = false; |
| } |
| } |
| } |
| |
| if(isOK) |
| { |
| StringTokenizer tokenizer(child->getNodeValue(), XALAN_STATIC_UCODE_STRING(" \t=")); |
| |
| while(tokenizer.hasMoreTokens()) |
| { |
| const XalanDOMString theCurrentToken = tokenizer.nextToken(); |
| |
| if(equals(theCurrentToken, XALAN_STATIC_UCODE_STRING("href"))) |
| { |
| stylesheetURI = tokenizer.nextToken(); |
| stylesheetURI = substring(stylesheetURI, 1, length(stylesheetURI) - 1); |
| hrefs.push_back(stylesheetURI); |
| } |
| } |
| } |
| } |
| } |
| |
| child = child->getNextSibling(); |
| } |
| |
| bool isRoot = true; |
| Stylesheet* prevStylesheet = 0; |
| |
| if (hrefs.empty() == false) |
| { |
| const XalanDOMChar* const pxch = inputSource.getSystemId(); |
| |
| const XalanDOMString sysid(pxch == 0 ? &s_dummyString : pxch); |
| |
| do |
| { |
| const XalanDOMString& ref = hrefs.back(); |
| |
| Stylesheet* stylesheet = |
| getStylesheetFromPIURL( |
| ref, |
| *sourceTree, |
| sysid, |
| isRoot, |
| constructionContext); |
| |
| if(false == isRoot) |
| { |
| prevStylesheet->addImport(stylesheet, false); |
| } |
| |
| prevStylesheet = stylesheet; |
| isRoot = false; |
| hrefs.pop_back(); |
| } while(!hrefs.empty()); |
| } |
| } |
| |
| if(0 == m_stylesheetRoot) |
| { |
| error("Failed to process stylesheet!"); |
| } |
| else if(0 != sourceTree) |
| { |
| executionContext.setStylesheetRoot(m_stylesheetRoot); |
| |
| FormatterListener* const theFormatter = |
| outputTarget.getDocumentHandler(); |
| |
| if (theFormatter != 0) |
| { |
| theFormatter->setPrefixResolver(this); |
| } |
| |
| m_stylesheetRoot->process(sourceTree, outputTarget, executionContext); |
| |
| if(0 != m_diagnosticsPrintWriter) |
| { |
| displayDuration(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Total time")), &totalTimeID); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::process( |
| const XSLTInputSource& inputSource, |
| XSLTResultTarget& outputTarget, |
| StylesheetExecutionContext& executionContext) |
| { |
| bool totalTimeID = true; |
| |
| if(0 != m_diagnosticsPrintWriter) |
| { |
| pushTime(&totalTimeID); |
| } |
| |
| XalanNode* const sourceTree = getSourceTreeFromInput(inputSource); |
| |
| if(0 != sourceTree) |
| { |
| if (m_stylesheetRoot == 0) |
| { |
| error("No stylesheet is available to process!"); |
| } |
| |
| FormatterListener* const theFormatter = |
| outputTarget.getDocumentHandler(); |
| |
| if (theFormatter != 0) |
| { |
| theFormatter->setPrefixResolver(this); |
| } |
| |
| m_stylesheetRoot->process(sourceTree, outputTarget, executionContext); |
| } |
| |
| if(0 != m_diagnosticsPrintWriter) |
| { |
| displayDuration(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Total time")), &totalTimeID); |
| } |
| } |
| |
| |
| |
| StylesheetRoot* |
| XSLTEngineImpl::processStylesheet( |
| const XalanDOMString& xsldocURLString, |
| StylesheetConstructionContext& constructionContext) |
| { |
| const XSLTInputSource input(c_wstr(xsldocURLString)); |
| |
| return processStylesheet(input, constructionContext); |
| } |
| |
| |
| |
| StylesheetRoot* |
| XSLTEngineImpl::processStylesheet( |
| const XSLTInputSource& stylesheetSource, |
| StylesheetConstructionContext& constructionContext) |
| { |
| StylesheetRoot* theStylesheet = 0; |
| |
| const XalanDOMChar* const systemID = stylesheetSource.getSystemId(); |
| XalanNode* const stylesheetNode = stylesheetSource.getNode(); |
| |
| if (systemID != 0 || stylesheetNode != 0 || stylesheetSource.getStream() != 0) |
| { |
| XalanDOMString xslIdentifier; |
| |
| theStylesheet = constructionContext.create(stylesheetSource); |
| |
| StylesheetHandler stylesheetProcessor(*theStylesheet, constructionContext); |
| |
| if(stylesheetNode != 0) |
| { |
| xslIdentifier = XALAN_STATIC_UCODE_STRING("Input XSL"); |
| |
| FormatterTreeWalker tw(stylesheetProcessor); |
| |
| tw.traverse(stylesheetSource.getNode()); |
| } |
| else |
| { |
| if (systemID != 0) |
| { |
| xslIdentifier = systemID; |
| } |
| |
| diag(XALAN_STATIC_UCODE_STRING("========= Parsing ") + xslIdentifier + XALAN_STATIC_UCODE_STRING(" ==========")); |
| |
| pushTime(&xslIdentifier); |
| |
| m_parserLiaison.parseXMLStream(stylesheetSource, |
| stylesheetProcessor); |
| |
| if(0 != m_diagnosticsPrintWriter) |
| displayDuration(XALAN_STATIC_UCODE_STRING("Parse of ") + xslIdentifier, &xslIdentifier); |
| } |
| |
| theStylesheet->postConstruction(constructionContext); |
| } |
| |
| return theStylesheet; |
| } |
| |
| |
| |
| //========================================================== |
| // SECTION: XML Parsing Functions |
| //========================================================== |
| |
| XalanNode* |
| XSLTEngineImpl::getSourceTreeFromInput(const XSLTInputSource& inputSource) |
| { |
| XalanNode* sourceTree = inputSource.getNode(); |
| |
| if(0 == sourceTree) |
| { |
| const XalanDOMString xmlIdentifier = 0 != inputSource.getSystemId() ? |
| XalanDOMString(inputSource.getSystemId()) : |
| StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Input XML")); |
| |
| // In case we have a fragment identifier, go ahead and |
| // try to parse the XML here. |
| diag(XALAN_STATIC_UCODE_STRING("========= Parsing ") + |
| xmlIdentifier + |
| XALAN_STATIC_UCODE_STRING(" ==========")); |
| |
| pushTime(&xmlIdentifier); |
| |
| #if defined(XALAN_VQ_SPECIAL_TRACE) |
| QuantifyStartRecordingData(); |
| #endif |
| |
| XalanDocument* const theDocument = |
| m_parserLiaison.parseXMLStream(inputSource, |
| xmlIdentifier); |
| assert(theDocument != 0); |
| |
| #if defined(XALAN_VQ_SPECIAL_TRACE) |
| QuantifyStopRecordingData(); |
| #endif |
| if(0 != m_diagnosticsPrintWriter) |
| { |
| displayDuration( |
| XALAN_STATIC_UCODE_STRING("Parse of ") + xmlIdentifier, |
| &xmlIdentifier); |
| } |
| |
| m_xpathEnvSupport.setSourceDocument(xmlIdentifier, theDocument); |
| |
| sourceTree = theDocument; |
| } |
| |
| return sourceTree; |
| } |
| |
| |
| |
| const XalanDOMString* |
| XSLTEngineImpl::getNamespaceForPrefix(const XalanDOMString& prefix) const |
| { |
| return m_resultNamespacesStack.getNamespaceForPrefix(prefix); |
| } |
| |
| |
| |
| const XalanDOMString& |
| XSLTEngineImpl::getURI() const |
| { |
| return s_emptyString; |
| } |
| |
| |
| |
| XalanDocument* |
| XSLTEngineImpl::parseXML( |
| const XalanDOMString& urlString, |
| DocumentHandler* docHandler, |
| XalanDocument* docToRegister) |
| { |
| |
| XalanDocument* doc = |
| m_xpathEnvSupport.getSourceDocument(urlString); |
| |
| if(doc == 0) |
| { |
| EntityResolver* const theResolver = |
| m_parserLiaison.getEntityResolver(); |
| |
| if (theResolver == 0) |
| { |
| const XSLTInputSource inputSource(c_wstr(urlString)); |
| |
| doc = parseXML(inputSource, docHandler, docToRegister); |
| } |
| else |
| { |
| const XalanAutoPtr<InputSource> resolverInputSource = |
| theResolver->resolveEntity(0, c_wstr(urlString)); |
| |
| if (resolverInputSource.get() != 0) |
| { |
| doc = parseXML(*resolverInputSource.get(), docHandler, docToRegister); |
| } |
| else |
| { |
| const XSLTInputSource inputSource(c_wstr(urlString)); |
| |
| doc = parseXML(inputSource, docHandler, docToRegister); |
| } |
| } |
| |
| if (doc != 0) |
| { |
| m_xpathEnvSupport.setSourceDocument(urlString, doc); |
| } |
| } |
| |
| return doc; |
| } |
| |
| |
| |
| XalanDocument* |
| XSLTEngineImpl::parseXML( |
| const InputSource& inputSource, |
| DocumentHandler* docHandler, |
| XalanDocument* docToRegister) |
| { |
| if(0 != docHandler) |
| { |
| m_parserLiaison.parseXMLStream(inputSource, *docHandler); |
| |
| return docToRegister; |
| } |
| else |
| { |
| return m_parserLiaison.parseXMLStream(inputSource); |
| } |
| } |
| |
| |
| |
| Stylesheet* |
| XSLTEngineImpl::getStylesheetFromPIURL( |
| const XalanDOMString& xslURLString, |
| XalanNode& fragBase, |
| const XalanDOMString& xmlBaseIdent, |
| bool isRoot, |
| StylesheetConstructionContext& constructionContext) |
| { |
| Stylesheet* stylesheet = 0; |
| |
| XalanDOMString stringHolder; |
| |
| XalanDOMString localXSLURLString = trim(xslURLString); |
| |
| const unsigned int fragIndex = indexOf(localXSLURLString, XalanUnicode::charNumberSign); |
| |
| const XalanDocument* stylesheetDoc = 0; |
| |
| if(fragIndex == 0) |
| { |
| diag("Locating stylesheet from fragment identifier..."); |
| |
| const XalanDOMString fragID = substring(localXSLURLString, 1); |
| |
| const XalanElement* nsNode = 0; |
| |
| const XalanNode::NodeType theType = fragBase.getNodeType(); |
| |
| if (theType == XalanNode::DOCUMENT_NODE) |
| { |
| const XalanDocument& doc = |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (const XalanDocument&)fragBase; |
| #else |
| static_cast<const XalanDocument&>(fragBase); |
| #endif |
| |
| nsNode = doc.getDocumentElement(); |
| } |
| else if (theType == XalanNode::ELEMENT_NODE) |
| { |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| nsNode = (const XalanElement*)&fragBase; |
| #else |
| nsNode = static_cast<const XalanElement*>(&fragBase); |
| #endif |
| } |
| else |
| { |
| XalanNode* const node = fragBase.getParentNode(); |
| |
| if (node->getNodeType() == XalanNode::ELEMENT_NODE) |
| { |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| nsNode = (const XalanElement*)&fragBase; |
| #else |
| nsNode = static_cast<XalanElement*>(node); |
| #endif |
| } |
| else |
| { |
| error("Could not identify fragment: " + fragID); |
| } |
| } |
| |
| // Try a bunch of really ugly stuff to find the fragment. |
| // What's the right way to do this? |
| XalanDOMString ds(XALAN_STATIC_UCODE_STRING("id(")); |
| |
| ds += fragID; |
| ds += XALAN_STATIC_UCODE_STRING(")"); |
| |
| ElementPrefixResolverProxy theProxy(nsNode, m_xpathEnvSupport, m_domSupport); |
| |
| XPathExecutionContextDefault theExecutionContext(m_xpathEnvSupport, |
| m_domSupport, |
| m_xobjectFactory, |
| &fragBase, |
| 0, |
| &theProxy); |
| |
| const XObjectPtr xobj(evalXPathStr(ds, theExecutionContext)); |
| assert(xobj.null() == false); |
| |
| NodeRefList nl(xobj->nodeset()); |
| |
| if(nl.getLength() == 0) |
| { |
| NodeRefList theEmptyList; |
| |
| ds = XALAN_STATIC_UCODE_STRING("//*[@id='"); |
| ds += fragID; |
| ds += XALAN_STATIC_UCODE_STRING("']"); |
| |
| theExecutionContext.setContextNodeList(theEmptyList); |
| |
| const XObjectPtr xobj(evalXPathStr(ds, theExecutionContext)); |
| assert(xobj.null() == false); |
| |
| nl = xobj->nodeset(); |
| |
| if(nl.getLength() == 0) |
| { |
| ds = XALAN_STATIC_UCODE_STRING("//*[@name='"); |
| ds += fragID; |
| ds += XALAN_STATIC_UCODE_STRING("']"); |
| |
| theExecutionContext.setContextNodeList(theEmptyList); |
| |
| const XObjectPtr xobj(evalXPathStr(ds, theExecutionContext)); |
| assert(xobj.null() == false); |
| |
| nl = xobj->nodeset(); |
| |
| if(nl.getLength() == 0) |
| { |
| // Well, hell, maybe it's an XPath... |
| theExecutionContext.setContextNodeList(theEmptyList); |
| |
| const XObjectPtr xobj(evalXPathStr(fragID, theExecutionContext)); |
| assert(xobj.null() == false); |
| |
| nl = xobj->nodeset(); |
| } |
| } |
| } |
| |
| if(nl.getLength() == 0) |
| { |
| error("Could not find fragment: " + fragID); |
| } |
| |
| XalanNode* const frag = nl.item(0); |
| |
| if(XalanNode::ELEMENT_NODE == frag->getNodeType()) |
| { |
| pushTime(frag); |
| |
| XalanAutoPtr<Stylesheet> theGuard; |
| |
| if(isRoot) |
| { |
| StylesheetRoot* const theLocalRoot = |
| constructionContext.create(stringHolder); |
| |
| stylesheet = theLocalRoot; |
| |
| m_stylesheetRoot = theLocalRoot; |
| } |
| else |
| { |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| stylesheet = constructionContext.create(*((StylesheetRoot*)m_stylesheetRoot), stringHolder); |
| #else |
| stylesheet = constructionContext.create(*const_cast<StylesheetRoot*>(m_stylesheetRoot), stringHolder); |
| #endif |
| |
| theGuard.reset(stylesheet); |
| } |
| |
| StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext); |
| |
| FormatterTreeWalker tw(stylesheetProcessor); |
| |
| tw.traverse(frag, frag->getParentNode()); |
| |
| displayDuration( |
| XalanDOMString(XALAN_STATIC_UCODE_STRING("Setup of ")) + |
| localXSLURLString, |
| frag); |
| |
| stylesheet->postConstruction(constructionContext); |
| |
| theGuard.release(); |
| } |
| else |
| { |
| stylesheetDoc = 0; |
| error("Node pointed to by fragment identifier was not an element: " + fragID); |
| } |
| } |
| else |
| { |
| diag(XalanDOMString(XALAN_STATIC_UCODE_STRING("========= Parsing and preparing ")) + |
| localXSLURLString + |
| XALAN_STATIC_UCODE_STRING(" ==========")); |
| pushTime(&localXSLURLString); |
| |
| XalanAutoPtr<Stylesheet> theGuard; |
| |
| const XalanDocument* const theOwnerDocument = |
| fragBase.getNodeType() == XalanNode::DOCUMENT_NODE ? |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (const XalanDocument*)&fragBase : |
| #else |
| static_cast<const XalanDocument*>(&fragBase) : |
| #endif |
| fragBase.getOwnerDocument(); |
| assert(theOwnerDocument != 0); |
| |
| if (length(xmlBaseIdent) == 0) |
| { |
| localXSLURLString = |
| URISupport::getURLStringFromString( |
| localXSLURLString, |
| m_xpathEnvSupport.findURIFromDoc(theOwnerDocument)); |
| } |
| else |
| { |
| localXSLURLString = |
| URISupport::getURLStringFromString( |
| localXSLURLString, |
| xmlBaseIdent); |
| } |
| |
| if(isRoot) |
| { |
| StylesheetRoot* const theLocalRoot = |
| constructionContext.create(localXSLURLString); |
| |
| stylesheet = theLocalRoot; |
| |
| m_stylesheetRoot = theLocalRoot; |
| } |
| else |
| { |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| stylesheet = new Stylesheet(*(StylesheetRoot*)m_stylesheetRoot, localXSLURLString, constructionContext); |
| #else |
| stylesheet = new Stylesheet(*const_cast<StylesheetRoot*>(m_stylesheetRoot), localXSLURLString, constructionContext); |
| #endif |
| |
| theGuard.reset(stylesheet); |
| } |
| |
| StylesheetHandler stylesheetProcessor(*stylesheet, constructionContext); |
| |
| typedef StylesheetConstructionContext::URLAutoPtrType URLAutoPtrType; |
| |
| URLAutoPtrType xslURL(constructionContext.getURLFromString(localXSLURLString)); |
| |
| XSLTInputSource inputSource(xslURL->getURLText()); |
| |
| m_parserLiaison.parseXMLStream(inputSource, stylesheetProcessor); |
| |
| stylesheet->postConstruction(constructionContext); |
| |
| theGuard.release(); |
| |
| displayDuration("Parsing and init of " + localXSLURLString, &localXSLURLString); |
| } |
| |
| return stylesheet; |
| } |
| |
| |
| //========================================================== |
| // SECTION: Stylesheet Tables |
| //========================================================== |
| |
| |
| double |
| XSLTEngineImpl::getXSLTVerSupported() |
| { |
| return s_XSLTVerSupported; |
| } |
| |
| |
| //========================================================== |
| // SECTION: XSL directive handling functions |
| //========================================================== |
| |
| |
| |
| int |
| XSLTEngineImpl::getXSLToken(const XalanNode& node) const |
| { |
| int tok = -2; |
| |
| if(XalanNode::ELEMENT_NODE != node.getNodeType()) return tok; |
| |
| const XalanDOMString& ns = node.getNamespaceURI(); |
| |
| if(equals(ns, s_XSLNameSpaceURL)) |
| { |
| const XalanDOMString& localName = |
| DOMServices::getLocalNameOfNode(node); |
| |
| const ElementKeysMapType::const_iterator j = |
| s_elementKeys.find(localName); |
| |
| if(j != s_elementKeys.end()) |
| { |
| tok = (*j).second; |
| } |
| } |
| else if(equals(ns, s_XSLT4JNameSpaceURL)) |
| { |
| const XalanDOMString& localName = |
| DOMServices::getLocalNameOfNode(node); |
| |
| const ElementKeysMapType::const_iterator j = |
| s_XSLT4JElementKeys.find(localName); |
| |
| if(j != s_XSLT4JElementKeys.end()) |
| { |
| tok = (*j).second; |
| } |
| } |
| |
| return tok; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::outputToResultTree( |
| StylesheetExecutionContext& executionContext, |
| const XObject& value) |
| { |
| const XObject::eObjectType type = value.getType(); |
| |
| switch(type) |
| { |
| case XObject::eTypeBoolean: |
| case XObject::eTypeNumber: |
| case XObject::eTypeString: |
| { |
| const XalanDOMString& s = value.str(); |
| |
| characters(toCharArray(s), 0, length(s)); |
| } |
| break; |
| |
| case XObject::eTypeNodeSet: |
| { |
| const NodeRefListBase& nl = value.nodeset(); |
| |
| const unsigned int nChildren = nl.getLength(); |
| |
| for(unsigned int i = 0; i < nChildren; i++) |
| { |
| XalanNode* pos = nl.item(i); |
| assert(pos != 0); |
| |
| XalanNode* const top = pos; |
| |
| while(0 != pos) |
| { |
| flushPending(); |
| |
| XalanNode::NodeType posNodeType = pos->getNodeType(); |
| |
| cloneToResultTree(*pos, posNodeType, false, false, true); |
| |
| XalanNode* nextNode = pos->getFirstChild(); |
| |
| while(0 == nextNode) |
| { |
| if(XalanNode::ELEMENT_NODE == posNodeType) |
| { |
| endElement(c_wstr(pos->getNodeName())); |
| } |
| |
| if(top == pos) |
| break; |
| |
| nextNode = pos->getNextSibling(); |
| |
| if(0 == nextNode) |
| { |
| pos = pos->getParentNode(); |
| assert(pos != 0); |
| |
| posNodeType = pos->getNodeType(); |
| |
| if(top == pos) |
| { |
| if(XalanNode::ELEMENT_NODE == posNodeType) |
| { |
| endElement(c_wstr(pos->getNodeName())); |
| } |
| |
| nextNode = 0; |
| break; |
| } |
| } |
| } |
| |
| pos = nextNode; |
| |
| if (pos != 0) |
| { |
| posNodeType = pos->getNodeType(); |
| } |
| } |
| } |
| } |
| break; |
| |
| case XObject::eTypeResultTreeFrag: |
| outputResultTreeFragment(executionContext, value); |
| break; |
| |
| case XObject::eTypeNull: |
| case XObject::eTypeUnknown: |
| case XObject::eUnknown: |
| default: |
| assert(0); |
| } |
| } |
| |
| |
| |
| const StylesheetRoot* |
| XSLTEngineImpl::getStylesheetRoot() const |
| { |
| return m_stylesheetRoot; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setStylesheetRoot(const StylesheetRoot* theStylesheet) |
| { |
| m_stylesheetRoot = theStylesheet; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setExecutionContext(StylesheetExecutionContext* theExecutionContext) |
| { |
| m_executionContext = theExecutionContext; |
| } |
| |
| |
| |
| //========================================================== |
| // SECTION: Diagnostic functions |
| //========================================================== |
| |
| unsigned long |
| XSLTEngineImpl::getTraceListeners() const |
| { |
| return m_traceListeners.size(); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::addTraceListener(TraceListener* tl) |
| { |
| if (tl != 0) |
| { |
| m_traceListeners.push_back(tl); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::removeTraceListener(TraceListener* tl) |
| { |
| #if !defined(XALAN_NO_NAMESPACES) |
| using std::remove; |
| #endif |
| |
| const TraceListenerVectorType::iterator i = |
| remove( |
| m_traceListeners.begin(), |
| m_traceListeners.end(), |
| tl); |
| |
| m_traceListeners.erase(i); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireGenerateEvent(const GenerateEvent& ge) |
| { |
| #if !defined(XALAN_NO_NAMESPACES) |
| using std::for_each; |
| #endif |
| |
| for_each( |
| m_traceListeners.begin(), |
| m_traceListeners.end(), |
| TraceListener::TraceListenerGenerateFunctor(ge)); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireSelectEvent(const SelectionEvent& se) |
| { |
| #if !defined(XALAN_NO_NAMESPACES) |
| using std::for_each; |
| #endif |
| |
| for_each( |
| m_traceListeners.begin(), |
| m_traceListeners.end(), |
| TraceListener::TraceListenerSelectFunctor(se)); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireTraceEvent(const TracerEvent& te) |
| { |
| #if !defined(XALAN_NO_NAMESPACES) |
| using std::for_each; |
| #endif |
| |
| for_each( |
| m_traceListeners.begin(), |
| m_traceListeners.end(), |
| TraceListener::TraceListenerTraceFunctor(te)); |
| } |
| |
| |
| |
| bool |
| XSLTEngineImpl::getTraceSelects() const |
| { |
| return m_traceSelects; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setTraceSelects(bool b) |
| { |
| m_traceSelects = b; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::message( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| problem(msg, ProblemListener::eMESSAGE, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::message( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const ElemTemplateElement* styleNode) const |
| { |
| problem(msg, ProblemListener::eMESSAGE, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::message( |
| const char* msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| message(TranscodeFromLocalCodePage(msg), sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::problem( |
| const XalanDOMString& msg, |
| ProblemListener::eClassification classification, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| const Locator* const locator = getLocatorFromStack(); |
| |
| const XalanDOMChar* id = 0; |
| |
| XalanDOMString uri; |
| |
| int lineNumber = -1; |
| int columnNumber = -1; |
| |
| if (locator != 0) |
| { |
| id = locator->getPublicId(); |
| |
| if (id == 0) |
| { |
| id = locator->getSystemId(); |
| } |
| |
| if (id != 0) |
| { |
| uri = id; |
| } |
| |
| lineNumber = locator->getLineNumber(); |
| columnNumber = locator->getColumnNumber(); |
| } |
| |
| if (m_problemListener != 0) |
| { |
| m_problemListener->problem( |
| ProblemListener::eXSLPROCESSOR, |
| classification, |
| sourceNode, |
| styleNode, |
| msg, |
| id, |
| lineNumber, |
| columnNumber); |
| } |
| |
| if (classification == ProblemListener::eERROR) |
| { |
| throw XSLTProcessorException(msg, uri, lineNumber, columnNumber); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::problem( |
| const XalanDOMString& msg, |
| ProblemListener::eClassification classification, |
| const XalanNode* sourceNode, |
| const ElemTemplateElement* styleNode) const |
| { |
| const XalanDOMChar* id = 0; |
| |
| XalanDOMString uri; |
| |
| int lineNumber = -1; |
| int columnNumber = -1; |
| |
| const Locator* locator = getLocatorFromStack(); |
| |
| if (locator == 0) |
| { |
| locator = styleNode->getLocator(); |
| } |
| |
| if (locator != 0) |
| { |
| id = locator->getPublicId(); |
| |
| if (id == 0) |
| { |
| id = locator->getSystemId(); |
| } |
| |
| if (id != 0) |
| { |
| uri = id; |
| } |
| |
| lineNumber = locator->getLineNumber(); |
| columnNumber = locator->getColumnNumber(); |
| } |
| else if (styleNode != 0) |
| { |
| lineNumber = styleNode->getLineNumber(); |
| columnNumber = styleNode->getColumnNumber(); |
| |
| uri = styleNode->getURI(); |
| } |
| |
| if (m_problemListener != 0) |
| { |
| m_problemListener->problem( |
| ProblemListener::eXSLPROCESSOR, |
| classification, |
| styleNode, |
| sourceNode, |
| msg, |
| id, |
| lineNumber, |
| columnNumber); |
| } |
| |
| if (classification == ProblemListener::eERROR) |
| { |
| throw XSLTProcessorException(msg, uri, lineNumber, columnNumber); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::warn( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| problem(msg, ProblemListener::eWARNING, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::warn( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const ElemTemplateElement* styleNode) const |
| { |
| problem(msg, ProblemListener::eWARNING, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::warn( |
| const char* msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| warn(TranscodeFromLocalCodePage(msg), sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::error( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| problem(msg, ProblemListener::eERROR, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::error( |
| const XalanDOMString& msg, |
| const XalanNode* sourceNode, |
| const ElemTemplateElement* styleNode) const |
| { |
| problem(msg, ProblemListener::eERROR, sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::error( |
| const char* msg, |
| const XalanNode* sourceNode, |
| const XalanNode* styleNode) const |
| { |
| error(TranscodeFromLocalCodePage(msg), sourceNode, styleNode); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::pushTime(const void* key) |
| { |
| if(0 != key) |
| { |
| m_durationsTable[key] = clock(); |
| } |
| } |
| |
| |
| |
| clock_t |
| XSLTEngineImpl::popDuration(const void* key) |
| { |
| clock_t clockTicksDuration = 0; |
| |
| if(0 != key) |
| { |
| const DurationsTableMapType::iterator i = |
| m_durationsTable.find(key); |
| |
| if (i != m_durationsTable.end()) |
| { |
| clockTicksDuration = clock() - (*i).second; |
| |
| m_durationsTable.erase(i); |
| } |
| } |
| |
| return clockTicksDuration; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::displayDuration( |
| const XalanDOMString& info, |
| const void* key) |
| { |
| if(0 != key) |
| { |
| const clock_t theDuration = popDuration(key); |
| |
| if(0 != m_diagnosticsPrintWriter) |
| { |
| const double millis = (double(theDuration) / CLOCKS_PER_SEC) * 1000.0L; |
| |
| XalanDOMString msg(info); |
| |
| msg += XALAN_STATIC_UCODE_STRING(" took "); |
| msg += DoubleToDOMString(millis); |
| msg += XALAN_STATIC_UCODE_STRING(" milliseconds"); |
| |
| m_diagnosticsPrintWriter->println(msg); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setDiagnosticsOutput(PrintWriter* pw) |
| { |
| m_diagnosticsPrintWriter = pw; |
| |
| m_problemListener->setPrintWriter(pw); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::diag(const XalanDOMString& s) const |
| { |
| if (0 != m_diagnosticsPrintWriter) |
| { |
| m_diagnosticsPrintWriter->println(s); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::diag(const char* s) const |
| { |
| diag(TranscodeFromLocalCodePage(s)); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setQuietConflictWarnings(bool b) |
| { |
| m_quietConflictWarnings = b; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setDocumentLocator(const Locator* const /* locator */) |
| { |
| // Do nothing for now |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::traceSelect( |
| const XalanElement& theTemplate, |
| const NodeRefListBase& nl) const |
| { |
| if (0 != m_diagnosticsPrintWriter) |
| { |
| XalanDOMString msg = theTemplate.getNodeName() + XalanDOMString(XALAN_STATIC_UCODE_STRING(": ")); |
| |
| XalanAttr* attr = theTemplate.getAttributeNode(Constants::ATTRNAME_SELECT); |
| |
| if(0 != attr) |
| { |
| msg += attr->getValue(); |
| msg += XALAN_STATIC_UCODE_STRING(", "); |
| msg += LongToDOMString(nl.getLength()); |
| msg += XALAN_STATIC_UCODE_STRING(" selected"); |
| } |
| else |
| { |
| msg += XALAN_STATIC_UCODE_STRING("*|text(), (default select), "); |
| msg += LongToDOMString(nl.getLength()); |
| msg += XALAN_STATIC_UCODE_STRING(" selected"); |
| } |
| |
| attr = theTemplate.getAttributeNode(Constants::ATTRNAME_MODE); |
| |
| if(0 != attr) |
| { |
| msg += XalanDOMString(XALAN_STATIC_UCODE_STRING(", mode = ")) + attr->getValue(); |
| } |
| |
| m_diagnosticsPrintWriter->println(msg); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::startDocument() |
| { |
| assert(getFormatterListener() != 0); |
| assert(m_executionContext != 0); |
| |
| if (getHasPendingStartDocument() == false) |
| { |
| m_resultNamespacesStack.pushContext(); |
| |
| setHasPendingStartDocument(true); |
| |
| setMustFlushPendingStartDocument(false); |
| } |
| else if (getMustFlushPendingStartDocument() == true) |
| { |
| getFormatterListener()->startDocument(); |
| |
| if(getTraceListeners() > 0) |
| { |
| const GenerateEvent ge(GenerateEvent::EVENTTYPE_STARTDOCUMENT); |
| |
| fireGenerateEvent(ge); |
| } |
| |
| // Reset this, but leave getMustFlushPendingStartDocument() alone, |
| // since it will still be needed. |
| setHasPendingStartDocument(false); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::endDocument() |
| { |
| assert(getFormatterListener() != 0); |
| assert(m_executionContext != 0); |
| |
| setMustFlushPendingStartDocument(true); |
| |
| flushPending(); |
| |
| getFormatterListener()->endDocument(); |
| |
| if(getTraceListeners() > 0) |
| { |
| const GenerateEvent ge(GenerateEvent::EVENTTYPE_ENDDOCUMENT); |
| |
| fireGenerateEvent(ge); |
| } |
| |
| m_resultNamespacesStack.popContext(); |
| |
| assert(m_resultNamespacesStack.size() == 0); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::addResultNamespaceDecl( |
| const XalanDOMString& prefix, |
| const XalanDOMString& namespaceVal) |
| { |
| m_resultNamespacesStack.addDeclaration(prefix, namespaceVal); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::addResultAttribute( |
| AttributeListImpl& attList, |
| const XalanDOMString& aname, |
| const XalanDOMString& value) |
| { |
| bool fExcludeAttribute = false; |
| |
| if (equals(aname, DOMServices::s_XMLNamespace)) |
| { |
| // OK, we're adding a default namespace declaration. So see if the length |
| // of the namespace is 0. If it's not, go ahead and add the declaration. |
| // If it's not, it means we're "turning off" the previous default |
| // declaration. |
| |
| const XalanDOMString* const currentDefaultNamespace = |
| getNamespaceForPrefix(s_emptyString); |
| |
| // Note that we use an empty string for the prefix, instead of "xmlns", since the |
| // prefix really is "". |
| if (length(value) != 0) |
| { |
| if (currentDefaultNamespace != 0 && |
| equals(*currentDefaultNamespace, value) == true) |
| { |
| fExcludeAttribute = true; |
| } |
| else |
| { |
| addResultNamespaceDecl(s_emptyString, value); |
| } |
| } |
| else |
| { |
| // OK, we're turning of the previous default namespace declaration. |
| // Check to see if there is one, and if there isn't, don't add |
| // the namespace declaration _and_ don't add the attribute. |
| if (currentDefaultNamespace != 0 && length(*currentDefaultNamespace) != 0) |
| { |
| addResultNamespaceDecl(s_emptyString, value); |
| } |
| else |
| { |
| fExcludeAttribute = true; |
| } |
| } |
| } |
| else if (startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator) == true) |
| { |
| assert(m_executionContext != 0); |
| |
| StylesheetExecutionContext::GetAndReleaseCachedString prefixGuard(*m_executionContext); |
| |
| XalanDOMString& prefix = prefixGuard.get(); |
| |
| prefix = substring(aname, DOMServices::s_XMLNamespaceWithSeparatorLength); |
| |
| addResultNamespaceDecl(prefix, value); |
| } |
| |
| if (fExcludeAttribute == false) |
| { |
| attList.addAttribute( |
| c_wstr(aname), |
| c_wstr(Constants::ATTRTYPE_CDATA), |
| c_wstr(value)); |
| } |
| } |
| |
| |
| |
| bool |
| XSLTEngineImpl::pendingAttributesHasDefaultNS() const |
| { |
| const AttributeListImpl& thePendingAttributes = |
| getPendingAttributes(); |
| |
| const unsigned int n = thePendingAttributes.getLength(); |
| |
| for(unsigned int i = 0; i < n; i++) |
| { |
| if(equals(thePendingAttributes.getName(i), |
| DOMServices::s_XMLNamespace) == true) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::flushPending() |
| { |
| if(getHasPendingStartDocument() == true && 0 != length(getPendingElementName())) |
| { |
| assert(getFormatterListener() != 0); |
| assert(m_executionContext != 0); |
| |
| if (m_stylesheetRoot->isOutputMethodSet() == false) |
| { |
| if (equalsIgnoreCaseASCII(getPendingElementName(), |
| Constants::ELEMNAME_HTML_STRING) == true && |
| pendingAttributesHasDefaultNS() == false) |
| { |
| if (getFormatterListener()->getOutputFormat() == FormatterListener::OUTPUT_METHOD_XML) |
| { |
| // Yuck!!! Ugly hack to switch to HTML on-the-fly. |
| FormatterToXML* const theFormatter = |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (FormatterToXML*)getFormatterListener(); |
| #else |
| static_cast<FormatterToXML*>(getFormatterListener()); |
| #endif |
| |
| setFormatterListenerImpl( |
| m_executionContext->createFormatterToHTML( |
| *theFormatter->getWriter(), |
| theFormatter->getEncoding(), |
| theFormatter->getMediaType(), |
| theFormatter->getDoctypeSystem(), |
| theFormatter->getDoctypePublic(), |
| true, // indent |
| theFormatter->getIndent() > 0 ? theFormatter->getIndent() : |
| StylesheetExecutionContext::eDefaultHTMLIndentAmount)); |
| } |
| } |
| } |
| } |
| |
| XalanDOMString& thePendingElementName = getPendingElementNameImpl(); |
| |
| if(getHasPendingStartDocument() == true && getMustFlushPendingStartDocument() == true) |
| { |
| startDocument(); |
| } |
| |
| if(0 != length(thePendingElementName) && getMustFlushPendingStartDocument() == true) |
| { |
| assert(getFormatterListener() != 0); |
| assert(m_executionContext != 0); |
| |
| m_cdataStack.push_back(isCDataResultElem(thePendingElementName) ? true : false); |
| |
| AttributeListImpl& thePendingAttributes = |
| getPendingAttributesImpl(); |
| |
| getFormatterListener()->startElement(c_wstr(thePendingElementName), thePendingAttributes); |
| |
| if(getTraceListeners() > 0) |
| { |
| const GenerateEvent ge( |
| GenerateEvent::EVENTTYPE_STARTELEMENT, |
| thePendingElementName, |
| &thePendingAttributes); |
| |
| fireGenerateEvent(ge); |
| } |
| |
| thePendingAttributes.clear(); |
| |
| clear(thePendingElementName); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::startElement(const XMLCh* const name) |
| { |
| assert(getFormatterListener() != 0); |
| assert(name != 0); |
| |
| flushPending(); |
| |
| m_resultNamespacesStack.pushContext(); |
| |
| setPendingElementName(name); |
| |
| setMustFlushPendingStartDocument(true); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::startElement( |
| const XMLCh* const name, |
| AttributeList& atts) |
| { |
| assert(getFormatterListener() != 0); |
| assert(name != 0); |
| |
| flushPending(); |
| |
| const unsigned int nAtts = atts.getLength(); |
| |
| assert(m_outputContextStack.size() > 0); |
| |
| AttributeListImpl& thePendingAttributes = |
| getPendingAttributesImpl(); |
| |
| thePendingAttributes.clear(); |
| |
| for(unsigned int i = 0; i < nAtts; i++) |
| { |
| thePendingAttributes.addAttribute( |
| atts.getName(i), |
| atts.getType(i), |
| atts.getValue(i)); |
| } |
| |
| m_resultNamespacesStack.pushContext(); |
| |
| setPendingElementName(name); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::endElement(const XMLCh* const name) |
| { |
| assert(getFormatterListener() != 0); |
| assert(name != 0); |
| |
| flushPending(); |
| |
| getFormatterListener()->endElement(name); |
| |
| if(getTraceListeners() > 0) |
| { |
| const GenerateEvent ge(GenerateEvent::EVENTTYPE_ENDELEMENT, name); |
| |
| fireGenerateEvent(ge); |
| } |
| |
| m_resultNamespacesStack.popContext(); |
| |
| if(m_stylesheetRoot->hasCDATASectionElements() == true) |
| { |
| m_cdataStack.pop_back(); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::characters( |
| const XMLCh* const ch, |
| const unsigned int length) |
| { |
| characters(ch, |
| 0, |
| length); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::characters( |
| const XMLCh* const ch, |
| const unsigned int start, |
| const unsigned int length) |
| { |
| assert(getFormatterListener() != 0); |
| assert(ch != 0); |
| |
| doFlushPending(); |
| |
| if(generateCDATASection() == true) |
| { |
| getFormatterListener()->cdata(ch + start, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(ch, start, length, true); |
| } |
| } |
| else |
| { |
| getFormatterListener()->characters(ch + start, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(ch, start, length, false); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::characters(const XalanNode& node) |
| { |
| assert(getFormatterListener() != 0); |
| |
| doFlushPending(); |
| |
| if(generateCDATASection() == true) |
| { |
| DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::cdata); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(node, true); |
| } |
| } |
| else |
| { |
| DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::characters); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(node, false); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::characters(const XObjectPtr& xobject) |
| { |
| assert(getFormatterListener() != 0); |
| assert(xobject.null() == false); |
| |
| doFlushPending(); |
| |
| if(generateCDATASection() == true) |
| { |
| xobject->str(*getFormatterListener(), &FormatterListener::cdata); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(xobject, true); |
| } |
| } |
| else |
| { |
| xobject->str(*getFormatterListener(), &FormatterListener::characters); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(xobject, false); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::charactersRaw( |
| const XMLCh* const ch, |
| const unsigned int start, |
| const unsigned int length) |
| { |
| assert(ch != 0); |
| |
| doFlushPending(); |
| |
| getFormatterListener()->charactersRaw(ch, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(ch, start, length, false); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::charactersRaw(const XalanNode& node) |
| { |
| doFlushPending(); |
| |
| DOMServices::getNodeData(node, *getFormatterListener(), &FormatterListener::charactersRaw); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(node, false); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::charactersRaw(const XObjectPtr& xobject) |
| { |
| doFlushPending(); |
| |
| xobject->str(*getFormatterListener(), &FormatterListener::charactersRaw); |
| |
| if(getTraceListeners() > 0) |
| { |
| fireCharacterGenerateEvent(xobject, false); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::resetDocument() |
| { |
| assert(getFormatterListener() != 0); |
| |
| flushPending(); |
| |
| getFormatterListener()->resetDocument(); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::ignorableWhitespace( |
| const XMLCh* const ch, |
| const unsigned int length) |
| { |
| assert(getFormatterListener() != 0); |
| assert(ch != 0); |
| |
| doFlushPending(); |
| |
| getFormatterListener()->ignorableWhitespace(ch, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge(GenerateEvent::EVENTTYPE_IGNORABLEWHITESPACE, |
| ch, 0, length); |
| |
| fireGenerateEvent(ge); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::processingInstruction( |
| const XMLCh* const target, |
| const XMLCh* const data) |
| { |
| assert(getFormatterListener() != 0); |
| assert(target != 0); |
| assert(data != 0); |
| |
| doFlushPending(); |
| |
| getFormatterListener()->processingInstruction(target, data); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge( |
| GenerateEvent::EVENTTYPE_PI, |
| target, |
| data); |
| |
| fireGenerateEvent(ge); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::comment(const XMLCh* const data) |
| { |
| assert(getFormatterListener() != 0); |
| assert(data != 0); |
| |
| doFlushPending(); |
| |
| getFormatterListener()->comment(data); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge(GenerateEvent::EVENTTYPE_COMMENT, |
| data); |
| fireGenerateEvent(ge); |
| } |
| } |
| |
| |
| void |
| XSLTEngineImpl::entityReference(const XMLCh* const name) |
| { |
| assert(getFormatterListener() != 0); |
| assert(name != 0); |
| |
| doFlushPending(); |
| |
| getFormatterListener()->entityReference(name); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge(GenerateEvent::EVENTTYPE_ENTITYREF, |
| name); |
| |
| fireGenerateEvent(ge); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::cdata( |
| const XMLCh* const ch, |
| const unsigned int start, |
| const unsigned int length) |
| { |
| assert(getFormatterListener() != 0); |
| assert(ch != 0); |
| |
| setMustFlushPendingStartDocument(true); |
| |
| flushPending(); |
| |
| if(m_stylesheetRoot->hasCDATASectionElements() == true && |
| 0 != m_cdataStack.size()) |
| { |
| getFormatterListener()->cdata(ch, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge(GenerateEvent::EVENTTYPE_CDATA, ch, start, |
| length); |
| |
| fireGenerateEvent(ge); |
| } |
| } |
| else |
| { |
| getFormatterListener()->characters(ch, length); |
| |
| if(getTraceListeners() > 0) |
| { |
| GenerateEvent ge(GenerateEvent::EVENTTYPE_CHARACTERS, ch, |
| start, length); |
| |
| fireGenerateEvent(ge); |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::cloneToResultTree( |
| XalanNode& node, |
| XalanNode::NodeType nodeType, |
| bool isLiteral, |
| bool overrideStrip, |
| bool shouldCloneAttributes) |
| { |
| assert(nodeType == node.getNodeType()); |
| |
| switch(nodeType) |
| { |
| case XalanNode::TEXT_NODE: |
| { |
| bool stripWhiteSpace = false; |
| |
| // If stripWhiteSpace is false, then take this as an override and |
| // just preserve the space, otherwise use the XSL whitespace rules. |
| if(!overrideStrip) |
| { |
| stripWhiteSpace = isLiteral ? true : false; |
| // was: stripWhiteSpace = isLiteral ? true : shouldStripSourceNode(node); |
| } |
| |
| const XalanText& tx = |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (const XalanText&)node; |
| #else |
| static_cast<const XalanText&>(node); |
| #endif |
| |
| const bool isIgnorableWhitespace = tx.isIgnorableWhitespace(); |
| |
| if(stripWhiteSpace == false || isIgnorableWhitespace == false) |
| { |
| assert(tx.getParentNode() == 0 || |
| tx.getParentNode()->getNodeType() != XalanNode::DOCUMENT_NODE); |
| |
| const XalanDOMString& data = tx.getData(); |
| |
| if(0 != length(data)) |
| { |
| if(isIgnorableWhitespace == true) |
| { |
| ignorableWhitespace(toCharArray(data), length(data)); |
| } |
| else |
| { |
| characters(toCharArray(data), 0, length(data)); |
| } |
| } |
| } |
| } |
| break; |
| |
| case XalanNode::ELEMENT_NODE: |
| startElement(c_wstr(node.getNodeName())); |
| |
| if(shouldCloneAttributes == true) |
| { |
| copyAttributesToAttList( |
| m_stylesheetRoot, |
| node, |
| getPendingAttributesImpl()); |
| |
| copyNamespaceAttributes(node); |
| } |
| break; |
| |
| case XalanNode::CDATA_SECTION_NODE: |
| { |
| const XalanDOMString& data = node.getNodeValue(); |
| |
| cdata(toCharArray(data), 0, length(data)); |
| } |
| break; |
| |
| case XalanNode::ATTRIBUTE_NODE: |
| addResultAttribute( |
| getPendingAttributesImpl(), |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| DOMServices::getNameOfNode((const XalanAttr&)node), |
| #else |
| DOMServices::getNameOfNode(static_cast<const XalanAttr&>(node)), |
| #endif |
| node.getNodeValue()); |
| break; |
| |
| case XalanNode::COMMENT_NODE: |
| comment(c_wstr(node.getNodeValue())); |
| break; |
| |
| case XalanNode::DOCUMENT_FRAGMENT_NODE: |
| error("No clone of a document fragment!"); |
| break; |
| |
| case XalanNode::ENTITY_REFERENCE_NODE: |
| entityReference(c_wstr(node.getNodeName())); |
| break; |
| |
| case XalanNode::PROCESSING_INSTRUCTION_NODE: |
| processingInstruction( |
| c_wstr(node.getNodeName()), |
| c_wstr(node.getNodeValue())); |
| break; |
| |
| // Can't really do this, but we won't throw an error so that copy-of will |
| // work |
| case XalanNode::DOCUMENT_NODE: |
| case XalanNode::DOCUMENT_TYPE_NODE: |
| break; |
| |
| default: |
| error("Cannot create item in result tree: " + node.getNodeName()); |
| break; |
| |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::outputResultTreeFragment( |
| StylesheetExecutionContext& executionContext, |
| const XObject& theTree) |
| { |
| const ResultTreeFragBase& docFrag = theTree.rtree(executionContext); |
| |
| const XalanNodeList* const nl = docFrag.getChildNodes(); |
| assert(nl != 0); |
| |
| const unsigned int nChildren = nl->getLength(); |
| |
| for(unsigned int i = 0; i < nChildren; i++) |
| { |
| XalanNode* pos = nl->item(i); |
| assert(pos != 0); |
| |
| XalanNode::NodeType posNodeType = pos->getNodeType(); |
| |
| XalanNode* const top = pos; |
| |
| while(0 != pos) |
| { |
| flushPending(); |
| |
| cloneToResultTree(*pos, posNodeType, false, false, true); |
| |
| XalanNode* nextNode = pos->getFirstChild(); |
| |
| while(0 == nextNode) |
| { |
| if(XalanNode::ELEMENT_NODE == posNodeType) |
| { |
| endElement(c_wstr(pos->getNodeName())); |
| } |
| |
| if(top == pos) |
| break; |
| |
| nextNode = pos->getNextSibling(); |
| |
| if(0 == nextNode) |
| { |
| pos = pos->getParentNode(); |
| |
| if(0 == pos) |
| { |
| nextNode = 0; |
| |
| break; |
| } |
| else |
| { |
| assert(0 != pos); |
| |
| posNodeType = pos->getNodeType(); |
| |
| if(top == pos) |
| { |
| if(XalanNode::ELEMENT_NODE == posNodeType) |
| { |
| endElement(c_wstr(pos->getNodeName())); |
| } |
| |
| nextNode = 0; |
| |
| break; |
| } |
| } |
| } |
| } |
| |
| pos = nextNode; |
| |
| if (pos != 0) |
| { |
| posNodeType = pos->getNodeType(); |
| } |
| } |
| } |
| } |
| |
| |
| |
| bool |
| XSLTEngineImpl::isCDataResultElem(const XalanDOMString& elementName) const |
| { |
| assert(m_executionContext != 0); |
| |
| if(m_stylesheetRoot->hasCDATASectionElements() == false) |
| { |
| return false; |
| } |
| else |
| { |
| bool fResult = false; |
| |
| const unsigned int indexOfNSSep = indexOf(elementName, XalanUnicode::charColon); |
| |
| if(indexOfNSSep == length(elementName)) |
| { |
| fResult = m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(s_emptyString, elementName)); |
| } |
| else |
| { |
| typedef StylesheetExecutionContext::GetAndReleaseCachedString GetAndReleaseCachedString; |
| |
| GetAndReleaseCachedString elemLocalNameGuard(*m_executionContext); |
| GetAndReleaseCachedString prefixGuard(*m_executionContext); |
| |
| XalanDOMString& elemLocalName = elemLocalNameGuard.get(); |
| XalanDOMString& prefix = prefixGuard.get(); |
| |
| substring(elementName, prefix, 0, indexOfNSSep); |
| substring(elementName, elemLocalName, indexOfNSSep + 1); |
| |
| if(equals(prefix, DOMServices::s_XMLString)) |
| { |
| fResult = |
| m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(DOMServices::s_XMLNamespaceURI, elementName)); |
| } |
| else |
| { |
| const XalanDOMString* const elemNS = |
| getResultNamespaceForPrefix(prefix); |
| |
| if(elemNS == 0) |
| { |
| error("Prefix must resolve to a namespace: " + prefix); |
| } |
| else |
| { |
| fResult = |
| m_stylesheetRoot->isCDATASectionElementName(XalanQNameByReference(*elemNS, elementName)); |
| } |
| } |
| } |
| |
| return fResult; |
| } |
| } |
| |
| |
| |
| const XalanDOMString* |
| XSLTEngineImpl::getResultNamespaceForPrefix(const XalanDOMString& prefix) const |
| { |
| return m_resultNamespacesStack.getNamespaceForPrefix(prefix); |
| } |
| |
| |
| |
| const XalanDOMString* |
| XSLTEngineImpl::getResultPrefixForNamespace(const XalanDOMString& theNamespace) const |
| { |
| return m_resultNamespacesStack.getPrefixForNamespace(theNamespace); |
| } |
| |
| |
| |
| inline bool |
| isPrefixUsed( |
| const XalanDOMString& thePrefix, |
| unsigned int thePrefixLength, |
| const XalanDOMChar* theName, |
| unsigned int theNameLength) |
| { |
| assert(thePrefixLength != 0); |
| |
| // The name must be greater than the length of the prefix + 1, since |
| // there must be a ':' to separate the prefix from the local part... |
| if (theNameLength <= thePrefixLength + 1) |
| { |
| return false; |
| } |
| else |
| { |
| assert(theName != 0); |
| |
| const unsigned int theIndex = indexOf( |
| theName, |
| XalanUnicode::charColon); |
| |
| // OK, if the index of the ':' is the same as the length of the prefix, |
| // and theElementName starts with thePrefix, then the prefix is in use. |
| if (theIndex == thePrefixLength && |
| startsWith(theName, thePrefix) == true) |
| { |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| } |
| |
| |
| |
| inline bool |
| isPrefixUsed( |
| const XalanDOMString& thePrefix, |
| unsigned int thePrefixLength, |
| const XalanDOMString& theName) |
| { |
| return isPrefixUsed(thePrefix, thePrefixLength, c_wstr(theName), length(theName)); |
| } |
| |
| |
| |
| inline bool |
| isPrefixUsedOrDeclared( |
| const XalanDOMString& thePrefix, |
| unsigned int thePrefixLength, |
| const XalanDOMChar* theName, |
| unsigned int theNameLength) |
| { |
| if (isPrefixUsed(thePrefix, thePrefixLength, theName, theNameLength) == true) |
| { |
| return true; |
| } |
| else |
| { |
| const unsigned int theDeclarationLength = |
| thePrefixLength + DOMServices::s_XMLNamespaceWithSeparatorLength; |
| |
| // If this is a namespace declaration for this prefix, then all of |
| // these conditions must be true... |
| if (theDeclarationLength == theNameLength && |
| startsWith(theName, DOMServices::s_XMLNamespaceWithSeparator) == true && |
| endsWith(theName, c_wstr(thePrefix)) == true) |
| { |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| } |
| |
| |
| |
| inline bool |
| isPendingAttributePrefix( |
| const AttributeList& thePendingAttributes, |
| const XalanDOMString& thePrefix, |
| unsigned int thePrefixLength) |
| { |
| const unsigned int thePendingAttributesCount = |
| thePendingAttributes.getLength(); |
| |
| if (thePendingAttributesCount == 0) |
| { |
| // No attributes, no problem... |
| return false; |
| } |
| else |
| { |
| bool fResult = false; |
| |
| // Check each attribute... |
| for (unsigned int i = 0; i < thePendingAttributesCount; ++i) |
| { |
| const XalanDOMChar* const thePendingAttributeName = |
| thePendingAttributes.getName(i); |
| assert(thePendingAttributeName != 0); |
| |
| if (isPrefixUsedOrDeclared( |
| thePrefix, |
| thePrefixLength, |
| thePendingAttributeName, |
| length(thePendingAttributeName)) == true) |
| { |
| fResult = true; |
| |
| break; |
| } |
| } |
| |
| return fResult; |
| } |
| } |
| |
| |
| |
| bool |
| XSLTEngineImpl::isPendingResultPrefix(const XalanDOMString& thePrefix) const |
| { |
| const unsigned int thePrefixLength = length(thePrefix); |
| assert(thePrefixLength > 0); |
| |
| // The element name must be greater than the length of the prefix + 1, since |
| // there must be a ':' to separate the prefix from the local part... |
| if (isPrefixUsed(thePrefix, thePrefixLength, getPendingElementName()) == true) |
| { |
| return true; |
| } |
| else |
| { |
| // The element is not using the prefix, so check the |
| // pending attributes... |
| return isPendingAttributePrefix( |
| getPendingAttributes(), |
| thePrefix, |
| thePrefixLength); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::addResultNamespace( |
| const XalanNode& theNode, |
| AttributeListImpl& thePendingAttributes, |
| bool fOnlyIfPrefixNotPresent) |
| { |
| assert(theNode.getNodeType() == XalanNode::ATTRIBUTE_NODE); |
| |
| const XalanDOMString& aname = theNode.getNodeName(); |
| |
| const bool isPrefix = startsWith(aname, DOMServices::s_XMLNamespaceWithSeparator); |
| |
| const XalanDOMString prefix = isPrefix == true ? |
| substring(aname, DOMServices::s_XMLNamespaceWithSeparatorLength) : XalanDOMString(); |
| |
| if (equals(aname, DOMServices::s_XMLNamespace) || isPrefix) |
| { |
| if (fOnlyIfPrefixNotPresent == true) |
| { |
| if (m_resultNamespacesStack.prefixIsPresentLocal(prefix) == false) |
| { |
| const XalanDOMString* const desturi = getResultNamespaceForPrefix(prefix); |
| const XalanDOMString& srcURI = theNode.getNodeValue(); |
| |
| if(desturi == 0 || equals(srcURI, *desturi) == false) |
| { |
| addResultAttribute(thePendingAttributes, aname, srcURI); |
| } |
| } |
| } |
| else |
| { |
| const XalanDOMString* const desturi = getResultNamespaceForPrefix(prefix); |
| const XalanDOMString& srcURI = theNode.getNodeValue(); |
| |
| if(desturi == 0 || equals(srcURI, *desturi) == false) |
| { |
| addResultAttribute(thePendingAttributes, aname, srcURI); |
| } |
| } |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::copyNamespaceAttributes(const XalanNode& src) |
| { |
| const XalanNode* parent = &src; |
| |
| while (parent != 0 && |
| parent->getNodeType() == XalanNode::ELEMENT_NODE) |
| { |
| const XalanNamedNodeMap* const nnm = |
| parent->getAttributes(); |
| assert(nnm != 0); |
| |
| const unsigned int nAttrs = nnm->getLength(); |
| |
| assert(m_outputContextStack.size() > 0); |
| |
| AttributeListImpl& thePendingAttributes = |
| getPendingAttributesImpl(); |
| |
| for (unsigned int i = 0; i < nAttrs; i++) |
| { |
| const XalanNode* const attr = nnm->item(i); |
| assert(attr != 0); |
| |
| addResultNamespace(*attr, thePendingAttributes, true); |
| } |
| |
| parent = parent->getParentNode(); |
| } |
| } |
| |
| |
| |
| const XObjectPtr |
| XSLTEngineImpl::evalXPathStr( |
| const XalanDOMString& str, |
| XPathExecutionContext& executionContext) |
| { |
| assert(executionContext.getPrefixResolver() != 0); |
| |
| XPath* const theXPath = m_xpathFactory.create(); |
| |
| XPathGuard theGuard(m_xpathFactory, |
| theXPath); |
| |
| m_xpathProcessor->initXPath(*theXPath, |
| str, |
| *executionContext.getPrefixResolver(), |
| getLocatorFromStack()); |
| |
| return theXPath->execute(executionContext.getCurrentNode(), |
| *executionContext.getPrefixResolver(), |
| executionContext); |
| } |
| |
| |
| |
| const XObjectPtr |
| XSLTEngineImpl::evalXPathStr( |
| const XalanDOMString& str, |
| XalanNode* contextNode, |
| const PrefixResolver& prefixResolver, |
| XPathExecutionContext& executionContext) |
| { |
| XPath* const theXPath = m_xpathFactory.create(); |
| |
| XPathGuard theGuard(m_xpathFactory, |
| theXPath); |
| |
| m_xpathProcessor->initXPath(*theXPath, |
| str, |
| prefixResolver, |
| getLocatorFromStack()); |
| |
| return theXPath->execute(contextNode, prefixResolver, executionContext); |
| } |
| |
| |
| |
| const XObjectPtr |
| XSLTEngineImpl::evalXPathStr( |
| const XalanDOMString& str, |
| XalanNode* contextNode, |
| const XalanElement& prefixResolver, |
| XPathExecutionContext& executionContext) |
| { |
| ElementPrefixResolverProxy theProxy(&prefixResolver, |
| m_xpathEnvSupport, |
| m_domSupport); |
| |
| return evalXPathStr(str, contextNode, theProxy, executionContext); |
| } |
| |
| |
| |
| |
| /** |
| * Create and initialize an xpath and return it. |
| */ |
| const XPath* |
| XSLTEngineImpl::createMatchPattern( |
| const XalanDOMString& str, |
| const PrefixResolver& resolver) |
| { |
| XPath* const xpath = m_xpathFactory.create(); |
| |
| m_xpathProcessor->initMatchPattern(*xpath, str, resolver, getLocatorFromStack()); |
| |
| return xpath; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::returnXPath(const XPath* xpath) |
| { |
| m_xpathFactory.returnObject(xpath); |
| } |
| |
| |
| |
| inline void |
| XSLTEngineImpl::copyAttributeToTarget( |
| const XalanDOMString& attrName, |
| const XalanDOMString& attrValue, |
| AttributeListImpl& attrList) |
| { |
| // TODO: Find out about empty attribute template expression handling. |
| if(0 != length(attrValue)) |
| { |
| addResultAttribute(attrList, attrName, attrValue); |
| } |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::copyAttributesToAttList( |
| const Stylesheet* stylesheetTree, |
| const XalanNode& node, |
| AttributeListImpl& attList) |
| { |
| assert(m_stylesheetRoot != 0); |
| assert(stylesheetTree != 0); |
| |
| const XalanNamedNodeMap* const attributes = |
| node.getAttributes(); |
| |
| if (attributes != 0) |
| { |
| const unsigned int nAttributes = attributes->getLength(); |
| |
| for(unsigned int i = 0; i < nAttributes; ++i) |
| { |
| const XalanNode* const attr = attributes->item(i); |
| assert(attr != 0); |
| |
| copyAttributeToTarget( |
| attr->getNodeName(), |
| attr->getNodeValue(), |
| attList); |
| } |
| } |
| } |
| |
| |
| |
| bool |
| XSLTEngineImpl::shouldStripSourceNode( |
| XPathExecutionContext& executionContext, |
| const XalanNode& textNode) const |
| { |
| if (m_stylesheetRoot == 0) |
| { |
| return false; |
| } |
| else |
| { |
| bool strip = false; // return value |
| |
| if((m_stylesheetRoot->getWhitespacePreservingElements().size() > 0 || |
| m_stylesheetRoot->getWhitespaceStrippingElements().size() > 0)) |
| { |
| const XalanNode::NodeType type = textNode.getNodeType(); |
| |
| if(XalanNode::TEXT_NODE == type || XalanNode::CDATA_SECTION_NODE == type) |
| { |
| const XalanText& theTextNode = |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (const XalanText&)textNode; |
| #else |
| static_cast<const XalanText&>(textNode); |
| #endif |
| |
| if(!theTextNode.isIgnorableWhitespace()) |
| { |
| const XalanDOMString& data = theTextNode.getData(); |
| |
| if(0 == length(data)) |
| { |
| return true; |
| } |
| else if(!isXMLWhitespace(data)) |
| { |
| return false; |
| } |
| } |
| |
| XalanNode* parent = DOMServices::getParentOfNode(textNode); |
| |
| while(0 != parent) |
| { |
| if(parent->getNodeType() == XalanNode::ELEMENT_NODE) |
| { |
| const XalanElement* const parentElem = |
| #if defined(XALAN_OLD_STYLE_CASTS) |
| (const XalanElement*)parent; |
| #else |
| static_cast<const XalanElement*>(parent); |
| #endif |
| |
| XPath::eMatchScore highPreserveScore = XPath::eMatchScoreNone; |
| XPath::eMatchScore highStripScore = XPath::eMatchScoreNone; |
| |
| ElementPrefixResolverProxy theProxy(parentElem, m_xpathEnvSupport, m_domSupport); |
| |
| { |
| // $$$ ToDo: All of this should be moved into a member of |
| // Stylesheet, so as not to expose these two data members... |
| typedef Stylesheet::XPathVectorType XPathVectorType; |
| |
| const XPathVectorType& theElements = |
| m_stylesheetRoot->getWhitespacePreservingElements(); |
| |
| const XPathVectorType::size_type nTests = |
| theElements.size(); |
| |
| for(XPathVectorType::size_type i = 0; i < nTests; i++) |
| { |
| const XPath* const matchPat = theElements[i]; |
| assert(matchPat != 0); |
| |
| const XPath::eMatchScore score = matchPat->getMatchScore(parent, theProxy, executionContext); |
| |
| if(score > highPreserveScore) |
| highPreserveScore = score; |
| } |
| } |
| |
| { |
| typedef Stylesheet::XPathVectorType XPathVectorType; |
| |
| const XPathVectorType& theElements = |
| m_stylesheetRoot->getWhitespaceStrippingElements(); |
| |
| const XPathVectorType::size_type nTests = |
| theElements.size(); |
| |
| for(XPathVectorType::size_type i = 0; i < nTests; i++) |
| { |
| const XPath* const matchPat = |
| theElements[i]; |
| assert(matchPat != 0); |
| |
| const XPath::eMatchScore score = matchPat->getMatchScore(parent, theProxy, executionContext); |
| |
| if(score > highStripScore) |
| highStripScore = score; |
| } |
| } |
| |
| if(highPreserveScore > XPath::eMatchScoreNone || |
| highStripScore > XPath::eMatchScoreNone) |
| { |
| if(highPreserveScore > highStripScore) |
| { |
| strip = false; |
| } |
| else if(highStripScore > highPreserveScore) |
| { |
| strip = true; |
| } |
| else |
| { |
| warn("Match conflict between xsl:strip-space and xsl:preserve-space"); |
| } |
| break; |
| } |
| } |
| |
| parent = parent->getParentNode(); |
| } |
| } |
| } |
| |
| return strip; |
| } |
| } |
| |
| |
| |
| XMLParserLiaison& |
| XSLTEngineImpl::getXMLParserLiaison() const |
| { |
| return m_parserLiaison; |
| } |
| |
| |
| |
| const XalanDOMString |
| XSLTEngineImpl::getUniqueNamespaceValue() |
| { |
| XalanDOMString theResult; |
| |
| getUniqueNamespaceValue(theResult); |
| |
| return theResult; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::getUniqueNamespaceValue(XalanDOMString& theValue) |
| { |
| append(theValue, s_uniqueNamespacePrefix); |
| |
| UnsignedLongToDOMString(m_uniqueNSValue++, theValue); |
| } |
| |
| |
| |
| XalanDocument* |
| XSLTEngineImpl::getDOMFactory() const |
| { |
| if(m_domResultTreeFactory == 0) |
| { |
| #if defined(XALAN_NO_MUTABLE) |
| ((XSLTEngineImpl*)this)->m_domResultTreeFactory = m_parserLiaison.createDOMFactory(); |
| #else |
| m_domResultTreeFactory = m_parserLiaison.createDOMFactory(); |
| #endif |
| } |
| |
| return m_domResultTreeFactory; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setStylesheetParam( |
| const XalanDOMString& theName, |
| const XalanDOMString& expression) |
| { |
| const XalanQNameByValue qname(theName, 0, m_xpathEnvSupport, m_domSupport); |
| |
| m_topLevelParams.push_back(ParamVectorType::value_type(qname, expression)); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setStylesheetParam( |
| const XalanDOMString& theName, |
| XObjectPtr theValue) |
| { |
| const XalanQNameByValue qname(theName, 0, m_xpathEnvSupport, m_domSupport); |
| |
| m_topLevelParams.push_back(ParamVectorType::value_type(qname, theValue)); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::resolveTopLevelParams(StylesheetExecutionContext& executionContext) |
| { |
| executionContext.pushTopLevelVariables(m_topLevelParams); |
| } |
| |
| |
| |
| FormatterListener* |
| XSLTEngineImpl::getFormatterListener() const |
| { |
| return getFormatterListenerImpl(); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::setFormatterListener(FormatterListener* flistener) |
| { |
| if (getHasPendingStartDocument() == true && getFormatterListener() != 0) |
| { |
| setMustFlushPendingStartDocument(true); |
| |
| flushPending(); |
| } |
| |
| setFormatterListenerImpl(flistener); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireCharacterGenerateEvent( |
| const XalanNode& theNode, |
| bool isCDATA) |
| { |
| fireCharacterGenerateEvent(DOMServices::getNodeData(theNode), isCDATA); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireCharacterGenerateEvent( |
| const XObjectPtr& theXObject, |
| bool isCDATA) |
| { |
| fireCharacterGenerateEvent(theXObject->str(), isCDATA); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireCharacterGenerateEvent( |
| const XalanDOMString& theString, |
| bool isCDATA) |
| { |
| fireCharacterGenerateEvent(c_wstr(theString), 0, length(theString), isCDATA); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::fireCharacterGenerateEvent( |
| const XMLCh* ch, |
| unsigned int start, |
| unsigned int length, |
| bool isCDATA) |
| { |
| const GenerateEvent ge( |
| isCDATA == true ? GenerateEvent::EVENTTYPE_CDATA : GenerateEvent::EVENTTYPE_CHARACTERS, |
| ch, |
| start, |
| length); |
| |
| fireGenerateEvent(ge); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::installFunctions() |
| { |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("current")), FunctionCurrent()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("document")), FunctionDocument()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("element-available")), FunctionElementAvailable()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("function-available")), FunctionFunctionAvailable()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("format-number")), FunctionFormatNumber()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("generate-id")), FunctionGenerateID()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("key")), FunctionKey()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("system-property")), FunctionSystemProperty()); |
| XPath::installFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("unparsed-entity-uri")), FunctionUnparsedEntityURI()); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::uninstallFunctions() |
| { |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("current"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("document"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("element-available"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("function-available"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("format-number"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("generate-id"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("key"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("system-property"))); |
| XPath::uninstallFunction(StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("unparsed-entity-uri"))); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::initializeAttributeKeysTable(AttributeKeysMapType& theAttributeKeys) |
| { |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_METHOD] = Constants::TATTRNAME_OUTPUT_METHOD; |
| theAttributeKeys[Constants::ATTRNAME_AMOUNT] = Constants::TATTRNAME_AMOUNT; |
| theAttributeKeys[Constants::ATTRNAME_ANCESTOR] = Constants::TATTRNAME_ANCESTOR; |
| theAttributeKeys[Constants::ATTRNAME_ARCHIVE] = Constants::TATTRNAME_ARCHIVE; |
| theAttributeKeys[Constants::ATTRNAME_ATTRIBUTE] = Constants::TATTRNAME_ATTRIBUTE; |
| theAttributeKeys[Constants::ATTRNAME_ATTRIBUTE_SET] = Constants::TATTRNAME_ATTRIBUTE_SET; |
| theAttributeKeys[Constants::ATTRNAME_CASEORDER] = Constants::TATTRNAME_CASEORDER; |
| theAttributeKeys[Constants::ATTRNAME_CLASS] = Constants::TATTRNAME_CLASS; |
| theAttributeKeys[Constants::ATTRNAME_CLASSID] = Constants::TATTRNAME_CLASSID; |
| theAttributeKeys[Constants::ATTRNAME_CODEBASE] = Constants::TATTRNAME_CODEBASE; |
| theAttributeKeys[Constants::ATTRNAME_CODETYPE] = Constants::TATTRNAME_CODETYPE; |
| theAttributeKeys[Constants::ATTRNAME_CONDITION] = Constants::TATTRNAME_CONDITION; |
| theAttributeKeys[Constants::ATTRNAME_COPYTYPE] = Constants::TATTRNAME_COPYTYPE; |
| theAttributeKeys[Constants::ATTRNAME_COUNT] = Constants::TATTRNAME_COUNT; |
| theAttributeKeys[Constants::ATTRNAME_DATATYPE] = Constants::TATTRNAME_DATATYPE; |
| theAttributeKeys[Constants::ATTRNAME_DEFAULT] = Constants::TATTRNAME_DEFAULT; |
| theAttributeKeys[Constants::ATTRNAME_DEFAULTSPACE] = Constants::TATTRNAME_DEFAULTSPACE; |
| theAttributeKeys[Constants::ATTRNAME_DEPTH] = Constants::TATTRNAME_DEPTH; |
| theAttributeKeys[Constants::ATTRNAME_DIGITGROUPSEP] = Constants::TATTRNAME_DIGITGROUPSEP; |
| theAttributeKeys[Constants::ATTRNAME_DISABLE_OUTPUT_ESCAPING] = Constants::TATTRNAME_DISABLE_OUTPUT_ESCAPING; |
| theAttributeKeys[Constants::ATTRNAME_ELEMENT] = Constants::TATTRNAME_ELEMENT; |
| theAttributeKeys[Constants::ATTRNAME_ELEMENTS] = Constants::TATTRNAME_ELEMENTS; |
| theAttributeKeys[Constants::ATTRNAME_EXPR] = Constants::TATTRNAME_EXPR; |
| theAttributeKeys[Constants::ATTRNAME_EXTENSIONELEMENTPREFIXES] = Constants::TATTRNAME_EXTENSIONELEMENTPREFIXES; |
| theAttributeKeys[Constants::ATTRNAME_FORMAT] = Constants::TATTRNAME_FORMAT; |
| theAttributeKeys[Constants::ATTRNAME_FROM] = Constants::TATTRNAME_FROM; |
| theAttributeKeys[Constants::ATTRNAME_GROUPINGSEPARATOR] = Constants::TATTRNAME_GROUPINGSEPARATOR; |
| theAttributeKeys[Constants::ATTRNAME_GROUPINGSIZE] = Constants::TATTRNAME_GROUPINGSIZE; |
| theAttributeKeys[Constants::ATTRNAME_HREF] = Constants::TATTRNAME_HREF; |
| theAttributeKeys[Constants::ATTRNAME_ID] = Constants::TATTRNAME_ID; |
| theAttributeKeys[Constants::ATTRNAME_IMPORTANCE] = Constants::TATTRNAME_IMPORTANCE; |
| theAttributeKeys[Constants::ATTRNAME_INDENTRESULT] = Constants::TATTRNAME_INDENTRESULT; |
| theAttributeKeys[Constants::ATTRNAME_LANG] = Constants::TATTRNAME_LANG; |
| theAttributeKeys[Constants::ATTRNAME_LETTERVALUE] = Constants::TATTRNAME_LETTERVALUE; |
| theAttributeKeys[Constants::ATTRNAME_LEVEL] = Constants::TATTRNAME_LEVEL; |
| theAttributeKeys[Constants::ATTRNAME_MATCH] = Constants::TATTRNAME_MATCH; |
| theAttributeKeys[Constants::ATTRNAME_METHOD] = Constants::TATTRNAME_METHOD; |
| theAttributeKeys[Constants::ATTRNAME_MODE] = Constants::TATTRNAME_MODE; |
| theAttributeKeys[Constants::ATTRNAME_NAME] = Constants::TATTRNAME_NAME; |
| theAttributeKeys[Constants::ATTRNAME_NAMESPACE] = Constants::TATTRNAME_NAMESPACE; |
| theAttributeKeys[Constants::ATTRNAME_NDIGITSPERGROUP] = Constants::TATTRNAME_NDIGITSPERGROUP; |
| theAttributeKeys[Constants::ATTRNAME_NS] = Constants::TATTRNAME_NS; |
| theAttributeKeys[Constants::ATTRNAME_ONLY] = Constants::TATTRNAME_ONLY; |
| theAttributeKeys[Constants::ATTRNAME_ORDER] = Constants::TATTRNAME_ORDER; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_CDATA_SECTION_ELEMENTS] = Constants::TATTRNAME_OUTPUT_CDATA_SECTION_ELEMENTS; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_DOCTYPE_PUBLIC] = Constants::TATTRNAME_OUTPUT_DOCTYPE_PUBLIC; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_DOCTYPE_SYSTEM] = Constants::TATTRNAME_OUTPUT_DOCTYPE_SYSTEM; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_ENCODING] = Constants::TATTRNAME_OUTPUT_ENCODING; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_INDENT] = Constants::TATTRNAME_OUTPUT_INDENT; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_MEDIATYPE] = Constants::TATTRNAME_OUTPUT_MEDIATYPE; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_STANDALONE] = Constants::TATTRNAME_OUTPUT_STANDALONE; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_VERSION] = Constants::TATTRNAME_OUTPUT_VERSION; |
| theAttributeKeys[Constants::ATTRNAME_OUTPUT_OMITXMLDECL] = Constants::TATTRNAME_OUTPUT_OMITXMLDECL; |
| theAttributeKeys[Constants::ATTRNAME_PRIORITY] = Constants::TATTRNAME_PRIORITY; |
| theAttributeKeys[Constants::ATTRNAME_REFID] = Constants::TATTRNAME_REFID; |
| theAttributeKeys[Constants::ATTRNAME_RESULTNS] = Constants::TATTRNAME_RESULTNS; |
| theAttributeKeys[Constants::ATTRNAME_SELECT] = Constants::TATTRNAME_SELECT; |
| theAttributeKeys[Constants::ATTRNAME_SEQUENCESRC] = Constants::TATTRNAME_SEQUENCESRC; |
| theAttributeKeys[Constants::ATTRNAME_STYLE] = Constants::TATTRNAME_STYLE; |
| theAttributeKeys[Constants::ATTRNAME_TEST] = Constants::TATTRNAME_TEST; |
| theAttributeKeys[Constants::ATTRNAME_TOSTRING] = Constants::TATTRNAME_TOSTRING; |
| theAttributeKeys[Constants::ATTRNAME_TYPE] = Constants::TATTRNAME_TYPE; |
| theAttributeKeys[Constants::ATTRNAME_USE] = Constants::TATTRNAME_USE; |
| theAttributeKeys[Constants::ATTRNAME_USEATTRIBUTESETS] = Constants::TATTRNAME_USEATTRIBUTESETS; |
| theAttributeKeys[Constants::ATTRNAME_VALUE] = Constants::TATTRNAME_VALUE; |
| |
| theAttributeKeys[Constants::ATTRNAME_XMLNSDEF] = Constants::TATTRNAME_XMLNSDEF; |
| theAttributeKeys[Constants::ATTRNAME_XMLNS] = Constants::TATTRNAME_XMLNS; |
| theAttributeKeys[Constants::ATTRNAME_XMLSPACE] = Constants::TATTRNAME_XMLSPACE; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::initializeElementKeysTable(ElementKeysMapType& theElementKeys) |
| { |
| theElementKeys[Constants::ELEMNAME_APPLY_TEMPLATES_STRING] = Constants::ELEMNAME_APPLY_TEMPLATES; |
| theElementKeys[Constants::ELEMNAME_WITHPARAM_STRING] = Constants::ELEMNAME_WITHPARAM; |
| theElementKeys[Constants::ELEMNAME_CONSTRUCT_STRING] = Constants::ELEMNAME_CONSTRUCT; |
| theElementKeys[Constants::ELEMNAME_CONTENTS_STRING] = Constants::ELEMNAME_CONTENTS; |
| theElementKeys[Constants::ELEMNAME_COPY_STRING] = Constants::ELEMNAME_COPY; |
| theElementKeys[Constants::ELEMNAME_COPY_OF_STRING] = Constants::ELEMNAME_COPY_OF; |
| |
| theElementKeys[Constants::ELEMNAME_ATTRIBUTESET_STRING] = Constants::ELEMNAME_DEFINEATTRIBUTESET; |
| |
| theElementKeys[Constants::ELEMNAME_USE_STRING] = Constants::ELEMNAME_USE; |
| |
| theElementKeys[Constants::ELEMNAME_VARIABLE_STRING] = Constants::ELEMNAME_VARIABLE; |
| theElementKeys[Constants::ELEMNAME_PARAMVARIABLE_STRING] = Constants::ELEMNAME_PARAMVARIABLE; |
| |
| theElementKeys[Constants::ELEMNAME_DISPLAYIF_STRING] = Constants::ELEMNAME_DISPLAYIF; |
| theElementKeys[Constants::ELEMNAME_EMPTY_STRING] = Constants::ELEMNAME_EMPTY; |
| theElementKeys[Constants::ELEMNAME_EVAL_STRING] = Constants::ELEMNAME_EVAL; |
| theElementKeys[Constants::ELEMNAME_CALLTEMPLATE_STRING] = Constants::ELEMNAME_CALLTEMPLATE; |
| theElementKeys[Constants::ELEMNAME_TEMPLATE_STRING] = Constants::ELEMNAME_TEMPLATE; |
| theElementKeys[Constants::ELEMNAME_STYLESHEET_STRING] = Constants::ELEMNAME_STYLESHEET; |
| theElementKeys[Constants::ELEMNAME_TRANSFORM_STRING] = Constants::ELEMNAME_STYLESHEET; |
| theElementKeys[Constants::ELEMNAME_IMPORT_STRING] = Constants::ELEMNAME_IMPORT; |
| theElementKeys[Constants::ELEMNAME_INCLUDE_STRING] = Constants::ELEMNAME_INCLUDE; |
| theElementKeys[Constants::ELEMNAME_FOREACH_STRING] = Constants::ELEMNAME_FOREACH; |
| theElementKeys[Constants::ELEMNAME_VALUEOF_STRING] = Constants::ELEMNAME_VALUEOF; |
| theElementKeys[Constants::ELEMNAME_KEY_STRING] = Constants::ELEMNAME_KEY; |
| theElementKeys[Constants::ELEMNAME_STRIPSPACE_STRING] = Constants::ELEMNAME_STRIPSPACE; |
| theElementKeys[Constants::ELEMNAME_PRESERVESPACE_STRING] = Constants::ELEMNAME_PRESERVESPACE; |
| theElementKeys[Constants::ELEMNAME_NUMBER_STRING] = Constants::ELEMNAME_NUMBER; |
| theElementKeys[Constants::ELEMNAME_IF_STRING] = Constants::ELEMNAME_IF; |
| theElementKeys[Constants::ELEMNAME_CHOOSE_STRING] = Constants::ELEMNAME_CHOOSE; |
| theElementKeys[Constants::ELEMNAME_WHEN_STRING] = Constants::ELEMNAME_WHEN; |
| theElementKeys[Constants::ELEMNAME_OTHERWISE_STRING] = Constants::ELEMNAME_OTHERWISE; |
| theElementKeys[Constants::ELEMNAME_TEXT_STRING] = Constants::ELEMNAME_TEXT; |
| theElementKeys[Constants::ELEMNAME_ELEMENT_STRING] = Constants::ELEMNAME_ELEMENT; |
| theElementKeys[Constants::ELEMNAME_ATTRIBUTE_STRING] = Constants::ELEMNAME_ATTRIBUTE; |
| theElementKeys[Constants::ELEMNAME_SORT_STRING] = Constants::ELEMNAME_SORT; |
| theElementKeys[Constants::ELEMNAME_PI_STRING] = Constants::ELEMNAME_PI; |
| theElementKeys[Constants::ELEMNAME_COMMENT_STRING] = Constants::ELEMNAME_COMMENT; |
| |
| theElementKeys[Constants::ELEMNAME_COUNTER_STRING] = Constants::ELEMNAME_COUNTER; |
| theElementKeys[Constants::ELEMNAME_COUNTERS_STRING] = Constants::ELEMNAME_COUNTERS; |
| theElementKeys[Constants::ELEMNAME_COUNTERINCREMENT_STRING] = Constants::ELEMNAME_COUNTERINCREMENT; |
| theElementKeys[Constants::ELEMNAME_COUNTERRESET_STRING] = Constants::ELEMNAME_COUNTERRESET; |
| theElementKeys[Constants::ELEMNAME_COUNTERSCOPE_STRING] = Constants::ELEMNAME_COUNTERSCOPE; |
| |
| theElementKeys[Constants::ELEMNAME_APPLY_IMPORTS_STRING] = Constants::ELEMNAME_APPLY_IMPORTS; |
| |
| theElementKeys[Constants::ELEMNAME_EXTENSION_STRING] = Constants::ELEMNAME_EXTENSION; |
| theElementKeys[Constants::ELEMNAME_MESSAGE_STRING] = Constants::ELEMNAME_MESSAGE; |
| theElementKeys[Constants::ELEMNAME_LOCALE_STRING] = Constants::ELEMNAME_LOCALE; |
| theElementKeys[Constants::ELEMNAME_FALLBACK_STRING] = Constants::ELEMNAME_FALLBACK; |
| theElementKeys[Constants::ELEMNAME_OUTPUT_STRING] = Constants::ELEMNAME_OUTPUT; |
| |
| theElementKeys[Constants::ELEMNAME_DECIMALFORMAT_STRING] = Constants::ELEMNAME_DECIMALFORMAT; |
| theElementKeys[Constants::ELEMNAME_NSALIAS_STRING] = Constants::ELEMNAME_NSALIAS; |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::initializeXSLT4JElementKeys(ElementKeysMapType& theElementKeys) |
| { |
| theElementKeys[Constants::ELEMNAME_COMPONENT_STRING] = Constants::ELEMNAME_COMPONENT; |
| theElementKeys[Constants::ELEMNAME_SCRIPT_STRING] = Constants::ELEMNAME_SCRIPT; |
| } |
| |
| |
| |
| static XalanDOMString s_XSLNameSpaceURL; |
| |
| static XalanDOMString s_XSLT4JNameSpaceURL; |
| |
| static XalanDOMString s_uniqueNamespacePrefix; |
| |
| static XSLTEngineImpl::AttributeKeysMapType s_attributeKeys; |
| |
| static XSLTEngineImpl::ElementKeysMapType s_elementKeys; |
| |
| static XSLTEngineImpl::ElementKeysMapType s_XSLT4JElementKeys; |
| |
| |
| |
| const double XSLTEngineImpl::s_XSLTVerSupported(1.0); |
| |
| const XalanDOMString& XSLTEngineImpl::s_XSLNameSpaceURL = ::s_XSLNameSpaceURL; |
| |
| const XalanDOMString& XSLTEngineImpl::s_XSLT4JNameSpaceURL = ::s_XSLT4JNameSpaceURL; |
| |
| const XalanDOMString& XSLTEngineImpl::s_uniqueNamespacePrefix = ::s_uniqueNamespacePrefix; |
| |
| |
| const XSLTEngineImpl::AttributeKeysMapType& XSLTEngineImpl::s_attributeKeys = ::s_attributeKeys; |
| |
| const XSLTEngineImpl::ElementKeysMapType& XSLTEngineImpl::s_elementKeys = ::s_elementKeys; |
| |
| const XSLTEngineImpl::ElementKeysMapType& XSLTEngineImpl::s_XSLT4JElementKeys = ::s_XSLT4JElementKeys; |
| |
| |
| |
| void |
| XSLTEngineImpl::initialize() |
| { |
| ::s_XSLNameSpaceURL = XALAN_STATIC_UCODE_STRING("http://www.w3.org/1999/XSL/Transform"); |
| |
| ::s_XSLT4JNameSpaceURL = XALAN_STATIC_UCODE_STRING("http://xml.apache.org/xslt"); |
| |
| ::s_uniqueNamespacePrefix = XALAN_STATIC_UCODE_STRING("ns"); |
| |
| installFunctions(); |
| |
| initializeAttributeKeysTable(::s_attributeKeys); |
| |
| initializeElementKeysTable(::s_elementKeys); |
| |
| initializeXSLT4JElementKeys(::s_XSLT4JElementKeys); |
| } |
| |
| |
| |
| void |
| XSLTEngineImpl::terminate() |
| { |
| ElementKeysMapType().swap(::s_XSLT4JElementKeys); |
| |
| ElementKeysMapType().swap(::s_elementKeys); |
| |
| AttributeKeysMapType().swap(::s_attributeKeys); |
| |
| uninstallFunctions(); |
| |
| releaseMemory(::s_uniqueNamespacePrefix); |
| |
| releaseMemory(::s_XSLT4JNameSpaceURL); |
| |
| releaseMemory(::s_XSLNameSpaceURL); |
| } |