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 00019 #if !defined(XALAN_STYLESHEETHANDLER_HEADER_GUARD) 00020 #define XALAN_STYLESHEETHANDLER_HEADER_GUARD 00021 00022 // Base include file. Must be first. 00023 #include "XSLTDefinitions.hpp" 00024 00025 00026 00027 #include <xalanc/Include/XalanVector.hpp> 00028 #include <xalanc/Include/XalanSet.hpp> 00029 00030 00031 00032 #include <xalanc/XalanDOM/XalanDOMString.hpp> 00033 00034 00035 00036 #include <xalanc/PlatformSupport/FormatterListener.hpp> 00037 00038 00039 00040 #include <xalanc/XPath/XalanQNameByValue.hpp> 00041 00042 00043 00044 #include <xalanc/XSLT/NamespacesHandler.hpp> 00045 #include <xalanc/XSLT/Stylesheet.hpp> 00046 #include <xalanc/XSLT/XalanElemEmptyAllocator.hpp> 00047 #include <xalanc/XSLT/XalanElemTextAllocator.hpp> 00048 00049 00050 00051 XALAN_CPP_NAMESPACE_BEGIN 00052 00053 00054 00055 class ElemTemplate; 00056 class ElemTemplateElement; 00057 class ElemTextLiteral; 00058 class ExtensionNSHandler; 00059 class StylesheetConstructionContext; 00060 00061 00062 00063 /** 00064 * This class processes a stylesheet via SAX events, and inits 00065 * the given stylesheet. If you need to alter the code in here, 00066 * it is not for the faint-of-heart, due to the state tracking 00067 * that has to be done due to the SAX event model. 00068 */ 00069 class XALAN_XSLT_EXPORT StylesheetHandler : public FormatterListener 00070 { 00071 00072 public: 00073 00074 typedef XalanVector<ElemTemplateElement*> ElemTemplateStackType; 00075 typedef XalanVector<ElemTemplateElement*> ElemTextLiteralStackType; 00076 00077 typedef XalanVector<bool> BoolStackType; 00078 typedef XalanSet<XalanQNameByReference> QNameSetType; 00079 typedef XalanVector<QNameSetType, ConstructWithMemoryManagerTraits<QNameSetType> > 00080 QNameSetVectorType; 00081 00082 /** 00083 * Perform static initialization. See class XMLSupportInit. 00084 */ 00085 static void 00086 initialize(MemoryManager& theManager); 00087 00088 /** 00089 * Perform static shut down. See class XMLSupportInit. 00090 */ 00091 static void 00092 terminate(); 00093 00094 /** 00095 * Construct a StylesheetHandler ... it will add the DOM nodes 00096 * to the document fragment. 00097 */ 00098 StylesheetHandler( 00099 Stylesheet& stylesheetTree, 00100 StylesheetConstructionContext& constructionContext); 00101 00102 MemoryManager& 00103 getMemoryManager() 00104 { 00105 return m_constructionContext.getMemoryManager(); 00106 } 00107 00108 virtual 00109 ~StylesheetHandler(); 00110 00111 /** 00112 * Receive notification of character data. 00113 * 00114 * <p>The Parser will call this method to report each chunk of 00115 * character data. SAX parsers may return all contiguous character 00116 * data in a single chunk, or they may split it into several 00117 * chunks; however, all of the characters in any single event 00118 * must come from the same external entity, so that the Locator 00119 * provides useful information.</p> 00120 * 00121 * <p>The application must not attempt to read from the array 00122 * outside of the specified range.</p> 00123 * 00124 * <p>Note that some parsers will report whitespace using the 00125 * ignorableWhitespace() method rather than this one (validating 00126 * parsers must do so).</p> 00127 * 00128 * @param chars pointer to characters from the XML document 00129 * @param length number of characters to read from the array 00130 * @exception SAXException 00131 * @see #ignorableWhitespace 00132 * @see org.xml.sax.Locator 00133 */ 00134 virtual void 00135 characters( 00136 const XMLCh* const chars, 00137 const size_type length); 00138 00139 /** 00140 * Receive notification of character data. If available, when the 00141 * disable-output-escaping attribute is used, output raw text without 00142 * escaping. 00143 * 00144 * @param ch pointer to characters from the XML document 00145 * @param start start position in the array 00146 * @param length number of characters to read from the array 00147 * @exception SAXException 00148 */ 00149 virtual void 00150 charactersRaw( 00151 const XMLCh* const chars, 00152 const size_type length); 00153 00154 /** 00155 * Receive notification of cdata. 00156 * 00157 * <p>The Parser will call this method to report each chunk of 00158 * character data. SAX parsers may return all contiguous character 00159 * data in a single chunk, or they may split it into several 00160 * chunks; however, all of the characters in any single event 00161 * must come from the same external entity, so that the Locator 00162 * provides useful information.</p> 00163 * 00164 * <p>The application must not attempt to read from the array 00165 * outside of the specified range.</p> 00166 * 00167 * <p>Note that some parsers will report whitespace using the 00168 * ignorableWhitespace() method rather than this one (validating 00169 * parsers must do so).</p> 00170 * 00171 * @param ch pointer to characters from the XML document 00172 * @param start start position in the array 00173 * @param length number of characters to read from the array 00174 * @exception SAXException 00175 * @see #ignorableWhitespace 00176 */ 00177 virtual void 00178 cdata( 00179 const XMLCh* const ch, 00180 const size_type length); 00181 00182 /** 00183 * Receive notification of ignorable whitespace in element content. 00184 * 00185 * <p>Validating Parsers must use this method to report each chunk 00186 * of ignorable whitespace (see the W3C XML 1.0 recommendation, 00187 * section 2.10): non-validating parsers may also use this method 00188 * if they are capable of parsing and using content models.</p> 00189 * 00190 * <p>SAX parsers may return all contiguous whitespace in a single 00191 * chunk, or they may split it into several chunks; however, all of 00192 * the characters in any single event must come from the same 00193 * external entity, so that the Locator provides useful 00194 * information.</p> 00195 * 00196 * <p>The application must not attempt to read from the array 00197 * outside of the specified range.</p> 00198 * 00199 * @param chars characters from the XML document 00200 * @param start start position in the array 00201 * @param length number of characters to read from the array 00202 * @exception SAXException 00203 * @see #characters 00204 */ 00205 virtual void 00206 ignorableWhitespace( 00207 const XMLCh* const chars, 00208 const size_type length); 00209 00210 /** 00211 * Receive notification of a processing instruction. 00212 * 00213 * <p>The Parser will invoke this method once for each processing 00214 * instruction found: note that processing instructions may occur 00215 * before or after the main document element.</p> 00216 * 00217 * <p>A SAX parser should never report an XML declaration (XML 1.0, 00218 * section 2.8) or a text declaration (XML 1.0, section 4.3.1) 00219 * using this method.</p> 00220 * 00221 * @param target pointer to processing instruction target 00222 * @param data pointer to processing instruction data, or null if none 00223 * was supplied 00224 * @exception SAXException 00225 */ 00226 virtual void processingInstruction (const XMLCh* const target, const XMLCh* const data); 00227 00228 /** 00229 * Called when a Comment is to be constructed. 00230 * 00231 * @param data comment data 00232 * @exception SAXException 00233 */ 00234 virtual void comment(const XMLCh* const data); 00235 00236 /** 00237 * Receive notification of a entityReference. 00238 * 00239 * @param data pointer to characters from the XML document 00240 * @exception SAXException 00241 */ 00242 virtual void entityReference(const XMLCh* const data); 00243 00244 // These methods are inherited DocumentHandler ... 00245 00246 // $$$ Theoretically, shouldn't need javadoc for these, since they are 00247 // inherited from DocumentHandler, but let's leave them in for now -- JMD 00248 00249 /** 00250 * Receive an object for locating the origin of SAX document events. 00251 * 00252 * <p>SAX parsers are strongly encouraged (though not absolutely 00253 * required) to supply a locator: if it does so, it must supply 00254 * the locator to the application by invoking this method before 00255 * invoking any of the other methods in the DocumentHandler 00256 * interface.</p> 00257 * 00258 * <p>The locator allows the application to determine the end 00259 * position of any document-related event, even if the parser is 00260 * not reporting an error. Typically, the application will 00261 * use this information for reporting its own errors (such as 00262 * character content that does not match an application's 00263 * business rules). The information returned by the locator 00264 * is probably not sufficient for use with a search engine.</p> 00265 * 00266 * <p>Note that the locator will return correct information only 00267 * during the invocation of the events in this interface. The 00268 * application should not attempt to use it at any other time.</p> 00269 * 00270 * @param locator object that can return the location of 00271 * any SAX document event. 00272 * @see org.xml.sax.Locator 00273 */ 00274 virtual void setDocumentLocator(const Locator* const locator); 00275 00276 /** 00277 * Receive notification of the beginning of a document. 00278 * 00279 * <p>The SAX parser will invoke this method only once, before any 00280 * other methods in this interface or in DTDHandler (except for 00281 * setDocumentLocator).</p> 00282 * 00283 * @exception SAXException 00284 */ 00285 virtual void startDocument(); 00286 00287 /** 00288 * Receive notification of the end of a document. 00289 * 00290 * <p>The SAX parser will invoke this method only once, and it will 00291 * be the last method invoked during the parse. The parser shall 00292 * not invoke this method until it has either abandoned parsing 00293 * (because of an unrecoverable error) or reached the end of 00294 * input.</p> 00295 * 00296 * @exception SAXException 00297 */ 00298 virtual void endDocument(); 00299 00300 /** 00301 * Receive notification of the beginning of an element. 00302 * 00303 * <p>The Parser will invoke this method at the beginning of every 00304 * element in the XML document; there will be a corresponding 00305 * endElement() event for every startElement() event (even when the 00306 * element is empty). All of the element's content will be 00307 * reported, in order, before the corresponding endElement() 00308 * event.</p> 00309 * 00310 * <p>If the element name has a namespace prefix, the prefix will 00311 * still be attached. Note that the attribute list provided will 00312 * contain only attributes with explicit values (specified or 00313 * defaulted): #IMPLIED attributes will be omitted.</p> 00314 * 00315 * @param name element type name 00316 * @param atts attributes attached to the element, if any 00317 * @exception SAXException 00318 * @see #endElement 00319 * @see org.xml.sax.AttributeList 00320 */ 00321 virtual void startElement(const XMLCh* const name, AttributeListType& attrs); 00322 00323 /** 00324 * Receive notification of the end of an element. 00325 * 00326 * <p>The SAX parser will invoke this method at the end of every 00327 * element in the XML document; there will be a corresponding 00328 * startElement() event for every endElement() event (even when the 00329 * element is empty).</p> 00330 * 00331 * <p>If the element name has a namespace prefix, the prefix will 00332 * still be attached to the name.</p> 00333 * 00334 * @param name element type name 00335 * @exception SAXException 00336 */ 00337 virtual void endElement(const XMLCh* const name); 00338 00339 /** 00340 * This method allows the user installed Document Handler to 'reset' 00341 * itself, freeing all the memory resources. The scanner calls this 00342 * method before starting a new parse event. 00343 */ 00344 virtual void resetDocument(); 00345 00346 protected: 00347 00348 /** 00349 * See if this is a xmlns attribute, and, if so, process it. 00350 * 00351 * @param attrName Qualified name of attribute. 00352 * @param atts The attribute list where the element comes from (not used at 00353 * this time). 00354 * @param which The index into the attribute list (not used at this time). 00355 * @return True if this is a namespace name. 00356 */ 00357 bool 00358 isAttrOK( 00359 const XalanDOMChar* attrName, 00360 const AttributeListType& atts, 00361 XalanSize_t which); 00362 00363 /** 00364 * Tell whether or not this is a xml:space attribute and, if so, process it. 00365 * 00366 * @param elementName The name of the element that owns the attribute 00367 * @param aname The name of the attribute in question. 00368 * @param atts The attribute list that owns the attribute. 00369 * @param which The index of the attribute into the attribute list. 00370 * @param locator A Locator instance for error reporting. 00371 * @param fPreserve set to true if the attribute value is "preserve" 00372 * @return True if this is a xml:space attribute. 00373 */ 00374 bool 00375 processSpaceAttr( 00376 const XalanDOMChar* elementName, 00377 const XalanDOMChar* aname, 00378 const AttributeListType& atts, 00379 XalanSize_t which, 00380 const Locator* locator, 00381 bool& fPreserve); 00382 00383 /** 00384 * Tell whether or not this is a xml:space attribute and, if so, process it. 00385 * 00386 * @param elementName The name of the element that owns the attributes 00387 * @param atts The attribute list that owns the attribute. 00388 * @param locator A Locator instance for error reporting. 00389 * @param fPreserve set to true if an xml:space attribute value is "preserve" 00390 * @return True if this is a xml:space attribute. 00391 */ 00392 bool 00393 processSpaceAttr( 00394 const XalanDOMChar* elementName, 00395 const AttributeListType& atts, 00396 const Locator* locator, 00397 bool& fPreserve); 00398 00399 /** 00400 * Process xsl:import. 00401 */ 00402 void 00403 processImport( 00404 const XalanDOMChar* name, 00405 const AttributeListType& atts, 00406 const Locator* locator); 00407 00408 /** 00409 * Process xsl:include. 00410 */ 00411 void 00412 processInclude( 00413 const XalanDOMChar* name, 00414 const AttributeListType& atts, 00415 const Locator* locator); 00416 00417 void 00418 doCleanup(); 00419 00420 private: 00421 00422 enum { eElemEmptyAllocatorBlockSize = 10, eElemTextBlockSize = 10 }; 00423 00424 // not implemented 00425 StylesheetHandler(const StylesheetHandler&); 00426 00427 StylesheetHandler& 00428 operator=(const StylesheetHandler&); 00429 00430 // Utility functions... 00431 void 00432 illegalAttributeError( 00433 const XalanDOMChar* theElementName, 00434 const XalanDOMChar* theAttributeName, 00435 const Locator* theLocator) const; 00436 00437 void 00438 error( 00439 const XalanDOMChar* theMessage1, 00440 const XalanDOMChar* theMessage2, 00441 const Locator* theLocator) const; 00442 00443 void 00444 error( 00445 const XalanDOMChar* theMessage1, 00446 const XalanDOMString& theMessage2, 00447 const Locator* theLocator) const; 00448 00449 void 00450 error( 00451 const XalanDOMString& theMessage1, 00452 const XalanDOMChar* theMessage2, 00453 const Locator* theLocator) const; 00454 00455 void 00456 error( 00457 const XalanDOMString& theMessage1, 00458 const XalanDOMString& theMessage2, 00459 const Locator* theLocator) const; 00460 00461 void 00462 warn( 00463 const XalanDOMChar* theMessage1, 00464 const XalanDOMChar* theMessage2, 00465 const Locator* theLocator) const; 00466 00467 void 00468 warn( 00469 const XalanDOMChar* theMessage1, 00470 const XalanDOMString& theMessage2, 00471 const Locator* theLocator) const; 00472 void 00473 warn( 00474 const XalanDOMString& theMessage, 00475 const Locator* theLocator) const; 00476 00477 void 00478 error( 00479 const XalanDOMString& theMessage, 00480 const Locator* theLocator) const; 00481 00482 void 00483 processText( 00484 const XMLCh* chars, 00485 size_type length); 00486 00487 void 00488 accumulateText( 00489 const XMLCh* chars, 00490 size_type length); 00491 00492 void 00493 processAccumulatedText(); 00494 00495 void 00496 processTopLevelElement( 00497 const XalanDOMChar* name, 00498 const AttributeListType& atts, 00499 int xslToken, 00500 const Locator* locator, 00501 bool& fPreserveSpace, 00502 bool& fSpaceAttrProcessed); 00503 00504 void 00505 processStylesheet( 00506 const XalanDOMChar* name, 00507 const AttributeListType& atts, 00508 const Locator* locator, 00509 bool& fPreserveSpace, 00510 bool& fSpaceAttrProcessed); 00511 00512 void 00513 processPreserveStripSpace( 00514 const XalanDOMChar* name, 00515 const AttributeListType& atts, 00516 const Locator* locator, 00517 int xslToken); 00518 00519 void 00520 appendChildElementToParent( 00521 ElemTemplateElement* elem, 00522 const Locator* locator); 00523 00524 void 00525 appendChildElementToParent( 00526 ElemTemplateElement* parent, 00527 ElemTemplateElement* elem); 00528 00529 void 00530 appendChildElementToParent( 00531 ElemTemplateElement* parent, 00532 ElemTemplateElement* elem, 00533 const Locator* locator); 00534 00535 bool 00536 inExtensionElement() const; 00537 00538 void 00539 processExtensionElement( 00540 const XalanDOMChar* name, 00541 const XalanDOMString& localName, 00542 const AttributeListType& atts, 00543 const Locator* locator); 00544 00545 void 00546 checkForOrAddVariableName( 00547 const XalanQName& theVariableName, 00548 const Locator* theLocator); 00549 00550 // Data members... 00551 00552 /** 00553 * The owning stylesheet. 00554 */ 00555 Stylesheet& m_stylesheet; 00556 00557 /** 00558 * The construction context. 00559 */ 00560 StylesheetConstructionContext& m_constructionContext; 00561 00562 /** 00563 * An allocator for ElemEmpty instances. 00564 */ 00565 XalanElemEmptyAllocator m_elemEmptyAllocator; 00566 00567 /** 00568 * An allocator for ElemText instances. 00569 */ 00570 XalanElemTextAllocator m_elemTextAllocator; 00571 00572 /** 00573 * The stack of elements, pushed and popped as events occur. 00574 */ 00575 ElemTemplateStackType m_elemStack; 00576 00577 /** 00578 * Need to keep a stack of found whitespace elements so that 00579 * whitespace elements next to non-whitespace elements can 00580 * be merged. For instance: <out> <![CDATA[test]]> </out> 00581 */ 00582 ElemTextLiteralStackType m_whiteSpaceElems; 00583 00584 /** 00585 * The current template. 00586 */ 00587 ElemTemplateElement* m_pTemplate; 00588 00589 class LastPoppedHolder 00590 { 00591 public: 00592 00593 LastPoppedHolder(StylesheetHandler& theStylesheetHandler) : 00594 m_stylesheetHandler(theStylesheetHandler), 00595 m_lastPopped(0) 00596 { 00597 } 00598 00599 ~LastPoppedHolder() 00600 { 00601 cleanup(); 00602 } 00603 00604 ElemTemplateElement* 00605 operator->() const 00606 { 00607 return m_lastPopped; 00608 } 00609 00610 bool 00611 operator==(ElemTemplateElement* theRHS) 00612 { 00613 return m_lastPopped == theRHS; 00614 } 00615 00616 bool 00617 operator!=(ElemTemplateElement* theRHS) 00618 { 00619 return m_lastPopped != theRHS; 00620 } 00621 00622 void 00623 operator=(ElemTemplateElement* theRHS) 00624 { 00625 if (theRHS != m_lastPopped) 00626 { 00627 cleanup(); 00628 00629 m_lastPopped = theRHS; 00630 } 00631 } 00632 00633 void 00634 swap(LastPoppedHolder& theOther) 00635 { 00636 ElemTemplateElement* const theTemp = m_lastPopped; 00637 00638 m_lastPopped = theOther.m_lastPopped; 00639 00640 theOther.m_lastPopped = theTemp; 00641 } 00642 00643 ElemTemplateElement* 00644 get() const 00645 { 00646 return m_lastPopped; 00647 } 00648 00649 private: 00650 00651 void 00652 set(ElemTemplateElement* theNewElement) 00653 { 00654 if (theNewElement != m_lastPopped) 00655 { 00656 cleanup(); 00657 00658 m_lastPopped = theNewElement; 00659 } 00660 } 00661 00662 // Not implemented... 00663 LastPoppedHolder& 00664 operator=(const LastPoppedHolder&); 00665 00666 LastPoppedHolder(const LastPoppedHolder&); 00667 00668 // Helper functions... 00669 void 00670 cleanup(); 00671 00672 // Data members... 00673 StylesheetHandler& m_stylesheetHandler; 00674 00675 ElemTemplateElement* m_lastPopped; 00676 }; 00677 00678 friend class LastPoppedHolder; 00679 00680 /** 00681 * Manages the last element popped from the stack. 00682 */ 00683 LastPoppedHolder m_lastPopped; 00684 00685 /** 00686 * True if the process is in a template context. 00687 */ 00688 bool m_inTemplate; 00689 00690 /** 00691 * True if the stylesheet element was found, or if it was determined that 00692 * the stylesheet is wrapperless. 00693 */ 00694 bool m_foundStylesheet; 00695 00696 /** 00697 * Flag to let us know when we've found an element inside the 00698 * stylesheet that is not an xsl:import, so we can restrict imports 00699 * to being the first elements. 00700 */ 00701 bool m_foundNotImport; 00702 00703 XalanDOMString m_elementLocalName; 00704 00705 /** 00706 * Accumulate character buffer to create contiguous character data 00707 * where possible. 00708 */ 00709 XalanDOMString m_accumulateText; 00710 00711 XalanDOMString m_includeBase; 00712 00713 BoolStackType m_inExtensionElementStack; 00714 00715 BoolStackType m_preserveSpaceStack; 00716 00717 // Note that these variables must not be saved by 00718 // PushPopIncludeState... 00719 unsigned long m_locatorsPushed; 00720 00721 QNameSetType m_globalVariableNames; 00722 00723 enum { eVariablesStackDefault = 20 }; 00724 00725 QNameSetVectorType m_inScopeVariableNamesStack; 00726 00727 /** 00728 * Init the wrapperless template 00729 */ 00730 ElemTemplateElement* 00731 initWrapperless( 00732 const XalanDOMChar* name, 00733 const AttributeListType& atts, 00734 const Locator* locator); 00735 00736 const XalanDOMString* 00737 getNamespaceFromStack(const XalanDOMChar* theName, 00738 XalanDOMString& theBuffer) const; 00739 00740 const XalanDOMString* 00741 getNamespaceForPrefixFromStack(const XalanDOMString& thePrefix) const; 00742 00743 class PushPopIncludeState; 00744 00745 friend class StylesheetHandler::PushPopIncludeState; 00746 00747 class PushPopIncludeState 00748 { 00749 public: 00750 00751 PushPopIncludeState(StylesheetHandler& theHandler); 00752 00753 ~PushPopIncludeState(); 00754 00755 private: 00756 00757 StylesheetHandler& m_handler; 00758 00759 ElemTemplateStackType m_elemStack; 00760 00761 ElemTemplateElement* const m_pTemplate; 00762 00763 LastPoppedHolder m_lastPopped; 00764 00765 const bool m_inTemplate; 00766 00767 const bool m_foundStylesheet; 00768 00769 const XalanDOMString m_XSLNameSpaceURL; 00770 00771 const bool m_foundNotImport; 00772 00773 Stylesheet::NamespaceVectorType m_namespaceDecls; 00774 00775 Stylesheet::NamespacesStackType m_namespaces; 00776 00777 NamespacesHandler m_namespacesHandler; 00778 00779 BoolStackType m_inExtensionElementStack; 00780 00781 BoolStackType m_preserveSpaceStack; 00782 }; 00783 00784 static const XalanDOMString s_emptyString; 00785 }; 00786 00787 00788 00789 XALAN_CPP_NAMESPACE_END 00790 00791 00792 00793 #endif // XALAN_STYLESHEETHANDLER_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 |
|