blob: a3f2fcc335f559aca9ae932e6891e1467ba83575 [file] [log] [blame]
/*
* 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"
XALAN_CPP_NAMESPACE_BEGIN
class XalanOutputStream;
XALAN_USING_XERCES(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 "&lt;".
*/
static const char s_lessThanEntityString[];
static const size_type s_lessThanEntityStringLength;
/**
* The string "&gt;".
*/
static const char s_greaterThanEntityString[];
static const size_type s_greaterThanEntityStringLength;
/**
* The string "&amp;".
*/
static const char s_ampersandEntityString[];
static const size_type s_ampersandEntityStringLength;
/**
* The string "&quot;".
*/
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 "&lt;".
*/
static const XalanDOMChar s_lessThanEntityString[];
static const size_type s_lessThanEntityStringLength;
/**
* The string "&gt;".
*/
static const XalanDOMChar s_greaterThanEntityString[];
static const size_type s_greaterThanEntityStringLength;
/**
* The string "&amp;".
*/
static const XalanDOMChar s_ampersandEntityString[];
static const size_type s_ampersandEntityStringLength;
/**
* The string "&quot;".
*/
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;
};
XALAN_CPP_NAMESPACE_END
#endif // XALANXMLSERIALIZERBASE_HEADER_GUARD_1357924680