| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #if !defined(XALANXMLSERIALIZERBASE_HEADER_GUARD_1357924680) |
| #define XALANXMLSERIALIZERBASE_HEADER_GUARD_1357924680 |
| |
| |
| |
| |
| // Base include file. Must be first. |
| #include "xalanc/XMLSupport/XMLSupportDefinitions.hpp" |
| |
| |
| |
| #include "xalanc/Include/XalanVector.hpp" |
| |
| |
| |
| #include "xalanc/XalanDOM/XalanDOMString.hpp" |
| |
| |
| |
| // Base class header file. |
| #include "xalanc/PlatformSupport/FormatterListener.hpp" |
| |
| |
| |
| namespace XALAN_CPP_NAMESPACE { |
| |
| |
| |
| class XalanOutputStream; |
| |
| |
| |
| using xercesc::MemoryManager; |
| |
| |
| |
| /** |
| * XalanXMLSerializerBase serves as a base class for XML serializers based on |
| * FormatterListener events. |
| */ |
| class XALAN_XMLSUPPORT_EXPORT XalanXMLSerializerBase : public FormatterListener |
| { |
| public: |
| |
| /** |
| * Perform static initialization. See class XMLSupportInit. |
| */ |
| static void |
| initialize(MemoryManager& theManager); |
| |
| /** |
| * Perform static shut down. See class XMLSupportInit. |
| */ |
| static void |
| terminate(); |
| |
| |
| /** |
| * Constructor |
| * |
| * @param theManager The MemoryManager instance to use for any memory |
| * allocations |
| * @param doctypeSystem system identifier to be used in the document |
| * type declaration |
| * @param doctypePublic public identifier to be used in the document |
| * type declaration |
| * @param xmlDecl true if the XSLT processor should output an XML |
| * declaration |
| * @param theStandalone The string the XSLT processor should output for |
| * the standalone document declaration |
| */ |
| XalanXMLSerializerBase( |
| MemoryManager& theManager, |
| eXMLVersion theXMLVersion, |
| const XalanDOMString& theEncoding, |
| const XalanDOMString& theDoctypeSystem, |
| const XalanDOMString& theDoctypePublic, |
| bool xmlDecl, |
| const XalanDOMString& theStandalone); |
| |
| virtual |
| ~XalanXMLSerializerBase(); |
| |
| MemoryManager& |
| getMemoryManager() |
| { |
| return m_elemStack.getMemoryManager(); |
| } |
| |
| |
| // These methods are inherited from FormatterListener ... |
| |
| virtual void |
| setDocumentLocator(const Locator* const locator); |
| |
| virtual void |
| startDocument(); |
| |
| virtual void |
| startElement( |
| const XMLCh* const name, |
| AttributeList& attrs) = 0; |
| |
| virtual void |
| endElement(const XMLCh* const name) = 0; |
| |
| virtual void |
| characters( |
| const XMLCh* const chars, |
| const size_type length); |
| |
| virtual void |
| charactersRaw( |
| const XMLCh* const chars, |
| const size_type length) = 0; |
| |
| virtual void |
| entityReference(const XMLCh* const name) = 0; |
| |
| virtual void |
| ignorableWhitespace( |
| const XMLCh* const chars, |
| const size_type length); |
| |
| virtual void |
| processingInstruction( |
| const XMLCh* const target, |
| const XMLCh* const data); |
| |
| virtual void |
| resetDocument(); |
| |
| virtual void |
| comment(const XMLCh* const data) = 0; |
| |
| virtual void |
| cdata( |
| const XMLCh* const ch, |
| const size_type length); |
| |
| virtual const XalanDOMString& |
| getDoctypeSystem() const; |
| |
| virtual const XalanDOMString& |
| getDoctypePublic() const; |
| |
| virtual const XalanDOMString& |
| getEncoding() const; |
| |
| const XalanDOMString& |
| getVersion() const |
| { |
| return m_version; |
| } |
| |
| const XalanDOMString& |
| getStandalone() const |
| { |
| return m_standalone; |
| } |
| |
| bool |
| getShouldWriteXMLHeader() const |
| { |
| return m_shouldWriteXMLHeader; |
| } |
| |
| void |
| setShouldWriteXMLHeader(bool b) |
| { |
| m_shouldWriteXMLHeader = b; |
| } |
| |
| typedef XalanVector<bool> BoolStackType; |
| |
| |
| static const XalanDOMString& s_1_0String; |
| |
| static const XalanDOMString& s_1_1String; |
| |
| |
| class XALAN_XMLSUPPORT_EXPORT UTF8 |
| { |
| public: |
| |
| // Static data members... |
| /** |
| * The string "UTF-8". |
| */ |
| static const XalanDOMString& s_encodingString; |
| |
| /** |
| * The string "<!DOCTYPE ". |
| */ |
| static const char s_doctypeHeaderStartString[]; |
| |
| static const size_type s_doctypeHeaderStartStringLength; |
| |
| /** |
| * The string " PUBLIC \"". |
| */ |
| static const char s_doctypeHeaderPublicString[]; |
| |
| static const size_type s_doctypeHeaderPublicStringLength; |
| |
| /** |
| * The string " SYSTEM \"". |
| */ |
| static const char s_doctypeHeaderSystemString[]; |
| |
| static const size_type s_doctypeHeaderSystemStringLength; |
| |
| /** |
| * The string "<?xml version=\"". |
| */ |
| static const char s_xmlHeaderStartString[]; |
| |
| static const size_type s_xmlHeaderStartStringLength; |
| |
| /** |
| * The string "\" encoding=\"". |
| */ |
| static const char s_xmlHeaderEncodingString[]; |
| |
| static const size_type s_xmlHeaderEncodingStringLength; |
| |
| /** |
| * The string "\" standalone=\"". |
| */ |
| static const char s_xmlHeaderStandaloneString[]; |
| |
| static const size_type s_xmlHeaderStandaloneStringLength; |
| |
| /** |
| * The string "\"?>". |
| */ |
| static const char s_xmlHeaderEndString[]; |
| |
| static const size_type s_xmlHeaderEndStringLength; |
| |
| /** |
| * The string "1.0". |
| */ |
| static const char s_defaultVersionString[]; |
| |
| static const size_type s_defaultVersionStringLength; |
| |
| /** |
| * The string "-//W3C//DTD XHTML". |
| */ |
| static const XalanDOMChar s_xhtmlDocTypeString[]; |
| |
| static const size_type s_xhtmlDocTypeStringLength; |
| |
| /** |
| * The string "<![CDATA[". |
| */ |
| static const char s_cdataOpenString[]; |
| |
| static const size_type s_cdataOpenStringLength; |
| |
| /** |
| * The string "]]>". |
| */ |
| static const char s_cdataCloseString[]; |
| |
| static const size_type s_cdataCloseStringLength; |
| |
| /** |
| * The string "<". |
| */ |
| static const char s_lessThanEntityString[]; |
| |
| static const size_type s_lessThanEntityStringLength; |
| |
| /** |
| * The string ">". |
| */ |
| static const char s_greaterThanEntityString[]; |
| |
| static const size_type s_greaterThanEntityStringLength; |
| |
| /** |
| * The string "&". |
| */ |
| static const char s_ampersandEntityString[]; |
| |
| static const size_type s_ampersandEntityStringLength; |
| |
| /** |
| * The string """. |
| */ |
| static const char s_quoteEntityString[]; |
| |
| static const size_type s_quoteEntityStringLength; |
| }; |
| |
| class XALAN_XMLSUPPORT_EXPORT UTF16 |
| { |
| public: |
| |
| /** |
| * The string "UTF-16". |
| */ |
| static const XalanDOMString& s_encodingString; |
| |
| /** |
| * The string "<!DOCTYPE ". |
| */ |
| static const XalanDOMChar s_doctypeHeaderStartString[]; |
| |
| static const size_type s_doctypeHeaderStartStringLength; |
| |
| /** |
| * The string " PUBLIC \"". |
| */ |
| static const XalanDOMChar s_doctypeHeaderPublicString[]; |
| |
| static const size_type s_doctypeHeaderPublicStringLength; |
| |
| /** |
| * The string " SYSTEM \"". |
| */ |
| static const XalanDOMChar s_doctypeHeaderSystemString[]; |
| |
| static const size_type s_doctypeHeaderSystemStringLength; |
| |
| /** |
| * The string "<?xml version=\"". |
| */ |
| static const XalanDOMChar s_xmlHeaderStartString[]; |
| |
| static const size_type s_xmlHeaderStartStringLength; |
| |
| /** |
| * The string "\" encoding=\"". |
| */ |
| static const XalanDOMChar s_xmlHeaderEncodingString[]; |
| |
| static const size_type s_xmlHeaderEncodingStringLength; |
| |
| /** |
| * The string "\" standalone=\"". |
| */ |
| static const XalanDOMChar s_xmlHeaderStandaloneString[]; |
| |
| static const size_type s_xmlHeaderStandaloneStringLength; |
| |
| /** |
| * The string "\"?>". |
| */ |
| static const XalanDOMChar s_xmlHeaderEndString[]; |
| |
| static const size_type s_xmlHeaderEndStringLength; |
| |
| /** |
| * The string "1.0". |
| */ |
| static const XalanDOMChar s_defaultVersionString[]; |
| |
| static const size_type s_defaultVersionStringLength; |
| |
| /** |
| * The string "-//W3C//DTD XHTML". |
| */ |
| static const XalanDOMChar s_xhtmlDocTypeString[]; |
| |
| static const size_type s_xhtmlDocTypeStringLength; |
| |
| /** |
| * The string "<![CDATA[". |
| */ |
| static const XalanDOMChar s_cdataOpenString[]; |
| |
| static const size_type s_cdataOpenStringLength; |
| |
| /** |
| * The string "]]>". |
| */ |
| static const XalanDOMChar s_cdataCloseString[]; |
| |
| static const size_type s_cdataCloseStringLength; |
| |
| /** |
| * The string "<". |
| */ |
| static const XalanDOMChar s_lessThanEntityString[]; |
| |
| static const size_type s_lessThanEntityStringLength; |
| |
| /** |
| * The string ">". |
| */ |
| static const XalanDOMChar s_greaterThanEntityString[]; |
| |
| static const size_type s_greaterThanEntityStringLength; |
| |
| /** |
| * The string "&". |
| */ |
| static const XalanDOMChar s_ampersandEntityString[]; |
| |
| static const size_type s_ampersandEntityStringLength; |
| |
| /** |
| * The string """. |
| */ |
| static const XalanDOMChar s_quoteEntityString[]; |
| |
| static const size_type s_quoteEntityStringLength; |
| }; |
| |
| enum |
| { |
| eBufferSize = 512 // The size of the buffer |
| }; |
| |
| class XALAN_XMLSUPPORT_EXPORT CharFunctor1_0 |
| { |
| public: |
| |
| bool |
| attribute(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] > eNone; |
| } |
| |
| bool |
| content(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] > eAttr; |
| } |
| |
| bool |
| range(XalanDOMChar theChar) const |
| { |
| assert(theChar > 0); |
| |
| return theChar > s_lastSpecial; |
| } |
| |
| bool |
| isForbidden(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] == eForb; |
| } |
| |
| bool |
| isCharRefForbidden(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] == eForb; |
| } |
| |
| |
| private: |
| static const size_t s_lastSpecial; |
| |
| static const char s_specialChars[]; |
| }; |
| |
| |
| |
| class XALAN_XMLSUPPORT_EXPORT CharFunctor1_1 |
| { |
| public: |
| |
| bool |
| attribute(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] > eNone; |
| } |
| |
| bool |
| content(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] > eAttr; |
| } |
| |
| bool |
| range(XalanDOMChar theChar) const |
| { |
| assert(theChar > 0); |
| |
| return theChar > s_lastSpecial; |
| } |
| |
| bool |
| isForbidden(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] == eForb; |
| } |
| |
| bool |
| isCharRefForbidden(XalanDOMChar theChar) const |
| { |
| return theChar > s_lastSpecial ? |
| false : |
| s_specialChars[theChar] == eCRFb; |
| } |
| |
| private: |
| static const size_t s_lastSpecial; |
| |
| static const char s_specialChars[]; |
| |
| }; |
| |
| |
| |
| |
| enum |
| { |
| eNone = 0u, |
| eAttr = 1u, // A flag to indicate a value in s_specialChars applies to attributes |
| eBoth = 2u, // A flag to indicate a value in s_specialChars applies to both content and attributes |
| eForb = 4u, // A flag to indicate a forbidden value in s_specialChars |
| // XML1.1 put a requirement to output chars #x1...#x1F and #x7F...#x9F as charRefs only |
| // In the comments , PI and CDATA usage of charRefs is forbidden, so we will report an error in |
| eCRFb = 5u // that case. For the elemets and attributes is should work the same as eBoth |
| }; |
| |
| |
| |
| protected: |
| |
| virtual void |
| writeXMLHeader() = 0; |
| |
| virtual void |
| flushBuffer() = 0; |
| |
| virtual void |
| writeDoctypeDecl(const XalanDOMChar* name) = 0; |
| |
| virtual void |
| writeProcessingInstruction( |
| const XMLCh* target, |
| const XMLCh* data) = 0; |
| |
| virtual void |
| writeCharacters( |
| const XMLCh* chars, |
| size_type length) = 0; |
| |
| virtual void |
| writeCDATA( |
| const XMLCh* chars, |
| size_type length) = 0; |
| |
| virtual void |
| outputNewline() = 0; |
| |
| /** |
| * Mark the parent element as having a child. If this |
| * is the first child, return true, otherwise, return |
| * false. This allows the child element to determine |
| * if the parent tag has already been closed. |
| * |
| * @return true if the parent element has not been previously marked for children. |
| */ |
| bool |
| markParentForChildren() |
| { |
| if(!m_elemStack.empty()) |
| { |
| // See if the parent element has already been flagged as having children. |
| if(false == m_elemStack.back()) |
| { |
| m_elemStack.back() = true; |
| |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Determine if it a DOCTYPE declaration needs to |
| * be written. |
| */ |
| bool |
| getNeedToOutputDoctypeDecl() const |
| { |
| return m_needToOutputDoctypeDecl; |
| } |
| |
| /** |
| * Open an element for possibile children |
| */ |
| void |
| openElementForChildren() |
| { |
| m_elemStack.push_back(false); |
| } |
| |
| bool |
| outsideDocumentElement() const |
| { |
| return m_elemStack.empty(); |
| } |
| |
| /** |
| * Determine if an element ever had any children added. |
| * |
| * @return true if the children were added, false if not. |
| */ |
| bool |
| childNodesWereAdded() |
| { |
| bool fResult = false; |
| |
| if (m_elemStack.empty() == false) |
| { |
| fResult = m_elemStack.back(); |
| |
| m_elemStack.pop_back(); |
| } |
| |
| return fResult; |
| } |
| |
| void |
| generateDoctypeDecl(const XalanDOMChar* name) |
| { |
| if(true == m_needToOutputDoctypeDecl) |
| { |
| assert(m_doctypeSystem.empty() == false); |
| |
| writeDoctypeDecl(name); |
| |
| m_needToOutputDoctypeDecl = false; |
| } |
| } |
| |
| /** |
| * Tell if the next text should be raw. |
| */ |
| bool m_nextIsRaw; |
| |
| /** |
| * Add space before '/>' for XHTML. |
| */ |
| bool m_spaceBeforeClose; |
| |
| /** |
| * The System ID for the doc type. |
| */ |
| const XalanDOMString m_doctypeSystem; |
| |
| /** |
| * The public ID for the doc type. |
| */ |
| const XalanDOMString m_doctypePublic; |
| |
| /** |
| * Tells the XML version, for writing out to the XML decl. |
| */ |
| const XalanDOMString& m_version; |
| |
| /** |
| * Text for standalone part of header. |
| */ |
| const XalanDOMString m_standalone; |
| |
| const XalanDOMString m_encoding; |
| |
| static bool |
| isUTF16HighSurrogate(XalanDOMChar theChar) |
| { |
| return 0xD800u <= theChar && theChar <= 0xDBFFu ? true : false; |
| } |
| |
| static bool |
| isUTF16LowSurrogate(XalanDOMChar theChar) |
| { |
| return 0xDC00u <= theChar && theChar <= 0xDFFFu ? true : false; |
| } |
| |
| static XalanUnicodeChar |
| decodeUTF16SurrogatePair( |
| XalanDOMChar theHighSurrogate, |
| XalanDOMChar theLowSurrogate, |
| MemoryManager& theManager); |
| |
| /** |
| * Throw an exception when an invalid |
| * surrogate is encountered. |
| * @param ch The first character in the surrogate |
| */ |
| static void |
| throwInvalidUTF16SurrogateException( |
| XalanDOMChar ch, |
| MemoryManager& theManager); |
| |
| /** |
| * Throw an exception when an invalid |
| * surrogate is encountered. |
| * @param ch The first character in the surrogate |
| * @param next The next character in the surrogate |
| */ |
| static void |
| throwInvalidUTF16SurrogateException( |
| XalanDOMChar ch, |
| XalanDOMChar next, |
| MemoryManager& theManager); |
| |
| /** |
| * Throw an exception when an invalid |
| * character is encountered. |
| * @param ch The first character in the surrogate |
| * @param next The next character in the surrogate |
| */ |
| static void |
| throwInvalidCharacterException( |
| XalanUnicodeChar ch, |
| MemoryManager& theManager); |
| |
| |
| /** |
| * Throw an exception when an invalid |
| * character for the specific XML version is encountered. |
| * @param ch The first character in the surrogate |
| * @param next The next character in the surrogate |
| */ |
| static void |
| throwInvalidXMLCharacterException( |
| XalanUnicodeChar ch, |
| const XalanDOMString& theXMLversion, |
| MemoryManager& theManager); |
| private: |
| |
| // These are not implemented. |
| XalanXMLSerializerBase(const XalanXMLSerializerBase&); |
| |
| XalanXMLSerializerBase& |
| operator=(const XalanXMLSerializerBase&); |
| |
| bool |
| operator==(const XalanXMLSerializerBase&) const; |
| |
| // Data members... |
| /** |
| * Flag to tell that we need to add the doctype decl, |
| * which we can't do until the first element is |
| * encountered. |
| */ |
| bool m_needToOutputDoctypeDecl; |
| |
| /** |
| * If true, XML header should be written to output. |
| */ |
| bool m_shouldWriteXMLHeader; |
| |
| /** |
| * A stack of Boolean objects that tell if the given element |
| * has children. |
| */ |
| BoolStackType m_elemStack; |
| |
| /** |
| * The string "-//W3C//DTD XHTML". |
| */ |
| static const XalanDOMChar s_xhtmlDocTypeString[]; |
| |
| static const size_type s_xhtmlDocTypeStringLength; |
| }; |
| |
| |
| |
| } |
| |
| |
| |
| #endif // XALANXMLSERIALIZERBASE_HEADER_GUARD_1357924680 |