/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed 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. */ // Class header file. #include "FormatterToXML.hpp" #include #include #include #include #include #include #include #include #include XALAN_CPP_NAMESPACE_BEGIN static const XalanDOMChar theDefaultAttrSpecialChars[] = { XalanUnicode::charLessThanSign, XalanUnicode::charGreaterThanSign, XalanUnicode::charAmpersand, XalanUnicode::charQuoteMark, XalanUnicode::charCR, XalanUnicode::charLF, 0 }; FormatterToXML::FormatterToXML( Writer& writer, const XalanDOMString& version, bool doIndent, int indent, const XalanDOMString& encoding, const XalanDOMString& mediaType, const XalanDOMString& doctypeSystem, const XalanDOMString& doctypePublic, bool xmlDecl, const XalanDOMString& standalone, eFormat format, bool fBufferData, MemoryManagerType& theManager) : FormatterListener(format), m_writer(&writer), m_stream(m_writer->getStream()), m_maxCharacter(0), #if !defined(XALAN_NO_DEFAULT_BUILTIN_ARRAY_INITIALIZATION) m_attrCharsMap(), m_charsMap(), #endif m_shouldWriteXMLHeader(xmlDecl), m_ispreserve(false), m_doIndent(doIndent), m_startNewLine(false), m_needToOutputDocTypeDecl(true), m_isprevtext(false), m_stripCData(false), m_nextIsRaw(false), m_inCData(false), m_encodingIsUTF(false), m_doctypeSystem(doctypeSystem, theManager), m_doctypePublic(doctypePublic, theManager), m_encoding(theManager), m_currentIndent(0), m_indent(indent), m_preserves(theManager), m_stringBuffer(theManager), m_bytesEqualChars(false), m_shouldFlush(fBufferData), m_spaceBeforeClose(false), m_escapeCData(false), m_version(version, theManager), m_standalone(standalone, theManager), m_mediaType(mediaType, theManager), m_attrSpecialChars(theDefaultAttrSpecialChars, theManager), m_charBuf(theManager), m_pos(0), m_byteBuf(theManager), m_elemStack(theManager), m_accumNameCharFunction(0), m_accumNameStringFunction(0), m_accumNameDOMStringFunction(0), m_accumNameArrayFunction(0), m_accumContentCharFunction(0), m_accumContentStringFunction(0), m_accumContentDOMStringFunction(0), m_accumContentArrayFunction(0), m_flushFunction(0), m_newlineString(0), m_newlineStringLength(0), m_isXML1_1(false) { if (isEmpty(encoding) == false) { m_encoding = encoding; } else { m_encoding = XalanDOMString(XalanTranscodingServices::s_utf8String, theManager); } assert(isEmpty(m_encoding) == false); if(isEmpty(m_doctypePublic) == false) { if(startsWith( m_doctypePublic, s_xhtmlDocTypeString) == true) { m_spaceBeforeClose = true; } } if (m_stream == 0) { m_newlineString = XalanOutputStream::defaultNewlineString(); } else { try { m_stream->setOutputEncoding(m_encoding); } catch(const XalanOutputStream::UnsupportedEncodingException&) { // Default to UTF-8 if the requested encoding is not supported... m_stream->setOutputEncoding(XalanDOMString(XalanTranscodingServices::s_utf8String, theManager)); m_encoding = XalanTranscodingServices::s_utf8String; } m_newlineString = m_stream->getNewlineString(); } assert(m_newlineString != 0); m_newlineStringLength = length(m_newlineString); m_maxCharacter = XalanTranscodingServices::getMaximumCharacterValue(m_encoding); // We cannot omit the XML declaration if the encoding is not UTF-8 or // UTF-16, or if there is a standalone declaration const bool canOmitXMLDeclaration = (XalanTranscodingServices::encodingIsUTF8(m_encoding) || XalanTranscodingServices::encodingIsUTF16(m_encoding)) && m_standalone.length() == 0; if (canOmitXMLDeclaration == false && m_shouldWriteXMLHeader == false) { m_shouldWriteXMLHeader = true; } //OK, now we can determine if the encoding is UTF* m_encodingIsUTF = canOmitXMLDeclaration || XalanTranscodingServices::encodingIsUTF32(m_encoding); if (m_version.empty() != true && DoubleSupport::equal(DOMStringToDouble(m_version, theManager), 1.1) == true) { m_isXML1_1 = true; } #if 1 if (m_encodingIsUTF == true) { if (fBufferData == false) { m_accumNameCharFunction = &FormatterToXML::accumCharUTFDirect; m_accumContentCharFunction = &FormatterToXML::accumCharUTFDirect; m_accumNameStringFunction = &FormatterToXML::accumStringUTFDirect; m_accumContentStringFunction = &FormatterToXML::accumStringUTFDirect; m_accumNameDOMStringFunction = &FormatterToXML::accumDOMStringUTFDirect; m_accumContentDOMStringFunction = &FormatterToXML::accumDOMStringUTFDirect; m_accumNameArrayFunction = &FormatterToXML::accumArrayUTFDirect; m_accumContentArrayFunction = &FormatterToXML::accumArrayUTFDirect; } else { m_charBuf.resize(s_maxBufferSize); m_accumNameCharFunction = &FormatterToXML::accumCharUTF; m_accumContentCharFunction = &FormatterToXML::accumCharUTF; m_accumNameStringFunction = &FormatterToXML::accumStringUTF; m_accumContentStringFunction = &FormatterToXML::accumStringUTF; m_accumNameDOMStringFunction = &FormatterToXML::accumDOMStringUTF; m_accumContentDOMStringFunction = &FormatterToXML::accumDOMStringUTF; m_accumNameArrayFunction = &FormatterToXML::accumArrayUTF; m_accumContentArrayFunction = &FormatterToXML::accumArrayUTF; } } else { if (fBufferData == false) { m_accumNameCharFunction = &FormatterToXML::accumNameAsCharDirect; m_accumContentCharFunction = &FormatterToXML::accumContentAsCharDirect; } else { m_charBuf.resize(s_maxBufferSize); m_accumNameCharFunction = &FormatterToXML::accumNameAsChar; m_accumContentCharFunction = &FormatterToXML::accumContentAsChar; } m_accumNameStringFunction = &FormatterToXML::accumNameString; m_accumContentStringFunction = &FormatterToXML::accumContentString; m_accumNameDOMStringFunction = &FormatterToXML::accumNameDOMString; m_accumContentDOMStringFunction = &FormatterToXML::accumContentDOMString; m_accumNameArrayFunction = &FormatterToXML::accumNameArray; m_accumContentArrayFunction = &FormatterToXML::accumContentArray; } m_flushFunction = &FormatterToXML::flushChars; #else if (XalanTranscodingServices::getBytesEqualChars(m_encoding) == true) { m_bytesEqualChars = true; if (fBufferData == false) { m_accumNameCharFunction = &FormatterToXML::accumNameAsByteDirect; m_accumContentCharFunction = &FormatterToXML::accumContentAsByteDirect; } else { m_byteBuf.resize(s_maxBufferSize); m_accumNameCharFunction = &FormatterToXML::accumNameAsByte; m_accumContentCharFunction = &FormatterToXML::accumContentAsByte; } m_accumNameStringFunction = &FormatterToXML::accumNameString; m_accumContentStringFunction = &FormatterToXML::accumContentString; m_accumNameDOMStringFunction = &FormatterToXML::accumNameDOMString; m_accumContentDOMStringFunction = &FormatterToXML::accumContentDOMString; m_accumNameArrayFunction = &FormatterToXML::accumNameArray; m_accumContentArrayFunction = &FormatterToXML::accumContentArray; m_flushFunction = &FormatterToXML::flushBytes; } else { if (fBufferData == false) { m_accumNameCharFunction = &FormatterToXML::accumNameAsCharDirect; m_accumContentCharFunction = &FormatterToXML::accumContentAsCharDirect; } else { m_charBuf.resize(s_maxBufferSize); m_accumNameCharFunction = &FormatterToXML::accumNameAsChar; m_accumContentCharFunction = &FormatterToXML::accumContentAsChar; } m_flushFunction = &FormatterToXML::flushChars; } #endif // Do this last so we initialize the map according to the value of // m_maxCharacter for the encoding. initCharsMap(); } FormatterToXML* FormatterToXML::create( MemoryManagerType& theManager, Writer& writer, const XalanDOMString& version, bool doIndent , int indent , const XalanDOMString& encoding , const XalanDOMString& mediaType , const XalanDOMString& doctypeSystem , const XalanDOMString& doctypePublic , bool xmlDecl , const XalanDOMString& standalone , eFormat format, bool fBufferData ) { typedef FormatterToXML ThisType; XalanMemMgrAutoPtr theGuard( theManager , (ThisType*)theManager.allocate(sizeof(ThisType))); ThisType* theResult = theGuard.get(); new (theResult) ThisType( writer, version, doIndent , indent , encoding , mediaType , doctypeSystem , doctypePublic , xmlDecl , standalone , format, fBufferData, theManager); theGuard.release(); return theResult; } FormatterToXML::~FormatterToXML() { } void FormatterToXML::initAttrCharsMap() { #if defined(XALAN_STRICT_ANSI_HEADERS) std::memset(m_attrCharsMap, 0, sizeof(m_attrCharsMap)); #else memset(m_attrCharsMap, 0, sizeof(m_attrCharsMap)); #endif const XalanDOMString::size_type nSpecials = length(m_attrSpecialChars); { for(XalanDOMString::size_type i = 0; i < nSpecials; ++i) { m_attrCharsMap[charAt(m_attrSpecialChars, i)] = 'S'; } } m_attrCharsMap[XalanUnicode::charHTab] = 'S'; m_attrCharsMap[XalanUnicode::charLF] = 'S'; m_attrCharsMap[XalanUnicode::charCR] = 'S'; for(size_t i = 1; i < 0x20; i++) { m_attrCharsMap[i] = 'S'; } for(size_t j = 0x7F; j < 0x9F; j++) { m_attrCharsMap[j] = 'S'; } } void FormatterToXML::initCharsMap() { initAttrCharsMap(); #if defined(XALAN_STRICT_ANSI_HEADERS) std::memset(m_charsMap, 0, sizeof(m_charsMap)); #else memset(m_charsMap, 0, sizeof(m_charsMap)); #endif m_charsMap[XalanUnicode::charLessThanSign] = 'S'; m_charsMap[XalanUnicode::charGreaterThanSign] = 'S'; m_charsMap[XalanUnicode::charAmpersand] = 'S'; for(size_t i = 1; i < 0x20; i++) { m_charsMap[i] = 'S'; } for(size_t j = 0x7F; j < 0x9F; j++) { m_charsMap[j] = 'S'; } m_charsMap[9] = '\0'; assert(m_maxCharacter != 0); for(XalanDOMChar k = m_maxCharacter; k < SPECIALSSIZE; ++k) { m_charsMap[k] = 'S'; } } void FormatterToXML::outputDocTypeDecl(const XalanDOMChar* name) { // " m_maxCharacter) { m_byteBuf[m_pos++] = char(XalanUnicode::charQuestionMark); } else { m_byteBuf[m_pos++] = char(ch); } if(m_pos == s_maxBufferSize) { flushBytes(); } } void FormatterToXML::accumNameAsByteDirect(XalanDOMChar ch) { assert(m_stream != 0); if (ch > m_maxCharacter) { m_stream->write(char(XalanUnicode::charQuestionMark)); } else { m_stream->write(char(ch)); } } void FormatterToXML::accumContentAsByte(XalanDOMChar ch) { if (ch > m_maxCharacter) { writeNumberedEntityReference(ch); } else { m_byteBuf[m_pos++] = char(ch); } if(m_pos == s_maxBufferSize) { flushBytes(); } } void FormatterToXML::accumContentAsByteDirect(XalanDOMChar ch) { assert(m_stream != 0); if (ch > m_maxCharacter) { writeNumberedEntityReference(ch); } else { m_stream->write(char(ch)); } } void FormatterToXML::accumNameAsChar(XalanDOMChar ch) { if (ch > m_maxCharacter) { m_charBuf[m_pos++] = XalanUnicode::charQuestionMark; } else { m_charBuf[m_pos++] = ch; } if(m_pos == s_maxBufferSize) { flushChars(); } } void FormatterToXML::accumNameAsCharDirect(XalanDOMChar ch) { assert(m_stream != 0); if (ch > m_maxCharacter) { m_stream->write(XalanDOMChar(XalanUnicode::charQuestionMark)); } else { m_stream->write(ch); } } void FormatterToXML::accumContentAsChar(XalanDOMChar ch) { if (ch > m_maxCharacter) { writeNumberedEntityReference(ch); } else { m_charBuf[m_pos++] = ch; } if(m_pos == s_maxBufferSize) { flushChars(); } } void FormatterToXML::accumContentAsCharDirect(XalanDOMChar ch) { assert(m_stream != 0); if (ch > m_maxCharacter) { writeNumberedEntityReference(ch); } else { m_stream->write(ch); } } void FormatterToXML::accumCharUTF(XalanDOMChar ch) { assert(m_maxCharacter >= 65535); assert(m_stream != 0); m_charBuf[m_pos++] = ch; if(m_pos == s_maxBufferSize) { flushChars(); } } void FormatterToXML::accumCharUTFDirect(XalanDOMChar ch) { assert(m_maxCharacter >= 65535); assert(m_stream != 0); m_stream->write(ch); } void FormatterToXML::accumNameString(const XalanDOMChar* chars) { for(; *chars!= 0; ++chars) { accumName(*chars); } } void FormatterToXML::accumStringUTF(const XalanDOMChar* chars) { for(; *chars!= 0; ++chars) { accumCharUTF(*chars); } } void FormatterToXML::accumStringUTFDirect(const XalanDOMChar* chars) { assert(m_maxCharacter >= 65535); assert(m_stream != 0); m_stream->write(chars); } void FormatterToXML::accumContentString(const XalanDOMChar* chars) { for(; *chars!= 0; ++chars) { accumContent(*chars); } } void FormatterToXML::accumNameArray( const XalanDOMChar chars[], XalanDOMString::size_type start, XalanDOMString::size_type length) { const XalanDOMString::size_type n = start + length; for(XalanDOMString::size_type i = start; i < n; ++i) { accumName(chars[i]); } } void FormatterToXML::accumContentArray( const XalanDOMChar chars[], XalanDOMString::size_type start, XalanDOMString::size_type length) { const XalanDOMString::size_type n = start + length; for(XalanDOMString::size_type i = start; i < n; ++i) { accumContent(chars[i]); } } void FormatterToXML::accumArrayUTF( const XalanDOMChar chars[], XalanDOMString::size_type start, XalanDOMString::size_type length) { const XalanDOMString::size_type n = start + length; for(XalanDOMString::size_type i = start; i < n; ++i) { accumCharUTF(chars[i]); } } void FormatterToXML::accumArrayUTFDirect( const XalanDOMChar chars[], XalanDOMString::size_type start, XalanDOMString::size_type length) { assert(m_maxCharacter >= 65535); assert(m_stream != 0); m_stream->write(chars + start, length); } void FormatterToXML::accumNameDOMString(const XalanDOMString& str) { accumName(c_wstr(str), 0, length(str)); } void FormatterToXML::accumContentDOMString(const XalanDOMString& str) { accumContent(c_wstr(str), 0, length(str)); } void FormatterToXML::accumDOMStringUTF(const XalanDOMString& str) { accumArrayUTF(c_wstr(str), 0, length(str)); } void FormatterToXML::accumDOMStringUTFDirect(const XalanDOMString& str) { assert(m_maxCharacter >= 65535); assert(m_stream != 0); m_stream->write(c_wstr(str), length(str)); } XALAN_USING_XERCES(SAXException) void FormatterToXML::throwInvalidUTF16SurrogateException( XalanDOMChar ch, MemoryManagerType& theManager) { XalanDOMString chStr(theManager); UnsignedLongToHexDOMString(ch, chStr); XalanDOMString theMessage(theManager); XalanMessageLoader::getMessage( theMessage, XalanMessages::InvalidHighSurrogate_1Param, chStr); throw SAXException(theMessage.c_str(), &theManager); } void FormatterToXML::throwInvalidCharacterException( unsigned int ch, MemoryManagerType& theManager) { XalanDOMString theMessage(theManager); XalanDOMString theBuffer(theManager); XalanMessageLoader::getMessage( theMessage, XalanMessages::InvalidScalar_1Param, UnsignedLongToHexDOMString(ch, theBuffer)); XALAN_USING_XERCES(SAXException) throw SAXException(c_wstr(theMessage),&theManager); } void FormatterToXML::throwInvalidUTF16SurrogateException( XalanDOMChar ch, XalanDOMChar next, MemoryManagerType& theManager) { XalanDOMString chStr1(theManager); XalanDOMString chStr2(theManager); UnsignedLongToHexDOMString(ch, chStr1); UnsignedLongToHexDOMString(next, chStr2); XalanDOMString theMessage(theManager); XalanMessageLoader::getMessage( theMessage, XalanMessages::InvalidSurrogatePair_2Param, chStr1, chStr2); throw SAXException(theMessage.c_str(), &theManager); } XalanDOMString::size_type FormatterToXML::accumDefaultEscape( XalanDOMChar ch, XalanDOMString::size_type i, const XalanDOMChar chars[], XalanDOMString::size_type len, bool escLF) { if(!accumDefaultEntity(ch, escLF)) { if (0xd800 <= ch && ch < 0xdc00) { // UTF-16 surrogate unsigned long next = 0; if (i + 1 >= len) { throwInvalidUTF16SurrogateException(ch, getMemoryManager()); } else { next = chars[++i]; if (!(0xdc00u <= next && next < 0xe000u)) { throwInvalidUTF16SurrogateException(ch, XalanDOMChar(next), getMemoryManager()); } next = ((ch - 0xd800u) << 10) + next - 0xdc00u + 0x00010000u; } writeNumberedEntityReference(next); } else { if(ch > m_maxCharacter) { if( !m_isXML1_1 && XalanUnicode::charLSEP == ch ) { throwInvalidCharacterException(ch, getMemoryManager()); } else { writeNumberedEntityReference(ch); } } else if(ch < SPECIALSSIZE && m_attrCharsMap[ch] == 'S') { if(ch < 0x20 ) { if(m_isXML1_1) { writeNumberedEntityReference(ch); } else { throwInvalidCharacterException(ch, getMemoryManager()); } } else if( XalanUnicode::charNEL == ch ) { if(m_isXML1_1) { writeNumberedEntityReference(ch); } else { throwInvalidCharacterException(ch, getMemoryManager()); } } else { writeNumberedEntityReference(ch); } } else { accumContent(ch); } } } return i; } bool FormatterToXML::accumDefaultEntity( XalanDOMChar ch, bool escLF) { if (escLF == false && XalanUnicode::charLF == ch) { outputLineSep(); } else if (XalanUnicode::charLessThanSign == ch) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charLetter_l); accumContent(XalanUnicode::charLetter_t); accumContent(XalanUnicode::charSemicolon); } else if (XalanUnicode::charGreaterThanSign == ch) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charLetter_g); accumContent(XalanUnicode::charLetter_t); accumContent(XalanUnicode::charSemicolon); } else if (XalanUnicode::charAmpersand == ch) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charLetter_a); accumContent(XalanUnicode::charLetter_m); accumContent(XalanUnicode::charLetter_p); accumContent(XalanUnicode::charSemicolon); } else if (XalanUnicode::charQuoteMark == ch) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charLetter_q); accumContent(XalanUnicode::charLetter_u); accumContent(XalanUnicode::charLetter_o); accumContent(XalanUnicode::charLetter_t); accumContent(XalanUnicode::charSemicolon); } else if (XalanUnicode::charApostrophe == ch) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charLetter_a); accumContent(XalanUnicode::charLetter_p); accumContent(XalanUnicode::charLetter_o); accumContent(XalanUnicode::charLetter_s); accumContent(XalanUnicode::charSemicolon); } else { return false; } return true; } void FormatterToXML::flushChars() { assert(m_charBuf.empty() == false && m_charBuf.size() >= m_pos); m_writer->write(&m_charBuf[0], 0, m_pos); m_pos = 0; } void FormatterToXML::flushBytes() { assert(m_byteBuf.empty() == false && m_byteBuf.size() >= m_pos); m_writer->write(&m_byteBuf[0], 0, m_pos); m_pos = 0; } void FormatterToXML::flushWriter() { assert(m_writer != 0); m_writer->flush(); } void FormatterToXML::setDocumentLocator(const LocatorType* const /* locator */) { // I don't do anything with this yet. } void FormatterToXML::startDocument() { // Clear the buffer, just in case... clear(m_stringBuffer); m_needToOutputDocTypeDecl = true; m_startNewLine = false; if(m_shouldWriteXMLHeader == true) { // "*m_flushFunction)(); } flushWriter(); } void FormatterToXML::startElement( const XMLCh* const name, AttributeListType& attrs) { if(true == m_needToOutputDocTypeDecl && isEmpty(m_doctypeSystem) == false) { outputDocTypeDecl(name); m_needToOutputDocTypeDecl = false; } writeParentTagEnd(); m_ispreserve = false; if (shouldIndent() == true && m_startNewLine == true) { indent(m_currentIndent); } m_startNewLine = true; accumName(XalanUnicode::charLessThanSign); accumName(name); const unsigned int nAttrs = attrs.getLength(); for (unsigned int i = 0; i < nAttrs ; i++) { processAttribute(attrs.getName(i), attrs.getValue(i)); } // Flag the current element as not yet having any children. openElementForChildren(); m_currentIndent += m_indent; m_isprevtext = false; } void FormatterToXML::endElement(const XMLCh* const name) { m_currentIndent -= m_indent; const bool hasChildNodes = childNodesWereAdded(); if (hasChildNodes == true) { if (shouldIndent() == true) { indent(m_currentIndent); } accumName(XalanUnicode::charLessThanSign); accumName(XalanUnicode::charSolidus); accumName(name); } else { if(m_spaceBeforeClose == true) { accumName(XalanUnicode::charSpace); } accumName(XalanUnicode::charSolidus); } accumName(XalanUnicode::charGreaterThanSign); if (hasChildNodes == true) { if (m_preserves.empty() == true) { m_ispreserve = false; } else { m_ispreserve = m_preserves.back(); m_preserves.pop_back(); } } m_isprevtext = false; } void FormatterToXML::processingInstruction( const XMLCh* const target, const XMLCh* const data) { // Use a fairly nasty hack to tell if the next node is supposed to be // unescaped text. if(equals(target, length(target), s_piTarget, s_piTargetLength) == true && equals(data, length(data), s_piData, s_piDataLength) == true) { m_nextIsRaw = true; } else { writeParentTagEnd(); if (shouldIndent() == true) { indent(m_currentIndent); } accumName(XalanUnicode::charLessThanSign); accumName(XalanUnicode::charQuestionMark); accumName(target); const XalanDOMString::size_type len = length(data); if ( len > 0 && !isXMLWhitespace(data[0])) { accumName(XalanUnicode::charSpace); } accumNormalizedPIData(data, len); accumName(XalanUnicode::charQuestionMark); accumName(XalanUnicode::charGreaterThanSign); // If outside of an element, then put in a new line. This whitespace // is not significant. if (m_elemStack.empty() == true) { outputLineSep(); } m_startNewLine = true; } } void FormatterToXML::characters( const XMLCh* const chars, const unsigned int length) { if(length != 0) { if(m_inCData == true) { cdata(chars, length); } else if(m_nextIsRaw) { m_nextIsRaw = false; charactersRaw(chars, length); } else { writeParentTagEnd(); m_ispreserve = true; unsigned int i = 0; unsigned int firstIndex = 0; while(i < length) { const XalanDOMChar ch = chars[i]; if((ch < SPECIALSSIZE && m_charsMap[ch] == 'S') || ch > m_maxCharacter) { accumContent(chars, firstIndex, i - firstIndex); i = accumDefaultEscape(ch, i, chars, length, false); ++i; firstIndex = i; } else { ++i; } } accumContent(chars, firstIndex, i - firstIndex); if (m_isprevtext == false) { m_isprevtext = true; } } } } void FormatterToXML::charactersRaw( const XMLCh* const chars, const unsigned int length) { writeParentTagEnd(); m_ispreserve = true; accumContent(chars, 0, length); } Writer* FormatterToXML::getWriter() const { return m_writer; } const XalanDOMString& FormatterToXML::getDoctypeSystem() const { return m_doctypeSystem; } const XalanDOMString& FormatterToXML::getDoctypePublic() const { return m_doctypePublic; } const XalanDOMString& FormatterToXML::getEncoding() const { return m_encoding; } const XalanDOMString& FormatterToXML::getMediaType() const { return m_mediaType; } int FormatterToXML::getIndent() const { return m_indent; } void FormatterToXML::writeAttrString( const XalanDOMChar* theString, XalanDOMString::size_type theStringLength) { assert(theString != 0); XalanDOMString::size_type i = 0; XalanDOMString::size_type firstIndex = 0; while(i < theStringLength) { const XalanDOMChar ch = theString[i]; if((ch < SPECIALSSIZE && m_attrCharsMap[ch] == 'S') || ch > m_maxCharacter) { accumContent(theString, firstIndex, i - firstIndex); i = accumDefaultEscape(ch, i, theString, theStringLength, true); ++i; firstIndex = i; } else { ++i; } } accumContent(theString, firstIndex, i - firstIndex); } void FormatterToXML::accumCommentData(const XalanDOMChar* data) { accumContent(data); } void FormatterToXML::writeNormalizedChars( const XalanDOMChar ch[], XalanDOMString::size_type start, XalanDOMString::size_type length, bool isCData) { XalanDOMString::size_type end = start + length; for(XalanDOMString::size_type i = start; i < end; i++) { const XalanDOMChar c = ch[i]; if (XalanUnicode::charCR == c && i + 1 < end && XalanUnicode::charLF == ch[i + 1]) { outputLineSep(); i++; } else if(XalanUnicode::charLF == c) { outputLineSep(); } else if(isCData == true && c > m_maxCharacter) { if(i != 0) { accumContent(s_dtdCDATACloseString, 0, s_dtdCDATACloseStringLength); } // This needs to go into a function... if (0xd800u <= unsigned(c) && unsigned(c) < 0xdc00) { // UTF-16 surrogate XalanDOMChar next = 0; if (i + 1 >= end) { throwInvalidUTF16SurrogateException(c,getMemoryManager()); } else { next = ch[++i]; if (!(0xdc00 <= next && next < 0xe000)) { throwInvalidUTF16SurrogateException(c, next, getMemoryManager()); } next = XalanDOMChar(((c - 0xd800) << 10) + next - 0xdc00 + 0x00010000); } writeNumberedEntityReference(next); } else { writeNumberedEntityReference(c); } if(i != 0 && i < end - 1) { // "" accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charGreaterThanSign); accumContent(XalanUnicode::charLessThanSign); accumContent(XalanUnicode::charExclamationMark); accumContent(XalanUnicode::charLeftSquareBracket); accumContent(XalanUnicode::charLetter_C); accumContent(XalanUnicode::charLetter_D); accumContent(XalanUnicode::charLetter_A); accumContent(XalanUnicode::charLetter_T); accumContent(XalanUnicode::charLetter_A); accumContent(XalanUnicode::charLeftSquareBracket); accumContent(XalanUnicode::charGreaterThanSign); i += 2; } else { if(c <= m_maxCharacter) { accumContent(c); } // This needs to go into a function... else if (0xd800 <= c && c < 0xdc00) { // UTF-16 surrogate XalanDOMChar next = 0; if (i + 1 >= end) { throwInvalidUTF16SurrogateException(c, getMemoryManager()); } else { next = ch[++i]; if (!(0xdc00 <= next && next < 0xe000)) { throwInvalidUTF16SurrogateException(c, next, getMemoryManager()); } next = XalanDOMChar(((c - 0xd800) << 10) + next - 0xdc00 + 0x00010000); } writeNumberedEntityReference(next); } else { writeNumberedEntityReference(c); } } } } void FormatterToXML::writeNumberedEntityReference(unsigned long theNumber) { accumContent(XalanUnicode::charAmpersand); accumContent(XalanUnicode::charNumberSign); accumContent(UnsignedLongToDOMString(theNumber, m_stringBuffer)); clear(m_stringBuffer); accumContent(XalanUnicode::charSemicolon); } void FormatterToXML::entityReference(const XMLCh* const name) { writeParentTagEnd(); if (shouldIndent() == true) { indent(m_currentIndent); } accumName(XalanUnicode::charAmpersand); accumName(name); accumName(XalanUnicode::charSemicolon); } void FormatterToXML::ignorableWhitespace( const XMLCh* const chars, const unsigned int length) { #if 1 // We need to do normalization, which is slower, // but there you have it... if (length > 0) { characters(chars, length); } #else // We'ed like to be able to do this... if(length != 0) { assert(isXMLWhitespace(chars, 0, length)); if(m_inCData == true) { cdata(chars, length); } else if(m_nextIsRaw) { m_nextIsRaw = false; charactersRaw(chars, length); } else { writeParentTagEnd(); m_ispreserve = true; accumContent(chars, 0, length); if (m_isprevtext == false) { m_isprevtext = true; } } } #endif } void FormatterToXML::resetDocument() { // I don't do anything with this yet. } void FormatterToXML::comment(const XMLCh* const data) { writeParentTagEnd(); if (shouldIndent() == true) { indent(m_currentIndent); } accumName(XalanUnicode::charLessThanSign); accumName(XalanUnicode::charExclamationMark); accumName(XalanUnicode::charHyphenMinus); accumName(XalanUnicode::charHyphenMinus); accumCommentData(data); accumName(XalanUnicode::charHyphenMinus); accumName(XalanUnicode::charHyphenMinus); accumName(XalanUnicode::charGreaterThanSign); m_startNewLine = true; } void FormatterToXML::cdata( const XMLCh* const ch, const unsigned int length) { if(m_nextIsRaw == true) { m_nextIsRaw = false; charactersRaw(ch, length); } else { if(m_escapeCData) // Should normally always be false. { characters(ch, length); } else { writeParentTagEnd(); m_ispreserve = true; if (shouldIndent() == true) { indent(m_currentIndent); } if(m_stripCData == false) { if(length >= 1 && ch[0] <= m_maxCharacter) { // "= 1 && ch[length - 1] <= m_maxCharacter) { accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charRightSquareBracket); accumContent(XalanUnicode::charGreaterThanSign); } } } } } void FormatterToXML::writeParentTagEnd() { if(!m_elemStack.empty()) { // See if the parent element has already been flagged as having children. if(false == m_elemStack.back()) { accumContent(XalanUnicode::charGreaterThanSign); m_isprevtext = false; m_elemStack.back() = true; m_preserves.push_back(m_ispreserve); } } } void FormatterToXML::openElementForChildren() { m_elemStack.push_back(false); } bool FormatterToXML::childNodesWereAdded() { bool fResult = false; if (m_elemStack.empty() == false) { fResult = m_elemStack.back(); m_elemStack.pop_back(); } return fResult; } void FormatterToXML::processAttribute( const XalanDOMChar* name, const XalanDOMChar* value) { accumContent(XalanUnicode::charSpace); accumName(name); accumContent(XalanUnicode::charEqualsSign); accumContent(XalanUnicode::charQuoteMark); writeAttrString(value, length(value)); accumContent(XalanUnicode::charQuoteMark); } void FormatterToXML::outputLineSep() { assert(m_newlineString != 0 && length(m_newlineString) == m_newlineStringLength); accumContent(m_newlineString, 0, m_newlineStringLength); } void FormatterToXML::printSpace(int n) { for (int i = 0; i < n; i ++) { accumContent(XalanUnicode::charSpace); } } void FormatterToXML::indent(int n) { if(m_startNewLine == true) { outputLineSep(); } if(m_doIndent == true) { printSpace(n); } } void FormatterToXML::accumNormalizedPIData( const XalanDOMChar* theData, XalanDOMString::size_type theLength) { for (XalanDOMString::size_type i = 0; i < theLength; ++i) { accumContent(theData[i]); } } #define FXML_SIZE(str) ((sizeof(str) / sizeof(str[0]) - 1)) const XalanDOMChar FormatterToXML::s_doctypeHeaderStartString[] = { XalanUnicode::charLessThanSign, XalanUnicode::charExclamationMark, XalanUnicode::charLetter_D, XalanUnicode::charLetter_O, XalanUnicode::charLetter_C, XalanUnicode::charLetter_T, XalanUnicode::charLetter_Y, XalanUnicode::charLetter_P, XalanUnicode::charLetter_E, XalanUnicode::charSpace, 0 }; const FormatterToXML::size_type FormatterToXML::s_doctypeHeaderStartStringLength = FXML_SIZE(s_doctypeHeaderStartString); const XalanDOMChar FormatterToXML::s_doctypeHeaderPublicString[] = { XalanUnicode::charSpace, XalanUnicode::charLetter_P, XalanUnicode::charLetter_U, XalanUnicode::charLetter_B, XalanUnicode::charLetter_L, XalanUnicode::charLetter_I, XalanUnicode::charLetter_C, XalanUnicode::charSpace, XalanUnicode::charQuoteMark, 0 }; const FormatterToXML::size_type FormatterToXML::s_doctypeHeaderPublicStringLength = FXML_SIZE(s_doctypeHeaderPublicString); const XalanDOMChar FormatterToXML::s_doctypeHeaderSystemString[] = { XalanUnicode::charSpace, XalanUnicode::charLetter_S, XalanUnicode::charLetter_Y, XalanUnicode::charLetter_S, XalanUnicode::charLetter_T, XalanUnicode::charLetter_E, XalanUnicode::charLetter_M, XalanUnicode::charSpace, XalanUnicode::charQuoteMark, 0 }; const FormatterToXML::size_type FormatterToXML::s_doctypeHeaderSystemStringLength = FXML_SIZE(s_doctypeHeaderSystemString); const XalanDOMChar FormatterToXML::s_xmlHeaderStartString[] = { XalanUnicode::charLessThanSign, XalanUnicode::charQuestionMark, XalanUnicode::charLetter_x, XalanUnicode::charLetter_m, XalanUnicode::charLetter_l, XalanUnicode::charSpace, XalanUnicode::charLetter_v, XalanUnicode::charLetter_e, XalanUnicode::charLetter_r, XalanUnicode::charLetter_s, XalanUnicode::charLetter_i, XalanUnicode::charLetter_o, XalanUnicode::charLetter_n, XalanUnicode::charEqualsSign, XalanUnicode::charQuoteMark, 0 }; const FormatterToXML::size_type FormatterToXML::s_xmlHeaderStartStringLength = FXML_SIZE(s_xmlHeaderStartString); const XalanDOMChar FormatterToXML::s_xmlHeaderEncodingString[] = { XalanUnicode::charQuoteMark, XalanUnicode::charSpace, XalanUnicode::charLetter_e, XalanUnicode::charLetter_n, XalanUnicode::charLetter_c, XalanUnicode::charLetter_o, XalanUnicode::charLetter_d, XalanUnicode::charLetter_i, XalanUnicode::charLetter_n, XalanUnicode::charLetter_g, XalanUnicode::charEqualsSign, XalanUnicode::charQuoteMark, 0 }; const FormatterToXML::size_type FormatterToXML::s_xmlHeaderEncodingStringLength = FXML_SIZE(s_xmlHeaderEncodingString); const XalanDOMChar FormatterToXML::s_xmlHeaderStandaloneString[] = { XalanUnicode::charQuoteMark, XalanUnicode::charSpace, XalanUnicode::charLetter_s, XalanUnicode::charLetter_t, XalanUnicode::charLetter_a, XalanUnicode::charLetter_n, XalanUnicode::charLetter_d, XalanUnicode::charLetter_a, XalanUnicode::charLetter_l, XalanUnicode::charLetter_o, XalanUnicode::charLetter_n, XalanUnicode::charLetter_e, XalanUnicode::charEqualsSign, XalanUnicode::charQuoteMark, 0 }; const FormatterToXML::size_type FormatterToXML::s_xmlHeaderStandaloneStringLength = FXML_SIZE(s_xmlHeaderStandaloneString); const XalanDOMChar FormatterToXML::s_xmlHeaderEndString[] = { XalanUnicode::charQuoteMark, XalanUnicode::charQuestionMark, XalanUnicode::charGreaterThanSign, 0 }; const FormatterToXML::size_type FormatterToXML::s_xmlHeaderEndStringLength = FXML_SIZE(s_xmlHeaderEndString); const XalanDOMChar FormatterToXML::s_defaultVersionString[] = { XalanUnicode::charDigit_1, XalanUnicode::charFullStop, XalanUnicode::charDigit_0, 0 }; const FormatterToXML::size_type FormatterToXML::s_defaultVersionStringLength = FXML_SIZE(s_defaultVersionString); const XalanDOMChar FormatterToXML::s_dtdCDATACloseString[] = { XalanUnicode::charRightSquareBracket, XalanUnicode::charRightSquareBracket, XalanUnicode::charGreaterThanSign, 0 }; const FormatterToXML::size_type FormatterToXML::s_dtdCDATACloseStringLength = FXML_SIZE(s_dtdCDATACloseString); const XalanDOMChar FormatterToXML::s_xhtmlDocTypeString[] = { XalanUnicode::charHyphenMinus, XalanUnicode::charSolidus, XalanUnicode::charSolidus, XalanUnicode::charLetter_W, XalanUnicode::charDigit_3, XalanUnicode::charLetter_C, XalanUnicode::charSolidus, XalanUnicode::charSolidus, XalanUnicode::charLetter_D, XalanUnicode::charLetter_T, XalanUnicode::charLetter_D, XalanUnicode::charSpace, XalanUnicode::charLetter_X, XalanUnicode::charLetter_H, XalanUnicode::charLetter_T, XalanUnicode::charLetter_M, XalanUnicode::charLetter_L, 0 }; const FormatterToXML::size_type FormatterToXML::s_xhtmlDocTypeStringLength = FXML_SIZE(s_xhtmlDocTypeString); const XalanDOMString::size_type FormatterToXML::s_maxBufferSize = 512; XALAN_CPP_NAMESPACE_END