00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 #if !defined(XALAN_XSLTENGINEIMPL_HEADER_GUARD) 00019 #define XALAN_XSLTENGINEIMPL_HEADER_GUARD 00020 00021 00022 00023 // Base include file. Must be first. 00024 #include "XSLTDefinitions.hpp" 00025 00026 00027 00028 // Base class 00029 #include "XSLTProcessor.hpp" 00030 00031 00032 00033 00034 // Standard library headers 00035 #include <cassert> 00036 00037 00038 00039 #include <xalanc/XalanDOM/XalanDOMString.hpp> 00040 00041 00042 00043 #if defined(XALAN_AUTO_PTR_REQUIRES_DEFINITION) 00044 #include <xalanc/XPath/XPathProcessor.hpp> 00045 #endif 00046 00047 00048 00049 #include <xalanc/Include/XalanMemMgrAutoPtr.hpp> 00050 #include <xalanc/Include/XalanMap.hpp> 00051 00052 00053 00054 #include <xalanc/PlatformSupport/AttributeListImpl.hpp> 00055 #include <xalanc/PlatformSupport/DOMStringHelper.hpp> 00056 #include <xalanc/PlatformSupport/PrefixResolver.hpp> 00057 00058 00059 00060 #include <xalanc/DOMSupport/XalanNamespacesStack.hpp> 00061 00062 00063 00064 #include <xalanc/XPath/Function.hpp> 00065 00066 00067 00068 #include <xalanc/XPath/XPathConstructionContextDefault.hpp> 00069 00070 00071 00072 #include "OutputContextStack.hpp" 00073 #include "ProblemListenerDefault.hpp" 00074 #include "ResultNamespacesStack.hpp" 00075 #include "StylesheetExecutionContext.hpp" 00076 #include "XSLTProcessorException.hpp" 00077 #include "XalanParamHolder.hpp" 00078 00079 00080 00081 XALAN_DECLARE_XERCES_CLASS(InputSource) 00082 XALAN_DECLARE_XERCES_CLASS(DocumentHandler) 00083 00084 00085 00086 XALAN_CPP_NAMESPACE_BEGIN 00087 00088 00089 00090 typedef XERCES_CPP_NAMESPACE_QUALIFIER InputSource InputSourceType; 00091 typedef XERCES_CPP_NAMESPACE_QUALIFIER DocumentHandler DocumentHandlerType; 00092 00093 XALAN_USING_XERCES(InputSource) 00094 XALAN_USING_XERCES(DocumentHandler) 00095 00096 00097 00098 // Forward declarations... 00099 class DOMSupport; 00100 class GenerateEvent; 00101 class PrintWriter; 00102 class StylesheetConstructionContext; 00103 class StylesheetRoot; 00104 class XalanAttr; 00105 class XalanSourceTreeDocument; 00106 class XalanText; 00107 class XMLParserLiaison; 00108 class XObject; 00109 class XPathEnvSupport; 00110 class XPathFactory; 00111 class XPathProcessor; 00112 class XSLTResultTarget; 00113 00114 00115 00116 /** 00117 * It's the responsibility of the XSLTEngineImpl class, collaborating with the 00118 * XML parser liaison, the DOM, and the XPath engine, to transform a source 00119 * tree of nodes into a result tree according to instructions and templates 00120 * specified by a stylesheet tree. The process method is the primary 00121 * public entry points. 00122 * 00123 * 00124 * If you reuse the processor instance, you should call reset() between calls. 00125 * 00126 */ 00127 00128 class XALAN_XSLT_EXPORT XSLTEngineImpl : public XSLTProcessor, public PrefixResolver 00129 { 00130 public: 00131 00132 struct LessXalanDOMStringPointers 00133 { 00134 bool 00135 operator()( 00136 const XalanDOMString* theLHS, 00137 const XalanDOMString* theRHS) const 00138 { 00139 if (theLHS == 0 && theRHS != 0) 00140 { 00141 return true; 00142 } 00143 else if (theRHS == 0) 00144 { 00145 return false; 00146 } 00147 else 00148 { 00149 return theLHS->compare(*theRHS) < 0 ? true : false; 00150 } 00151 } 00152 }; 00153 00154 typedef XalanVector<const Locator*> LocatorStack; 00155 typedef XalanVector<TraceListener*> TraceListenerVectorType; 00156 typedef XalanVector<const XalanDOMString*> XalanDOMStringPointerVectorType; 00157 00158 typedef XalanVector<bool> BoolVectorType; 00159 00160 struct FindStringPointerFunctor 00161 { 00162 FindStringPointerFunctor(const XalanDOMString& theString) : 00163 m_string(theString) 00164 { 00165 } 00166 00167 bool 00168 operator()(const XalanDOMString* theString) const 00169 { 00170 assert(theString != 0); 00171 00172 return *theString == m_string; 00173 } 00174 00175 private: 00176 00177 const XalanDOMString& m_string; 00178 }; 00179 00180 typedef XalanMemMgrAutoPtr<XPathProcessor> XPathProcessorPtrType; 00181 typedef Function::XObjectArgVectorType XObjectArgVectorType; 00182 typedef StylesheetExecutionContext::ParamVectorType ParamVectorType; 00183 typedef XPathConstructionContext::GetCachedString CCGetCachedString; 00184 typedef XPathExecutionContext::GetCachedString ECGetCachedString; 00185 00186 typedef XalanMap<XalanDOMString, XalanParamHolder> ParamMapType; 00187 00188 // Public members 00189 //--------------------------------------------------------------------- 00190 00191 /** 00192 * Construct an XSL processor that can call back to a XML processor, so it 00193 * can handle included files, and the like. You must create a new instance 00194 * of the XSLTEngineImpl class each time you run a transformation. 00195 * 00196 * @param XMLParserLiaison liaison to an object that can help with a 00197 * specific parser implementation 00198 * @param xpathEnvSupport An XPathEnvSupport instance 00199 * @param domSupport A DOMSupport instance for the DOM being used 00200 * @param xobjectFactory object responsible for XObject objects 00201 * @param xpathFactory object responsible for XPath objects 00202 */ 00203 XSLTEngineImpl( 00204 MemoryManager& theManager, 00205 XMLParserLiaison& parserLiaison, 00206 XPathEnvSupport& xpathEnvSupport, 00207 DOMSupport& domSupport, 00208 XObjectFactory& xobjectFactory, 00209 XPathFactory& xpathFactory); 00210 00211 virtual 00212 ~XSLTEngineImpl(); 00213 00214 MemoryManager& 00215 getMemoryManager() const 00216 { 00217 return m_xpathConstructionContext.getMemoryManager(); 00218 } 00219 00220 MemoryManager& 00221 getMemoryManager() 00222 { 00223 return m_xpathConstructionContext.getMemoryManager(); 00224 } 00225 00226 /** 00227 * Perform initialization of statics -- must be called before any 00228 * processing occurs. See class XSLTInit. 00229 */ 00230 static void 00231 initialize(MemoryManager& theManager); 00232 00233 /** 00234 * Perform termination of statics. See class XSLTInit. 00235 */ 00236 static void 00237 terminate(); 00238 00239 // These methods are inherited from XSLTProcessor ... 00240 00241 virtual void 00242 problem( 00243 eSource source, 00244 eClassification classification, 00245 const XalanDOMString& msg, 00246 const Locator* locator, 00247 const XalanNode* sourceNode); 00248 00249 virtual void 00250 problem( 00251 eSource source, 00252 eClassification classification, 00253 const XalanDOMString& msg, 00254 const XalanNode* sourceNode); 00255 00256 virtual void 00257 process( 00258 const XSLTInputSource& inputSource, 00259 const XSLTInputSource& stylesheetSource, 00260 XSLTResultTarget& outputTarget, 00261 StylesheetConstructionContext& constructionContext, 00262 StylesheetExecutionContext& executionContext); 00263 00264 virtual void 00265 process( 00266 const XSLTInputSource& inputSource, 00267 XSLTResultTarget& outputTarget, 00268 StylesheetExecutionContext& executionContext); 00269 00270 virtual StylesheetRoot* 00271 processStylesheet( 00272 const XSLTInputSource& stylesheetSource, 00273 StylesheetConstructionContext& constructionContext); 00274 00275 virtual StylesheetRoot* 00276 processStylesheet( 00277 const XalanDOMString& xsldocURLString, 00278 StylesheetConstructionContext& constructionContext); 00279 00280 virtual XalanNode* 00281 getSourceTreeFromInput(const XSLTInputSource& inputSource); 00282 00283 virtual void 00284 resolveTopLevelParams(StylesheetExecutionContext& executionContext); 00285 00286 virtual XMLParserLiaison& 00287 getXMLParserLiaison() const; 00288 00289 virtual void 00290 getUniqueNamespaceValue(XalanDOMString& theValue); 00291 00292 virtual void 00293 setStylesheetParam( 00294 const XalanDOMString& key, 00295 const XalanDOMString& expression); 00296 00297 virtual void 00298 setStylesheetParam( 00299 const XalanDOMString& key, 00300 XObjectPtr value); 00301 00302 virtual void 00303 clearStylesheetParams(); 00304 00305 virtual FormatterListener* 00306 getFormatterListener() const; 00307 00308 virtual void 00309 setFormatterListener(FormatterListener* flistener); 00310 00311 // Trace-related functions... 00312 00313 virtual size_type 00314 getTraceListeners() const; 00315 00316 virtual void 00317 addTraceListener(TraceListener* tl); 00318 00319 virtual void 00320 removeTraceListener(TraceListener* tl); 00321 00322 virtual void 00323 fireGenerateEvent(const GenerateEvent& ge); 00324 00325 virtual void 00326 fireTraceEvent(const TracerEvent& te); 00327 00328 virtual void 00329 fireSelectEvent(const SelectionEvent& se); 00330 00331 virtual bool 00332 getTraceSelects() const; 00333 00334 virtual void 00335 setTraceSelects(bool b); 00336 00337 void 00338 traceSelect( 00339 StylesheetExecutionContext& executionContext, 00340 const ElemTemplateElement& theTemplate, 00341 const NodeRefListBase& nl, 00342 const XPath* xpath) const; 00343 00344 virtual void 00345 setQuietConflictWarnings(bool b); 00346 00347 virtual void 00348 setDiagnosticsOutput(PrintWriter* pw); 00349 00350 00351 // Inherited from PrefixResolver... 00352 00353 /** 00354 * Retrieve a namespace corresponding to a prefix. This assumes that 00355 * the PrevixResolver hold's its own namespace context, or is a namespace 00356 * context itself. 00357 * 00358 * @param prefix Prefix to resolve 00359 * @return namespace that prefix resolves to, or null if prefix is not found 00360 */ 00361 virtual const XalanDOMString* 00362 getNamespaceForPrefix(const XalanDOMString& prefix) const; 00363 00364 /** 00365 * Retrieve the base URI for the resolver. 00366 * 00367 * @return URI string 00368 */ 00369 virtual const XalanDOMString& 00370 getURI() const; 00371 00372 /** 00373 * Read in the XML file, either producing a Document or calling SAX events, 00374 * and register the document in a table. If the document has already been 00375 * read in, it will not be reparsed. 00376 * 00377 * @param urlString location of the XML 00378 * @param docHandler pointer to SAX event handler 00379 * @param docToRegister if using a SAX event handler, the object to register in the source docs table. 00380 * @return document object, which represents the parsed XML 00381 * @exception SAXException 00382 */ 00383 XalanDocument* 00384 parseXML( 00385 const XalanDOMString& urlString, 00386 DocumentHandler* docHandler, 00387 XalanDocument* docToRegister, 00388 ErrorHandler* theErrorHandler = 0); 00389 00390 /** 00391 * Read in the XML file, either producing a Document or calling SAX events, 00392 * and register the document in a table. If the document has already been 00393 * read in, it will not be reparsed. 00394 * 00395 * @param inputSource location of the XML 00396 * @param docHandler pointer to SAX event handler 00397 * @param docToRegister if using a SAX event handler, the object to register in the source docs table. 00398 * @return document object, which represents the parsed XML 00399 * @exception SAXException 00400 */ 00401 XalanDocument* 00402 parseXML( 00403 const InputSource& inputSource, 00404 DocumentHandler* docHandler, 00405 XalanDocument* docToRegister, 00406 ErrorHandler* theErrorHandler = 0); 00407 00408 /** 00409 * Reset the state of the XSL processor by reading in a new XSL stylesheet 00410 * from a processing instruction. 00411 * 00412 * @param xslURLString valid URI to an XSL stylesheet 00413 * @param fragBase base of tree if URI represents document 00414 * fragment 00415 * @param xmlBaseIdent base identifier for stylesheet URI 00416 * @param isRoot true if stylesheet is root of tree 00417 * @param constructionContext context for construction of object 00418 * @return pointer to stylesheet 00419 */ 00420 Stylesheet* 00421 getStylesheetFromPIURL( 00422 const XalanDOMString& xslURLString, 00423 XalanNode& fragBase, 00424 const XalanDOMString& xmlBaseIdent, 00425 bool isRoot, 00426 StylesheetConstructionContext& constructionContext); 00427 00428 /** 00429 * Flush the pending element. 00430 */ 00431 void 00432 flushPending(); 00433 00434 /** 00435 * Add a namespace declaration to the namespace stack 00436 * 00437 * @param prefix namespace prefix 00438 * @param namespaceVal value of namespace 00439 */ 00440 void 00441 addResultNamespaceDecl( 00442 const XalanDOMString& prefix, 00443 const XalanDOMString& namespaceVal) 00444 { 00445 addResultNamespaceDecl( 00446 prefix, 00447 namespaceVal.c_str(), 00448 namespaceVal.length()); 00449 } 00450 00451 /** 00452 * Add a namespace declaration to the namespace stack 00453 * 00454 * @param prefix namespace prefix 00455 * @param namespaceVal value of namespace 00456 * @param len length of namespace 00457 */ 00458 void 00459 addResultNamespaceDecl( 00460 const XalanDOMString& prefix, 00461 const XalanDOMChar* namespaceVal, 00462 size_type len) 00463 { 00464 m_resultNamespacesStack.addDeclaration( 00465 prefix, 00466 namespaceVal, 00467 len); 00468 } 00469 00470 /** 00471 * Add attribute to attribute list, and if it is a namespace, add it to the 00472 * namespaces stack. 00473 * 00474 * @param attList attribute list added to 00475 * @param aname name of attribute 00476 * @param value value of attribute 00477 * @param fromCopy true if the attribute is being copied from the source tree 00478 * @param locator The Locator for reporting errors. 00479 */ 00480 void 00481 addResultAttribute( 00482 AttributeListImpl& attList, 00483 const XalanDOMString& aname, 00484 const XalanDOMString& value, 00485 bool fromCopy = false, 00486 const Locator* locator = 0) 00487 { 00488 addResultAttribute( 00489 attList, 00490 aname, 00491 value.c_str(), 00492 fromCopy, 00493 locator); 00494 } 00495 00496 /** 00497 * Add attribute to attribute list, and if it is a namespace, add it to the 00498 * namespaces stack. 00499 * 00500 * @param attList attribute list added to 00501 * @param aname name of attribute 00502 * @param value value of attribute 00503 * @param fromCopy true if the attribute is being copied from the source tree 00504 * @param locator The Locator for reporting errors. 00505 */ 00506 void 00507 addResultAttribute( 00508 AttributeListImpl& attList, 00509 const XalanDOMString& aname, 00510 const XalanDOMChar* value, 00511 bool fromCopy = false, 00512 const Locator* locator = 0) 00513 { 00514 addResultAttribute( 00515 attList, 00516 aname, 00517 value, 00518 length(value), 00519 fromCopy, 00520 locator); 00521 } 00522 00523 /** 00524 * Add attribute to attribute list, and if it is a namespace, add it to the 00525 * namespaces stack. 00526 * 00527 * @param attList attribute list added to 00528 * @param aname name of attribute 00529 * @param value value of attribute 00530 * @param theLength The length of the value 00531 * @param fromCopy true if the attribute is being copied from the source tree 00532 * @param locator The Locator for reporting errors. 00533 */ 00534 void 00535 addResultAttribute( 00536 AttributeListImpl& attList, 00537 const XalanDOMString& aname, 00538 const XalanDOMChar* value, 00539 size_type theLength, 00540 bool fromCopy = false, 00541 const Locator* locator = 0); 00542 00543 /** 00544 * Add attribute to pending attributes list, and if it is a namespace, add 00545 * it to the namespaces stack. 00546 * 00547 * @param aname name of attribute 00548 * @param value value of attribute 00549 * @param fromCopy true if the attribute is being copied from the source tree 00550 * @param locator The Locator for reporting errors. 00551 */ 00552 void 00553 addResultAttribute( 00554 const XalanDOMString& aname, 00555 const XalanDOMChar* value, 00556 bool fromCopy = false, 00557 const Locator* locator = 0) 00558 { 00559 assert(m_outputContextStack.empty() == false); 00560 00561 addResultAttribute( 00562 getPendingAttributesImpl(), 00563 aname, 00564 value, 00565 fromCopy, 00566 locator); 00567 } 00568 00569 /** 00570 * Add attribute to pending attributes list, and if it is a namespace, add 00571 * it to the namespaces stack. 00572 * 00573 * @param aname name of attribute 00574 * @param value value of attribute 00575 * @param fromCopy true if the attribute is being copied from the source tree 00576 * @param locator The Locator for reporting errors. 00577 */ 00578 void 00579 addResultAttribute( 00580 const XalanDOMString& aname, 00581 const XalanDOMString& value, 00582 bool fromCopy = false, 00583 const Locator* locator = 0) 00584 { 00585 assert(m_outputContextStack.empty() == false); 00586 00587 addResultAttribute( 00588 getPendingAttributesImpl(), 00589 aname, 00590 value, 00591 fromCopy, 00592 locator); 00593 } 00594 00595 /** 00596 * Report an error copying a duplicate namespace node. 00597 * 00598 * @param theName The name of the node. 00599 */ 00600 void 00601 reportDuplicateNamespaceNodeError( 00602 const XalanDOMString& theName, 00603 const Locator* locator); 00604 00605 void 00606 setDocumentLocator(const Locator* locator); 00607 00608 void 00609 startDocument(); 00610 00611 void 00612 endDocument(); 00613 00614 void 00615 startElement( 00616 const XalanDOMChar* name, 00617 AttributeListType& atts); 00618 00619 void 00620 endElement(const XalanDOMChar* name); 00621 00622 void 00623 characters ( 00624 const XalanDOMChar* ch, 00625 size_type length); 00626 00627 void 00628 ignorableWhitespace( 00629 const XalanDOMChar* ch, 00630 size_type length); 00631 00632 void 00633 processingInstruction( 00634 const XalanDOMChar* target, 00635 const XalanDOMChar* data); 00636 00637 void 00638 resetDocument(); 00639 00640 /** 00641 * Receive notification of character data. 00642 * 00643 * @param ch pointer to characters from the XML document 00644 * @param start startng offset in 'ch' array 00645 * @param length number of characters to read from the array 00646 */ 00647 void 00648 characters( 00649 const XalanDOMChar* ch, 00650 size_type start, 00651 size_type length); 00652 00653 /** 00654 * Send character data from the node to the result tree. 00655 * 00656 * @param node The node to send. 00657 */ 00658 void 00659 characters(const XalanNode& node); 00660 00661 /** 00662 * Send character data from an XObject to the result tree. 00663 * 00664 * @param node The xobject to send. 00665 */ 00666 void 00667 characters(const XObjectPtr& xobject); 00668 00669 /** 00670 * Receive notification of the beginning of an element with an empty 00671 * attribute list 00672 * 00673 * @param name element type name 00674 */ 00675 void 00676 startElement(const XalanDOMChar* name); 00677 00678 /** 00679 * Receive notification of character data. If available, when the 00680 * disable-output-escaping attribute is used, output raw text without 00681 * escaping. 00682 * 00683 * @param ch pointer to characters from the XML document 00684 * @param start start position in the array 00685 * @param length number of characters to read from the array 00686 */ 00687 void 00688 charactersRaw( 00689 const XalanDOMChar* ch, 00690 size_type start, 00691 size_type length); 00692 00693 /** 00694 * Send raw character data from the node to the result tree. 00695 * 00696 * @param node The node to send. 00697 */ 00698 void 00699 charactersRaw(const XalanNode& node); 00700 00701 /** 00702 * Send raw character data from an XObject to the result tree. 00703 * 00704 * @param node The xobject to send. 00705 */ 00706 void 00707 charactersRaw(const XObjectPtr& xobject); 00708 00709 /** 00710 * Called when a Comment is to be constructed. 00711 * 00712 * @param data pointer to comment data 00713 */ 00714 void 00715 comment(const XalanDOMChar* data); 00716 00717 /** 00718 * Receive notification of a entityReference. 00719 * 00720 * @param data pointer to characters from the XML document 00721 * @exception SAXException 00722 */ 00723 void 00724 entityReference(const XalanDOMChar* data); 00725 00726 /** 00727 * Receive notification of cdata. 00728 * 00729 * @param ch pointer to characters from the XML document 00730 * @param start start position in the array 00731 * @param length number of characters to read from the array 00732 */ 00733 void 00734 cdata( 00735 const XalanDOMChar* ch, 00736 size_type start, 00737 size_type length); 00738 00739 /** 00740 * Clone a node to the result tree 00741 * 00742 * @param node node to clone 00743 * @param cloneTextNodesOnly if true, only text nodes will be cloned 00744 * @param locator the Locator for the event, if any. 00745 */ 00746 void 00747 cloneToResultTree( 00748 const XalanNode& node, 00749 bool cloneTextNodesOnly, 00750 const Locator* locator); 00751 00752 /** 00753 * Clone a node to the result tree 00754 * 00755 * @param node node to clone 00756 * @param nodeType the type of the node 00757 * @param overrideStrip false if white space stripping should be done 00758 * @param shouldCloneAttributes true if attributes should be cloned 00759 * @param cloneTextNodesOnly if true, only text nodes will be cloned 00760 * @param locator the Locator for the event, if any. 00761 */ 00762 void 00763 cloneToResultTree( 00764 const XalanNode& node, 00765 XalanNode::NodeType nodeType, 00766 bool overrideStrip, 00767 bool shouldCloneAttributes, 00768 bool cloneTextNodesOnly, 00769 const Locator* locator); 00770 00771 /** 00772 * Output an object to the result tree by doing the right conversions. 00773 * 00774 * @param value the XObject to output 00775 * @param outputTextNodesOnly if true, only text nodes will be copied 00776 * @param locator the Locator for the event, if any. 00777 */ 00778 void 00779 outputToResultTree( 00780 const XObject& value, 00781 bool outputTextNodesOnly, 00782 const Locator* locator); 00783 00784 /** 00785 * Given a result tree fragment, walk the tree and output it to the result 00786 * stream. 00787 * 00788 * @param theTree result tree fragment 00789 * @param outputTextNodesOnly if true, only text nodes will be copied 00790 * @param locator the Locator for the event, if any. 00791 */ 00792 void 00793 outputResultTreeFragment( 00794 const XObject& theTree, 00795 bool outputTextNodesOnly, 00796 const Locator* locator) 00797 { 00798 outputResultTreeFragment( 00799 theTree.rtree(), 00800 outputTextNodesOnly, 00801 locator); 00802 } 00803 00804 /** 00805 * Given a result tree fragment, walk the tree and output it to the result 00806 * stream. 00807 * 00808 * @param theTree result tree fragment 00809 * @param outputTextNodesOnly if true, only text nodes will be copied 00810 * @param locator the Locator for the event, if any. 00811 */ 00812 void 00813 outputResultTreeFragment( 00814 const XalanDocumentFragment& theTree, 00815 bool outputTextNodesOnly, 00816 const Locator* locator); 00817 00818 /** 00819 * Retrieve the root stylesheet. 00820 * 00821 * @return pointer to root stylesheet 00822 */ 00823 virtual const StylesheetRoot* 00824 getStylesheetRoot() const; 00825 00826 /** 00827 * Set the root stylesheet. 00828 * 00829 * @param theStylesheet pointer to new root stylesheet 00830 */ 00831 virtual void 00832 setStylesheetRoot(const StylesheetRoot* theStylesheet); 00833 00834 /** 00835 * Set the execution context. 00836 * 00837 * @param theExecutionContext pointer to new execution context. 00838 */ 00839 virtual void 00840 setExecutionContext(StylesheetExecutionContext* theExecutionContext); 00841 00842 /** 00843 * Retrieve the URI for the current XSL namespace, for example, 00844 * "http://www.w3.org/1999/XSL/Transform" 00845 * 00846 * @return URI string 00847 */ 00848 static const XalanDOMString& 00849 getXSLNameSpaceURL() 00850 { 00851 return s_XSLNameSpaceURL; 00852 } 00853 00854 /** 00855 * Special Xalan namespace for built-in extensions. 00856 * 00857 * @return Xalan namespace for extensions 00858 */ 00859 static const XalanDOMString& 00860 getXalanXSLNameSpaceURL() 00861 { 00862 return s_XalanNamespaceURL; 00863 } 00864 00865 /** 00866 * Whether to warn about pattern match conflicts. 00867 * 00868 * @return true to not warn about pattern match conflicts 00869 */ 00870 bool 00871 getQuietConflictWarnings() const 00872 { 00873 return m_quietConflictWarnings; 00874 } 00875 00876 /** 00877 * Retrieve the result namespace corresponding to a prefix. 00878 * 00879 * @param prefix prefix for namespace 00880 * @return string for namespace URI 00881 */ 00882 const XalanDOMString* 00883 getResultNamespaceForPrefix(const XalanDOMString& prefix) const; 00884 00885 /** 00886 * Retrieve the result prefix corresponding to a namespace. 00887 * 00888 * @param theNamespace namespace for prefix 00889 * @return string for namespace prefix 00890 */ 00891 const XalanDOMString* 00892 getResultPrefixForNamespace(const XalanDOMString& theNamespace) const; 00893 00894 /** 00895 * Determine whether or not a prefix is in use on the pending element or 00896 * the pending attributes. 00897 * 00898 * @param thePrefix prefix for namespace 00899 * 00900 * @return true if the prefix is in use, false if not. 00901 */ 00902 bool 00903 isPendingResultPrefix(const XalanDOMString& thePrefix) const; 00904 00905 /** 00906 * Evaluate an xpath string and return the result as a numberic score. 00907 * 00908 * @param str string to evaluate 00909 * @param context context node 00910 * @param executionContext current execution context 00911 * @return score number, higher representing better match 00912 */ 00913 double 00914 evalMatchPatternStr( 00915 const XalanDOMString& str, 00916 XalanNode* context, 00917 XPathExecutionContext& executionContext); 00918 00919 /** 00920 * Create and initialize an xpath and return it. 00921 * 00922 * @param str string for XPath 00923 * @param resolver resolver for namespace resolution 00924 * @return pointer to XPath created 00925 */ 00926 const XPath* 00927 createMatchPattern( 00928 const XalanDOMString& str, 00929 const PrefixResolver& resolver); 00930 00931 /** 00932 * Return the xpath created by createXPath() or 00933 * createMatchPattern(). 00934 * 00935 * @param xpath The XPath to return. 00936 */ 00937 void 00938 returnXPath(const XPath* xpath); 00939 00940 /** 00941 * Copy XMLNS: attributes in if not already in scope. 00942 * 00943 * @param src source node 00944 */ 00945 void 00946 copyNamespaceAttributes(const XalanNode& src); 00947 00948 /** 00949 * Evaluate an xpath string and return the result. 00950 * 00951 * @param str string to evaluate 00952 * @param executionContext current execution context 00953 * @return pointer to XObject result 00954 */ 00955 const XObjectPtr 00956 evalXPathStr( 00957 const XalanDOMString& str, 00958 XPathExecutionContext& executionContext); 00959 00960 /** 00961 * Evaluate an xpath string and return the result. 00962 * 00963 * @param str string to evaluate 00964 * @param contextNode context node 00965 * @param prefixResolver prefix resolver to use 00966 * @param executionContext current execution context 00967 * @return pointer to XObject result 00968 */ 00969 const XObjectPtr 00970 evalXPathStr( 00971 const XalanDOMString& str, 00972 XalanNode* contextNode, 00973 const PrefixResolver& prefixResolver, 00974 XPathExecutionContext& executionContext); 00975 00976 /** 00977 * Evaluate an xpath string and return the result. 00978 * 00979 * @param str string to evaluate 00980 * @param contextNode context node 00981 * @param prefixResolver prefix resolver to use 00982 * @param executionContext current execution context 00983 * @return pointer to XObject result 00984 */ 00985 const XObjectPtr 00986 evalXPathStr( 00987 const XalanDOMString& str, 00988 XalanNode* contextNode, 00989 const XalanElement& prefixResolver, 00990 XPathExecutionContext& executionContext); 00991 00992 /** 00993 * Copy an attribute to an AttributeListImpl. 00994 * 00995 * @param attrName The name of the attribute 00996 * @param attrValue The value of the attribute 00997 * @param attrList The attribute list added to 00998 */ 00999 void 01000 copyAttributeToTarget( 01001 const XalanDOMString& attrName, 01002 const XalanDOMString& attrValue, 01003 AttributeListImpl& attrList); 01004 01005 /** 01006 * Get the factory for making xpaths. 01007 * 01008 * @return XPath factory object 01009 */ 01010 XPathFactory& 01011 getXPathFactory() 01012 { 01013 return m_xpathFactory; 01014 } 01015 01016 /** 01017 * Get the XPath processor object. 01018 * 01019 * @return XPathProcessor interface being used 01020 */ 01021 XPathProcessor& 01022 getXPathProcessor() 01023 { 01024 return *m_xpathProcessor.get(); 01025 } 01026 01027 /** 01028 * Reset the state. This needs to be called after a process() call 01029 * is invoked, if the processor is to be used again. 01030 */ 01031 virtual void 01032 reset(); 01033 01034 /** 01035 * Retrieve the XPath environment support object 01036 * 01037 * @return XPath environment support object 01038 */ 01039 XPathEnvSupport& 01040 getXPathEnvSupport() 01041 { 01042 return m_xpathEnvSupport; 01043 } 01044 01045 /** 01046 * Set the problem listener property. The XSL class can have a single 01047 * listener that can be informed of errors and warnings, and can normally 01048 * control if an exception is thrown or not (or the problem listeners can 01049 * throw their own RuntimeExceptions). 01050 * 01051 * @param l pointer to ProblemListener interface 01052 */ 01053 void 01054 setProblemListener(ProblemListener* l) 01055 { 01056 m_problemListener = l; 01057 } 01058 01059 /** 01060 * Get the problem listener property. The XSL class can have a single 01061 * listener that can be informed of errors and warnings, and can normally 01062 * control if an exception is thrown or not (or the problem listeners can 01063 * throw their own RuntimeExceptions). 01064 * 01065 * @return pointer to ProblemListener interface 01066 */ 01067 ProblemListener* 01068 getProblemListener() const 01069 { 01070 return m_problemListener; 01071 } 01072 01073 /* 01074 * Push a new output context using the provided FormatterListener. 01075 * 01076 * @param A pointer to the FormatterListener instance for the new context. 01077 */ 01078 void 01079 pushOutputContext(FormatterListener* theListener) 01080 { 01081 m_outputContextStack.pushContext(theListener); 01082 } 01083 01084 /* 01085 * Pop the current output context. 01086 */ 01087 void 01088 popOutputContext() 01089 { 01090 m_outputContextStack.popContext(); 01091 } 01092 01093 /* 01094 * See if there is a pending start document event waiting. 01095 * @return true if there is a start document event waiting. 01096 */ 01097 bool 01098 getHasPendingStartDocument() const 01099 { 01100 return getHasPendingStartDocumentImpl(); 01101 } 01102 01103 /* 01104 * Set the pending start document event state. 01105 * @param the new value 01106 */ 01107 void 01108 setHasPendingStartDocument(bool b) 01109 { 01110 setHasPendingStartDocumentImpl(b); 01111 } 01112 01113 /* 01114 * See if a pending start document event must be flushed. 01115 * @return true if the event must be flushed. 01116 */ 01117 bool 01118 getMustFlushPendingStartDocument() const 01119 { 01120 return getMustFlushPendingStartDocumentImpl(); 01121 } 01122 01123 /* 01124 * Set the pending start document event flush state. 01125 * @param the new value 01126 */ 01127 void 01128 setMustFlushPendingStartDocument(bool b) 01129 { 01130 setMustFlushPendingStartDocumentImpl(b); 01131 } 01132 01133 /** 01134 * Get the list of attributes yet to be processed 01135 * 01136 * @return attribute list 01137 */ 01138 const AttributeListType& 01139 getPendingAttributes() const 01140 { 01141 return getPendingAttributesImpl(); 01142 } 01143 01144 /** 01145 * Set the list of attributes yet to be processed 01146 * 01147 * @param pendingAttributes The attribute list 01148 */ 01149 void 01150 setPendingAttributes(const AttributeListType& pendingAttributes) 01151 { 01152 getPendingAttributesImpl() = pendingAttributes; 01153 } 01154 01155 /** 01156 * Replace the contents of a pending attribute. 01157 * 01158 * @param theName name of attribute 01159 * @param theNewType type of attribute 01160 * @param theNewValue new value of attribute 01161 */ 01162 void 01163 replacePendingAttribute( 01164 const XalanDOMChar* theName, 01165 const XalanDOMChar* theNewType, 01166 const XalanDOMChar* theNewValue) 01167 { 01168 // Remove the old attribute, then add the new one. AttributeListImpl::addAttribute() 01169 // does this for us. 01170 getPendingAttributesImpl().addAttribute(theName, theNewType, theNewValue); 01171 } 01172 01173 bool 01174 isElementPending() const 01175 { 01176 return !getPendingElementNameImpl().empty(); 01177 } 01178 01179 /** 01180 * Retrieve name of the pending element currently being processed. 01181 * 01182 * @return element name 01183 */ 01184 const XalanDOMString& 01185 getPendingElementName() const 01186 { 01187 return getPendingElementNameImpl(); 01188 } 01189 01190 /** 01191 * Changes the currently pending element name. 01192 * 01193 * @param elementName new name of element 01194 */ 01195 void 01196 setPendingElementName(const XalanDOMString& elementName) 01197 { 01198 setPendingElementNameImpl(elementName); 01199 } 01200 01201 void 01202 setPendingElementName(const XalanDOMChar* elementName) 01203 { 01204 setPendingElementNameImpl(elementName); 01205 } 01206 01207 /** 01208 * Get the locator from the top of the locator stack. 01209 * 01210 * @return A pointer to the Locator, or 0 if there is nothing on the stack. 01211 */ 01212 const Locator* 01213 getLocatorFromStack() const 01214 { 01215 return m_stylesheetLocatorStack.empty() == true ? 0 : m_stylesheetLocatorStack.back(); 01216 } 01217 01218 /** 01219 * Push a locator on to the locator stack. 01220 * 01221 * @param A pointer to the Locator to push. 01222 */ 01223 void 01224 pushLocatorOnStack(const Locator* locator) 01225 { 01226 m_stylesheetLocatorStack.push_back(locator); 01227 } 01228 01229 /** 01230 * Pop the locator from the top of the locator stack. 01231 */ 01232 void 01233 popLocatorStack() 01234 { 01235 if (m_stylesheetLocatorStack.empty() == false) 01236 { 01237 m_stylesheetLocatorStack.pop_back(); 01238 } 01239 } 01240 01241 protected: 01242 01243 /** 01244 * Get the list of attributes yet to be processed 01245 * 01246 * @return attribute list 01247 */ 01248 const AttributeListImpl& 01249 getPendingAttributesImpl() const 01250 { 01251 return m_outputContextStack.getPendingAttributes(); 01252 } 01253 01254 /** 01255 * Get the list of attributes yet to be processed 01256 * 01257 * @return attribute list 01258 */ 01259 AttributeListImpl& 01260 getPendingAttributesImpl() 01261 { 01262 return m_outputContextStack.getPendingAttributes(); 01263 } 01264 01265 /** 01266 * Set the list of attributes yet to be processed 01267 * 01268 * @param pendingAttributes The attribute list 01269 */ 01270 void 01271 setPendingAttributesImpl(const AttributeListType& pendingAttributes) 01272 { 01273 getPendingAttributesImpl() = pendingAttributes; 01274 } 01275 01276 /** 01277 * Retrieve name of the pending element currently being processed. 01278 * 01279 * @return element name 01280 */ 01281 const XalanDOMString& 01282 getPendingElementNameImpl() const 01283 { 01284 return m_outputContextStack.getPendingElementName(); 01285 } 01286 01287 /** 01288 * Retrieve name of the pending element currently being processed. 01289 * 01290 * @return element name 01291 */ 01292 XalanDOMString& 01293 getPendingElementNameImpl() 01294 { 01295 return m_outputContextStack.getPendingElementName(); 01296 } 01297 01298 /** 01299 * Changes the currently pending element name. 01300 * 01301 * @param elementName new name of element 01302 */ 01303 void 01304 setPendingElementNameImpl(const XalanDOMString& elementName) 01305 { 01306 m_outputContextStack.getPendingElementName() = elementName; 01307 } 01308 01309 /** 01310 * Changes the currently pending element name. 01311 * 01312 * @param elementName new name of element 01313 */ 01314 void 01315 setPendingElementNameImpl(const XalanDOMChar* elementName) 01316 { 01317 assert(elementName != 0); 01318 01319 m_outputContextStack.getPendingElementName() = elementName; 01320 } 01321 01322 /* 01323 * See if there is a pending start document event waiting. 01324 * @return true if there is a start document event waiting. 01325 */ 01326 bool 01327 getHasPendingStartDocumentImpl() const 01328 { 01329 return m_outputContextStack.getHasPendingStartDocument(); 01330 } 01331 01332 /* 01333 * Set the pending start document event state. 01334 * @param the new value 01335 */ 01336 void 01337 setHasPendingStartDocumentImpl(bool b) 01338 { 01339 m_outputContextStack.getHasPendingStartDocument() = b; 01340 } 01341 01342 /* 01343 * See if a pending start document event must be flushed. 01344 * @return true if the event must be flushed. 01345 */ 01346 bool 01347 getMustFlushPendingStartDocumentImpl() const 01348 { 01349 return m_outputContextStack.getMustFlushPendingStartDocument(); 01350 } 01351 01352 /* 01353 * Set the pending start document event flush state. 01354 * @param the new value 01355 */ 01356 void 01357 setMustFlushPendingStartDocumentImpl(bool b) 01358 { 01359 m_outputContextStack.getMustFlushPendingStartDocument() = b; 01360 } 01361 01362 FormatterListener* 01363 getFormatterListenerImpl() const 01364 { 01365 return m_outputContextStack.getFormatterListener(); 01366 } 01367 01368 void 01369 setFormatterListenerImpl(FormatterListener* flistener) 01370 { 01371 m_outputContextStack.getFormatterListener() = flistener; 01372 } 01373 01374 /** 01375 * The namespace that the result tree conforms to. A null value 01376 * indicates that result-ns is not used and there is no checking. 01377 * A empty string indicates that the result tree conforms to the 01378 * default namespace. 01379 */ 01380 XalanDOMString m_resultNameSpacePrefix; 01381 01382 /** 01383 * The URL that belongs to the result namespace. 01384 */ 01385 XalanDOMString m_resultNameSpaceURL; 01386 01387 01388 /** 01389 * Copy the attributes from the XSL element to the created 01390 * output element. 01391 */ 01392 void 01393 copyAttributesToAttList( 01394 const XalanNode& node, 01395 AttributeListImpl& attList); 01396 01397 // Factory for creating xpaths. 01398 XPathFactory& m_xpathFactory; 01399 01400 // Factory for creating xobjects 01401 XObjectFactory& m_xobjectFactory; 01402 01403 // The query/pattern-matcher object. 01404 const XPathProcessorPtrType m_xpathProcessor; 01405 01406 /** 01407 * Stack of Booleans to keep track of if we should be outputting 01408 * cdata instead of escaped text. 01409 */ 01410 BoolVectorType m_cdataStack; 01411 01412 private: 01413 01414 /** 01415 * Issue a warning that only text nodes can be copied. 01416 * 01417 * @param sourceNode node in source where error occurred 01418 * @param locator The Locator to use, if any. 01419 */ 01420 void 01421 warnCopyTextNodesOnly( 01422 const XalanNode* sourceNode, 01423 const Locator* locator); 01424 01425 /** 01426 * Clone a text node to the result tree 01427 * 01428 * @param node node to clone 01429 * @param overrideStrip false if white space stripping should be done 01430 */ 01431 void 01432 cloneToResultTree( 01433 const XalanText& node, 01434 bool overrideStrip); 01435 01436 /** 01437 * Determine if any pending attributes is a default 01438 * namespace. 01439 */ 01440 bool 01441 pendingAttributesHasDefaultNS() const; 01442 01443 void 01444 addResultNamespace( 01445 const XalanDOMString& thePrefix, 01446 const XalanDOMString& theName, 01447 const XalanNode& theNode, 01448 AttributeListImpl& thePendingAttributes, 01449 bool fOnlyIfPrefixNotPresent); 01450 01451 void 01452 addResultNamespace( 01453 const XalanNode& theNode, 01454 AttributeListImpl& thePendingAttributes, 01455 bool fOnlyIfPrefixNotPresent = false); 01456 01457 /** 01458 * The top of this stack should contain the currently processed 01459 * stylesheet SAX locator object. 01460 */ 01461 LocatorStack m_stylesheetLocatorStack; 01462 01463 /** 01464 * The XSL class can have a single listener that can be informed 01465 * of errors and warnings, and can normally control if an exception 01466 * is thrown or not (or the problem listeners can throw their 01467 * own RuntimeExceptions). 01468 */ 01469 ProblemListenerDefault m_defaultProblemListener; 01470 01471 ProblemListener* m_problemListener; 01472 01473 /** 01474 * The root of a linked set of stylesheets. 01475 */ 01476 const StylesheetRoot* m_stylesheetRoot; 01477 01478 /** 01479 * The namespace that we must match as a minimum for XSLT. 01480 */ 01481 static const XalanDOMString& s_XSLNameSpaceURL; //"http://www.w3.org/1999/XSL/Transform" 01482 01483 /** 01484 * Special Xalan namespace for built-in extensions. 01485 */ 01486 static const XalanDOMString& s_XalanNamespaceURL; // "http://xml.apache.org/xalan" 01487 01488 /** 01489 * Prefix to use when generating unique namespaces. 01490 */ 01491 static const XalanDOMString& s_uniqueNamespacePrefix; 01492 01493 /** 01494 * If this is set to true, selects will be traced 01495 */ 01496 bool m_traceSelects; 01497 01498 /** 01499 * If this is set to true, do not warn about pattern 01500 * match conflicts. 01501 */ 01502 bool m_quietConflictWarnings; 01503 01504 /* 01505 * A stream to print diagnostics to. 01506 */ 01507 PrintWriter* m_diagnosticsPrintWriter; 01508 01509 /** 01510 * List of listeners who are interested in tracing what's 01511 * being generated. 01512 */ 01513 TraceListenerVectorType m_traceListeners; 01514 01515 void 01516 problem( 01517 const XalanDOMString& msg, 01518 ProblemListener::eClassification classification, 01519 const XalanNode* sourceNode, 01520 const ElemTemplateElement* styleNode) const; 01521 01522 void 01523 problem( 01524 const XalanDOMString& msg, 01525 ProblemListener::eClassification classification, 01526 const Locator& locator, 01527 const XalanNode* sourceNode) const; 01528 01529 void 01530 problem( 01531 const XalanDOMString& msg, 01532 ProblemListener::eClassification classification) const; 01533 01534 //========================================================== 01535 // SECTION: Function to do with attribute handling 01536 //========================================================== 01537 01538 /** 01539 * This is used whenever a unique namespace is needed. 01540 */ 01541 unsigned long m_uniqueNSValue; 01542 01543 ParamVectorType m_topLevelParams; 01544 01545 public: 01546 01547 /** 01548 * Reset the vector of top level parameters 01549 */ 01550 void 01551 clearTopLevelParams() 01552 { 01553 m_topLevelParams.clear(); 01554 } 01555 01556 private: 01557 01558 bool 01559 generateCDATASection() const 01560 { 01561 if (m_hasCDATASectionElements == false) 01562 { 01563 return false; 01564 } 01565 else 01566 { 01567 assert(m_cdataStack.empty() == false); 01568 01569 return m_cdataStack.back(); 01570 } 01571 } 01572 01573 void 01574 doFlushPending() 01575 { 01576 setMustFlushPendingStartDocument(true); 01577 01578 flushPending(); 01579 } 01580 01581 /** 01582 * Tell if a given element name should output its text 01583 * as cdata. 01584 * 01585 * @param elementName name of element 01586 * @return true if it should output as cdata 01587 */ 01588 bool 01589 isCDataResultElem(const XalanDOMString& elementName); 01590 01591 void 01592 fireCharacterGenerateEvent( 01593 const XalanNode& theNode, 01594 bool isCDATA); 01595 01596 void 01597 fireCharacterGenerateEvent( 01598 const XObjectPtr& theXObject, 01599 bool isCDATA); 01600 01601 void 01602 fireCharacterGenerateEvent( 01603 const XalanDOMString& theString, 01604 bool isCDATA); 01605 01606 void 01607 fireCharacterGenerateEvent( 01608 const XalanDOMChar* ch, 01609 size_type start, 01610 size_type length, 01611 bool isCDATA); 01612 01613 void 01614 checkDefaultNamespace( 01615 const XalanDOMString& theElementName, 01616 const XalanDOMString& theElementNamespaceURI); 01617 01618 void 01619 error( 01620 const XalanDOMString& theMessage, 01621 const Locator* theLocator, 01622 const XalanNode* theSourceNode); 01623 01624 void 01625 warn( 01626 const XalanDOMString& theMessage, 01627 const Locator* theLocator, 01628 const XalanNode* theSourceNode); 01629 01630 void 01631 message( 01632 const XalanDOMString& theMessage, 01633 const Locator* theLocator, 01634 const XalanNode* theSourceNode); 01635 01636 // Data members... 01637 XMLParserLiaison& m_parserLiaison; 01638 01639 XPathEnvSupport& m_xpathEnvSupport; 01640 01641 DOMSupport& m_domSupport; 01642 01643 /** 01644 * Current execution context... 01645 */ 01646 StylesheetExecutionContext* m_executionContext; 01647 01648 /* 01649 * Stack of current output contexts... 01650 */ 01651 OutputContextStack m_outputContextStack; 01652 01653 /* 01654 * Stack of current result namespaces... 01655 */ 01656 XalanNamespacesStack m_resultNamespacesStack; 01657 01658 /* 01659 * Dummy AttributeListImpl 01660 */ 01661 AttributeListImpl m_dummyAttributesList; 01662 01663 XalanDOMString m_scratchString; 01664 01665 XalanDOMStringPointerVectorType m_attributeNamesVisited; 01666 01667 bool m_hasCDATASectionElements; 01668 01669 XPathConstructionContextDefault m_xpathConstructionContext; 01670 01671 ParamMapType m_stylesheetParams; 01672 01673 static void 01674 installFunctions(MemoryManager& theManager); 01675 01676 static void 01677 uninstallFunctions(); 01678 01679 01680 static const XalanDOMString s_emptyString; 01681 01682 static const XalanDOMString& s_stylesheetNodeName; 01683 static const XalanDOMString& s_typeString; 01684 static const XalanDOMString& s_hrefString; 01685 static const XalanDOMString& s_piTokenizerString; 01686 static const XalanDOMString& s_typeValueString1; 01687 static const XalanDOMString& s_typeValueString2; 01688 static const XalanDOMString& s_typeValueString3; 01689 static const XalanDOMString& s_typeValueString4; 01690 01691 // Not implemented... 01692 XSLTEngineImpl(const XSLTEngineImpl&); 01693 01694 XSLTEngineImpl& 01695 operator=(const XSLTEngineImpl&); 01696 01697 bool 01698 operator==(const XSLTEngineImpl&) const; 01699 }; 01700 01701 01702 01703 XALAN_CPP_NAMESPACE_END 01704 01705 01706 01707 #endif // XALAN_XSLTENGINEIMPL_HEADER_GUARD
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.11 |
|