1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the qmake application of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "xmloutput.h"
31
XmlOutput::XmlOutput(QTextStream &file, ConverstionType type)
32
: xmlFile(file), indent("\t"), currentLevel(0), currentState(Bare), format(NewLine),
38
XmlOutput::~XmlOutput()
43
// Settings ------------------------------------------------------------------
44
void XmlOutput::setIndentString(const QString &indentString)
46
indent = indentString;
49
QString XmlOutput::indentString()
54
void XmlOutput::setIndentLevel(int level)
59
int XmlOutput::indentLevel()
64
void XmlOutput::setState(XMLState state)
69
XmlOutput::XMLState XmlOutput::state()
74
void XmlOutput::updateIndent()
76
currentIndent.clear();
77
for (int i = 0; i < currentLevel; ++i)
78
currentIndent.append(indent);
81
void XmlOutput::increaseIndent()
87
void XmlOutput::decreaseIndent()
96
QString XmlOutput::doConversion(const QString &text)
100
else if (conversion == NoConversion)
103
QString output(text);
104
if (conversion == XMLConversion) {
105
output.replace('&', "&");
106
output.replace('\"', """);
107
output.replace('\'', "'");
108
} else if (conversion == EscapeConversion) {
109
output.replace('\"', "\\\"");
110
output.replace('\'', "\\\'");
115
// Stream functions ----------------------------------------------------------
116
XmlOutput& XmlOutput::operator<<(const QString& o)
118
return operator<<(data(o));
121
XmlOutput& XmlOutput::operator<<(const xml_output& o)
130
addDeclaration(o.xo_text, o.xo_value);
133
newTagOpen(o.xo_text);
136
if (o.xo_value.count())
138
else if (o.xo_text.count())
144
addAttribute(o.xo_text, o.xo_value);
148
// Special case to be able to close tag in normal
149
// way ("</tag>", not "/>") without using addRaw()..
150
if (!o.xo_text.count()) {
154
QString output = doConversion(o.xo_text);
155
output.replace('\n', "\n" + currentIndent);
156
addRaw(QString("\n%1%2").arg(currentIndent).arg(output));
161
QString output("<!--%1-->");
162
addRaw(output.arg(o.xo_text));
167
QString output("<![CDATA[\n%1\n]]>");
168
addRaw(output.arg(o.xo_text));
176
// Output functions ----------------------------------------------------------
177
void XmlOutput::newTag(const QString &tag)
179
Q_ASSERT_X(tag.count(), "XmlOutput", "Cannot open an empty tag");
184
void XmlOutput::newTagOpen(const QString &tag)
186
Q_ASSERT_X(tag.count(), "XmlOutput", "Cannot open an empty tag");
189
if (format == NewLine)
190
xmlFile << endl << currentIndent;
191
xmlFile << '<' << doConversion(tag);
192
currentState = Attribute;
193
tagStack.append(tag);
194
increaseIndent(); // ---> indent
197
void XmlOutput::closeOpen()
199
switch(currentState) {
210
void XmlOutput::closeTag()
212
switch(currentState) {
214
if (tagStack.count())
215
//warn_msg(WarnLogic, "<Root>: Cannot close tag in Bare state, %d tags on stack", tagStack.count());
216
qDebug("<Root>: Cannot close tag in Bare state, %d tags on stack", tagStack.count());
218
//warn_msg(WarnLogic, "<Root>: Cannot close tag, no tags on stack");
219
qDebug("<Root>: Cannot close tag, no tags on stack");
222
decreaseIndent(); // <--- Pre-decrease indent
223
if (format == NewLine)
224
xmlFile << endl << currentIndent;
225
xmlFile << "</" << doConversion(tagStack.last()) << '>';
232
decreaseIndent(); // <--- Post-decrease indent
237
void XmlOutput::closeTo(const QString &tag)
240
if (!tagStack.contains(tag) && tag != QString()) {
241
//warn_msg(WarnLogic, "<%s>: Cannot close to tag <%s>, not on stack", tagStack.last().latin1(), tag.latin1());
242
qDebug("<%s>: Cannot close to tag <%s>, not on stack", tagStack.last().toLatin1().constData(), tag.toLatin1().constData());
245
int left = tagStack.count();
246
while (left-- && cont) {
247
cont = tagStack.last().compare(tag) != 0;
252
void XmlOutput::closeAll()
254
if (!tagStack.count())
259
void XmlOutput::addDeclaration(const QString &version, const QString &encoding)
261
switch(currentState) {
266
//warn_msg(WarnLogic, "<%s>: Cannot add declaration when not in bare state", tagStack.last().toLatin1().constData());
267
qDebug("<%s>: Cannot add declaration when not in bare state", tagStack.last().toLatin1().constData());
270
QString outData = QString("<?xml version=\"%1\" encoding = \"%2\"?>")
271
.arg(doConversion(version))
272
.arg(doConversion(encoding));
276
void XmlOutput::addRaw(const QString &rawText)
282
void XmlOutput::addAttribute(const QString &attribute, const QString &value)
284
switch(currentState) {
287
//warn_msg(WarnLogic, "<%s>: Cannot add attribute since tags not open", tagStack.last().toLatin1().constData());
288
qDebug("<%s>: Cannot add attribute (%s) since tag's not open",
289
(tagStack.count() ? tagStack.last().toLatin1().constData() : "Root"),
290
attribute.toLatin1().constData());
295
if (format == NewLine)
297
xmlFile << currentIndent << doConversion(attribute) << "=\"" << doConversion(value) << "\"";