/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the qmake application of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://qt.nokia.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "xmloutput.h" QT_BEGIN_NAMESPACE XmlOutput::XmlOutput(QTextStream &file, ConverstionType type) : xmlFile(file), indent("\t"), currentLevel(0), currentState(Bare), format(NewLine), conversion(type) { tagStack.clear(); } XmlOutput::~XmlOutput() { closeAll(); } // Settings ------------------------------------------------------------------ void XmlOutput::setIndentString(const QString &indentString) { indent = indentString; } QString XmlOutput::indentString() { return indent; } void XmlOutput::setIndentLevel(int level) { currentLevel = level; } int XmlOutput::indentLevel() { return currentLevel; } void XmlOutput::setState(XMLState state) { currentState = state; } XmlOutput::XMLState XmlOutput::state() { return currentState; } void XmlOutput::updateIndent() { currentIndent.clear(); for (int i = 0; i < currentLevel; ++i) currentIndent.append(indent); } void XmlOutput::increaseIndent() { ++currentLevel; updateIndent(); } void XmlOutput::decreaseIndent() { if (currentLevel) --currentLevel; updateIndent(); if (!currentLevel) currentState = Bare; } QString XmlOutput::doConversion(const QString &text) { if (!text.count()) return QString(); else if (conversion == NoConversion) return text; QString output; if (conversion == XMLConversion) { // this is a way to escape characters that shouldn't be converted for (int i=0; i", not "/>") without using addRaw().. if (!o.xo_text.count()) { closeOpen(); break; } QString output = doConversion(o.xo_text); output.replace('\n', "\n" + currentIndent); addRaw(QString("\n%1%2").arg(currentIndent).arg(output)); } break; case tComment: { QString output(""); addRaw(output.arg(o.xo_text)); } break; case tCDATA: { QString output(""); addRaw(output.arg(o.xo_text)); } break; } return *this; } // Output functions ---------------------------------------------------------- void XmlOutput::newTag(const QString &tag) { Q_ASSERT_X(tag.count(), "XmlOutput", "Cannot open an empty tag"); newTagOpen(tag); closeOpen(); } void XmlOutput::newTagOpen(const QString &tag) { Q_ASSERT_X(tag.count(), "XmlOutput", "Cannot open an empty tag"); closeOpen(); if (format == NewLine) xmlFile << endl << currentIndent; xmlFile << '<' << doConversion(tag); currentState = Attribute; tagStack.append(tag); increaseIndent(); // ---> indent } void XmlOutput::closeOpen() { switch(currentState) { case Bare: case Tag: return; case Attribute: break; } xmlFile << '>'; currentState = Tag; } void XmlOutput::closeTag() { switch(currentState) { case Bare: if (tagStack.count()) //warn_msg(WarnLogic, ": Cannot close tag in Bare state, %d tags on stack", tagStack.count()); qDebug(": Cannot close tag in Bare state, %d tags on stack", tagStack.count()); else //warn_msg(WarnLogic, ": Cannot close tag, no tags on stack"); qDebug(": Cannot close tag, no tags on stack"); return; case Tag: decreaseIndent(); // <--- Pre-decrease indent if (format == NewLine) xmlFile << endl << currentIndent; xmlFile << "'; tagStack.pop_back(); break; case Attribute: xmlFile << "/>"; tagStack.pop_back(); currentState = Tag; decreaseIndent(); // <--- Post-decrease indent break; } } void XmlOutput::closeTo(const QString &tag) { bool cont = true; if (!tagStack.contains(tag) && !tag.isNull()) { //warn_msg(WarnLogic, "<%s>: Cannot close to tag <%s>, not on stack", tagStack.last().latin1(), tag.latin1()); qDebug("<%s>: Cannot close to tag <%s>, not on stack", tagStack.last().toLatin1().constData(), tag.toLatin1().constData()); return; } int left = tagStack.count(); while (left-- && cont) { cont = tagStack.last().compare(tag) != 0; closeTag(); } } void XmlOutput::closeAll() { if (!tagStack.count()) return; closeTo(QString()); } void XmlOutput::addDeclaration(const QString &version, const QString &encoding) { switch(currentState) { case Bare: break; case Tag: case Attribute: //warn_msg(WarnLogic, "<%s>: Cannot add declaration when not in bare state", tagStack.last().toLatin1().constData()); qDebug("<%s>: Cannot add declaration when not in bare state", tagStack.last().toLatin1().constData()); return; } QString outData = QString("") .arg(doConversion(version)) .arg(doConversion(encoding)); addRaw(outData); } void XmlOutput::addRaw(const QString &rawText) { closeOpen(); xmlFile << rawText; } void XmlOutput::addAttribute(const QString &attribute, const QString &value) { switch(currentState) { case Bare: case Tag: //warn_msg(WarnLogic, "<%s>: Cannot add attribute since tags not open", tagStack.last().toLatin1().constData()); qDebug("<%s>: Cannot add attribute (%s) since tag's not open", (tagStack.count() ? tagStack.last().toLatin1().constData() : "Root"), attribute.toLatin1().constData()); return; case Attribute: break; } if (format == NewLine) xmlFile << endl; xmlFile << currentIndent << doConversion(attribute) << "=\"" << doConversion(value) << "\""; } QT_END_NAMESPACE