Orb/Doxygen/src/xmlwriter.cpp
changeset 1 82f11024044a
parent 0 42188c7ea2d9
equal deleted inserted replaced
0:42188c7ea2d9 1:82f11024044a
       
     1 /******************************************************************************
       
     2  *
       
     3  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4  *
       
     5  * Permission to use, copy, modify, and distribute this software and its
       
     6  * documentation under the terms of the GNU General Public License is hereby 
       
     7  * granted. No representations are made about the suitability of this software 
       
     8  * for any purpose. It is provided "as is" without express or implied warranty.
       
     9  * See the GNU General Public License for more details.
       
    10  *
       
    11  */
       
    12 
       
    13 
       
    14 
     1 #include "xmlwriter.h"
    15 #include "xmlwriter.h"
     2 #include "message.h"
    16 #include "message.h"
       
    17 #include "xmldita.h"
     3 
    18 
     4 char ILLEGAL_UNICODE_REPLACEMENT = ' ';
    19 char ILLEGAL_UNICODE_REPLACEMENT = ' ';
     5 /******************** XmlStream ********************/
    20 /******************** XmlStream ********************/
     6 XmlStream::XmlStream(const QString &fileName, const QString &aEncoding, const QString &aStandalone, const QString &doctypeStr) : mFile(fileName), \
    21 XmlStream::XmlStream(const QString &fileName, const QString &aEncoding, const QString &aStandalone, const QString &doctypeStr) : mFile(fileName), \
     7 											mStreamP(0), \
    22 											mStreamP(0), \
     8 											mElemStack(), \
    23 											mElemStack(), \
     9 											mInElement(false), \
    24 											mInElement(false)
    10 											mCanIndent(true)
    25 {
    11 {
    26 	mCanIndentList.setAutoDelete(true);
    12 	mIsOpen = mFile.open(IO_WriteOnly);
    27 	mIsOpen = mFile.open(IO_WriteOnly);
    13 	if (mIsOpen) {
    28 	if (mIsOpen) {
    14 		mStreamP = new QTextStream(&mFile);
    29 		mStreamP = new QTextStream(&mFile);
    15 		if (aEncoding == "UTF-8") {
    30 		if (aEncoding == "UTF-8") {
    16 			mStreamP->setEncoding(QTextStream::UnicodeUTF8);
    31 			mStreamP->setEncoding(QTextStream::UnicodeUTF8);
   119 		// Write element name
   134 		// Write element name
   120 		*mStreamP << "<" << aElemName;
   135 		*mStreamP << "<" << aElemName;
   121 		// Attributes in sorted order
   136 		// Attributes in sorted order
   122 		AttributeMapIter it = aAttrs.begin();
   137 		AttributeMapIter it = aAttrs.begin();
   123 		while (it != aAttrs.end()){
   138 		while (it != aAttrs.end()){
   124 			*mStreamP << " " << it.key() << "=\"" << encodeText(it.data()) << "\"";
   139 			QString attrVal = encodeText(it.data());
       
   140 #ifdef DITA_OT_BUG_ATTRIBUTE_VALUE_HACK
       
   141 			// DITA Open Toolkit error, it fails to re-encode files properly
       
   142 			// Replace "&lt;" with "&amp;lt;"
       
   143 			// Replace "&gt;" with "&amp;gt;"
       
   144 			int fIdx = 0;
       
   145 			QString toFind;
       
   146 			QString toReplace;
       
   147 			toFind = "&lt;";
       
   148 			toReplace = "&amp;lt;";
       
   149 			fIdx = attrVal.find(toFind, 0);
       
   150 			while (fIdx != -1) {
       
   151 				attrVal.replace(fIdx, toFind.length(), toReplace);
       
   152 				fIdx = attrVal.find(toFind, 0);
       
   153 			}
       
   154 			toFind = "&gt;";
       
   155 			toReplace = "&amp;gt;";
       
   156 			fIdx = attrVal.find(toFind, 0);
       
   157 			while (fIdx != -1) {
       
   158 				attrVal.replace(fIdx, toFind.length(), toReplace);
       
   159 				fIdx = attrVal.find(toFind, 0);
       
   160 			}
       
   161 #endif
       
   162 			*mStreamP << " " << it.key() << "=\"" << attrVal << "\"";
   125 			++it;
   163 			++it;
   126 		}
   164 		}
   127 		// Update internals
   165 		// Update internals
   128 		mInElement = true;
   166 		mInElement = true;
   129 		mCanIndent = true;
   167 		//mCanIndent = true;
   130 		mElemStack.push(&aElemName);
   168 		mElemStack.push(&aElemName);
       
   169 		mCanIndentList.append(new bool(true));
   131 	}
   170 	}
   132 }
   171 }
   133 
   172 
   134 void XmlStream::characters(const QString& aText)
   173 void XmlStream::characters(const QString& aText)
   135 {
   174 {
   139 		if (mStreamP && mIsOpen && mCanWrite) {
   178 		if (mStreamP && mIsOpen && mCanWrite) {
   140 			closeElementDeclIfOpen();
   179 			closeElementDeclIfOpen();
   141 			*mStreamP << encodeText(aText);
   180 			*mStreamP << encodeText(aText);
   142 		}
   181 		}
   143 		// Don't indent mixed content
   182 		// Don't indent mixed content
   144 		mCanIndent = false;
   183 		//mCanIndent = false;
   145 	}
   184 		setLastIndent(false);
       
   185 	}
       
   186 #ifdef DITA_TRACE
       
   187 #ifdef DITA_TRACE_TO_XML
       
   188 	// Useful for assertion crashes where otherwise the buffer would be lost
       
   189 	flush(*mStreamP);
       
   190 #endif
       
   191 #endif
   146 }
   192 }
   147 
   193 
   148 void XmlStream::characters(char c)
   194 void XmlStream::characters(char c)
   149 {
   195 {
   150 	if (mStreamP && mIsOpen && mCanWrite) {
   196 	if (mStreamP && mIsOpen && mCanWrite) {
   158 		} else {
   204 		} else {
   159 			*mStreamP << ILLEGAL_UNICODE_REPLACEMENT;
   205 			*mStreamP << ILLEGAL_UNICODE_REPLACEMENT;
   160 		}
   206 		}
   161 	}
   207 	}
   162 	// Don't indent mixed content
   208 	// Don't indent mixed content
   163 	mCanIndent = false;
   209 	//mCanIndent = false;
       
   210 	setLastIndent(false);
       
   211 #ifdef DITA_TRACE
       
   212 #ifdef DITA_TRACE_TO_XML
       
   213 	// Useful for assertion crashes where otherwise the buffer would be lost
       
   214 	flush(*mStreamP);
       
   215 #endif
       
   216 #endif
   164 }
   217 }
   165 
   218 
   166 XmlStream& XmlStream::operator<<(const QCString& s)
   219 XmlStream& XmlStream::operator<<(const QCString& s)
   167 {
   220 {
   168     characters(s);
   221     characters(s);
   196 			cmtTxt += "\"";
   249 			cmtTxt += "\"";
   197 			comment(cmtTxt);
   250 			comment(cmtTxt);
   198 		}
   251 		}
   199 	}
   252 	}
   200 	// Don't indent mixed content
   253 	// Don't indent mixed content
   201 	mCanIndent = false;
   254 	//mCanIndent = false;
       
   255 	setLastIndent(false);
   202 	return *this;
   256 	return *this;
   203 }
   257 }
   204 
   258 
   205 void XmlStream::processingInstruction(const QString& aText)
   259 void XmlStream::processingInstruction(const QString& aText)
   206 {
   260 {
   207 	if (mStreamP && mIsOpen && mCanWrite) {
   261 	if (mStreamP && mIsOpen && mCanWrite) {
   208 		closeElementDeclIfOpen();
   262 		closeElementDeclIfOpen();
   209 		*mStreamP << "<?" << aText << "?>";
   263 		*mStreamP << "<?" << aText << "?>";
   210 	}
   264 	}
   211 	mCanIndent = true;
   265 	//mCanIndent = true;
   212 }
   266 }
   213 
   267 
   214 void XmlStream::comment(const QString& aText)
   268 void XmlStream::comment(const QString& aText)
   215 {
   269 {
   216 	if (mStreamP && mIsOpen && mCanWrite) {
   270 	if (mStreamP && mIsOpen && mCanWrite) {
   217 		closeElementDeclIfOpen();
   271 		closeElementDeclIfOpen();
   218 		*mStreamP << "<!-- " << aText << " -->";
   272 		*mStreamP << "<!-- " << aText << " -->";
   219 	}
   273 	}
   220 	mCanIndent = true;
   274 	//mCanIndent = true;
   221 }
   275 }
   222 
   276 
   223 void XmlStream::endElement(const QString& aElemName)
   277 void XmlStream::endElement(const QString& aElemName)
   224 {
   278 {
   225 	if (mStreamP && mIsOpen && mCanWrite) {
   279 	if (mStreamP && mIsOpen && mCanWrite) {
   231 		} else {
   285 		} else {
   232 			indent(1);
   286 			indent(1);
   233 			*mStreamP << "</" << *(mElemStack.pop()) << ">";
   287 			*mStreamP << "</" << *(mElemStack.pop()) << ">";
   234 		}
   288 		}
   235 	}
   289 	}
   236 	mCanIndent = true;
   290 	mCanIndentList.removeLast();
   237 }
   291 }
   238 
   292 
   239 void XmlStream::closeElementDeclIfOpen()
   293 void XmlStream::closeElementDeclIfOpen()
   240 {
   294 {
   241 	if (mStreamP && mIsOpen && mCanWrite) {
   295 	if (mStreamP && mIsOpen && mCanWrite) {
   246 	}
   300 	}
   247 }
   301 }
   248 
   302 
   249 void XmlStream::indent(unsigned int aInitVal)
   303 void XmlStream::indent(unsigned int aInitVal)
   250 {
   304 {
   251 	if (mStreamP && mIsOpen && mCanIndent && mCanWrite) {
   305 	if (mStreamP && mIsOpen && canIndent() && mCanWrite) {
   252 		*mStreamP << XML_OUTPUT_ENDL;
   306 		*mStreamP << XML_OUTPUT_ENDL;
   253 		for (unsigned int i = aInitVal; i < mElemStack.count(); i++) {
   307 		for (unsigned int i = aInitVal; i < mElemStack.count(); i++) {
   254 			*mStreamP << XML_INDENT;
   308 			*mStreamP << XML_INDENT;
   255 		}
   309 		}
   256 	}
   310 	}
   274 	// that appear in the source code from getting into the XML.
   328 	// that appear in the source code from getting into the XML.
   275 	bool result = (u == 0x09 || u == 0x0A || u == 0x0D || \
   329 	bool result = (u == 0x09 || u == 0x0A || u == 0x0D || \
   276 				((u >= 0x20) && (u <= 0x7F)) \
   330 				((u >= 0x20) && (u <= 0x7F)) \
   277 			);
   331 			);
   278 	if (!result) {
   332 	if (!result) {
   279 		printf("XmlStream::isLegalXmlChar() rejecting 0x%X\n", u);
   333 		msg("XmlStream::isLegalXmlChar() rejecting 0x%X\n", u);
   280 	}
   334 	}
   281 	return result;
   335 	return result;
   282 }
   336 }
   283 
   337 
   284 QString XmlStream::encodeText(const QString& aStr) const
   338 QString XmlStream::encodeText(const QString& aStr) const
   333 			break;
   387 			break;
   334 	}
   388 	}
   335 	return false;
   389 	return false;
   336 }
   390 }
   337 
   391 
       
   392 bool XmlStream::canIndent()
       
   393 {
       
   394 	bool *bP;
       
   395 	for (bP = mCanIndentList.first(); bP != 0; bP = mCanIndentList.next()) {
       
   396 		if (!*bP) {
       
   397 			return false;
       
   398 		}
       
   399 	}
       
   400 	return true;
       
   401 }
       
   402 
       
   403 void XmlStream::setLastIndent(bool theB)
       
   404 {
       
   405 	mCanIndentList.removeLast();
       
   406 	mCanIndentList.append(new bool(theB));
       
   407 }
       
   408 
   338 /// Suspend output
   409 /// Suspend output
   339 void XmlStream::outputSuspend()
   410 void XmlStream::outputSuspend()
   340 {
   411 {
   341 	mCanWrite = false;
   412 	mCanWrite = false;
   342 }
   413 }