//============================================================================= // MusE // Linux Music Score Editor // $Id: xml.cpp 2015 2009-08-14 15:58:17Z wschweer $ // // Copyright (C) 2002-2009 Werner Schweer and others // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //============================================================================= #include "xml.h" #include "al.h" namespace AL { QString docName; //--------------------------------------------------------- // Xml //--------------------------------------------------------- Xml::Xml() { stack.clear(); } Xml::Xml(QIODevice* device) : QTextStream(device) { setCodec("utf8"); stack.clear(); } //--------------------------------------------------------- // putLevel //--------------------------------------------------------- void Xml::putLevel() { int level = stack.size(); for (int i = 0; i < level * 2; ++i) *this << ' '; } //--------------------------------------------------------- // header //--------------------------------------------------------- void Xml::header() { *this << "\n"; } //--------------------------------------------------------- // stag // //--------------------------------------------------------- void Xml::stag(const QString& s) { putLevel(); *this << '<' << s << '>' << endl; stack.append(s.split(' ')[0]); } //--------------------------------------------------------- // etag // //--------------------------------------------------------- void Xml::etag() { putLevel(); *this << "' << endl; } //--------------------------------------------------------- // tagE // //--------------------------------------------------------- void Xml::tagE(const char* format, ...) { va_list args; va_start(args, format); putLevel(); *this << '<'; char buffer[BS]; vsnprintf(buffer, BS, format, args); *this << buffer; va_end(args); *this << "/>" << endl; } //--------------------------------------------------------- // tagE //--------------------------------------------------------- void Xml::tagE(const QString& s) { putLevel(); *this << '<' << s << "/>\n"; } //--------------------------------------------------------- // ntag // without newline //--------------------------------------------------------- void Xml::ntag(const char* name) { putLevel(); *this << "<" << name << ">"; } //--------------------------------------------------------- // netag // without indentation //--------------------------------------------------------- void Xml::netag(const char* s) { *this << "' << endl; } //--------------------------------------------------------- // tag // value //--------------------------------------------------------- void Xml::tag(const QString& name, QVariant data) { QString ename(name.split(' ')[0]); putLevel(); switch(data.type()) { case QVariant::Bool: case QVariant::Char: case QVariant::Int: case QVariant::UInt: *this << "<" << name << ">"; *this << data.toInt(); *this << "\n"; break; case QVariant::Double: *this << "<" << name << ">"; *this << data.value(); *this << "\n"; break; case QVariant::String: *this << "<" << name << ">"; *this << xmlString(data.value()); *this << "\n"; break; case QVariant::Color: { QColor color(data.value()); *this << QString("<%1 r=\"%2\" g=\"%3\" b=\"%4\"/>\n").arg(name).arg(color.red()).arg(color.green()).arg(color.blue()); } break; case QVariant::Rect: { QRect r(data.value()); *this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()); } break; case QVariant::RectF: { QRectF r(data.value()); *this << QString("<%1 x=\"%2\" y=\"%3\" w=\"%4\" h=\"%5\"/>\n").arg(name).arg(r.x()).arg(r.y()).arg(r.width()).arg(r.height()); } break; case QVariant::PointF: { QPointF p(data.value()); *this << QString("<%1 x=\"%2\" y=\"%3\"/>\n").arg(name).arg(p.x()).arg(p.y()); } break; case QVariant::SizeF: { QSizeF p(data.value()); *this << QString("<%1 w=\"%2\" h=\"%3\"/>\n").arg(name).arg(p.width()).arg(p.height()); } break; default: printf("Xml::tag: unsupported type %d\n", data.type()); // abort(); break; } } void Xml::tag(const char* name, const QWidget* g) { tag(name, QRect(g->pos(), g->size())); } //--------------------------------------------------------- // xmlString //--------------------------------------------------------- QString Xml::xmlString(const QString& ss) { QString s(ss); s.replace('&', "&"); s.replace('<', "<"); s.replace('>', ">"); s.replace('\'', "'"); s.replace('"', """); return s; } //--------------------------------------------------------- // dump //--------------------------------------------------------- void Xml::dump(int len, const unsigned char* p) { putLevel(); int col = 0; setFieldWidth(5); setNumberFlags(numberFlags() | QTextStream::ShowBase); setIntegerBase(16); for (int i = 0; i < len; ++i, ++col) { if (col >= 16) { setFieldWidth(0); *this << endl; col = 0; putLevel(); setFieldWidth(5); } *this << (p[i] & 0xff); } if (col) *this << endl << dec; setFieldWidth(0); setIntegerBase(10); } //--------------------------------------------------------- // readPoint //--------------------------------------------------------- QPointF readPoint(QDomElement e) { QPointF p; p.setX(e.attribute("x", "0.0").toDouble()); p.setY(e.attribute("y", "0.0").toDouble()); return p; } //--------------------------------------------------------- // readColor //--------------------------------------------------------- QColor readColor(QDomElement e) { QColor c; c.setRed(e.attribute("r").toInt()); c.setGreen(e.attribute("g").toInt()); c.setBlue(e.attribute("b").toInt()); return c; } //--------------------------------------------------------- // readSize //--------------------------------------------------------- QSizeF readSize(QDomElement e) { QSizeF p; p.setWidth(e.attribute("w", "0.0").toDouble()); p.setHeight(e.attribute("h", "0.0").toDouble()); return p; } //--------------------------------------------------------- // readRectF //--------------------------------------------------------- QRectF readRectF(QDomElement e) { QRectF p; p.setX(e.attribute("x", "0.0").toDouble()); p.setY(e.attribute("y", "0.0").toDouble()); p.setWidth(e.attribute("w", "0.0").toDouble()); p.setHeight(e.attribute("h", "0.0").toDouble()); return p; } //--------------------------------------------------------- // printDomElementPath //--------------------------------------------------------- static QString domElementPath(QDomElement e) { QString s; QDomNode dn(e); while (!dn.parentNode().isNull()) { dn = dn.parentNode(); const QDomElement e = dn.toElement(); const QString k(e.tagName()); if (!s.isEmpty()) s += ":"; s += k; } return s; } //--------------------------------------------------------- // domError //--------------------------------------------------------- void domError(QDomElement e) { QString s = domElementPath(e); if (!docName.isEmpty()) fprintf(stderr, "<%s>:", qPrintable(docName)); int ln = e.lineNumber(); if (ln != -1) fprintf(stderr, "line:%d ", ln); int col = e.columnNumber(); if (col != -1) fprintf(stderr, "col:%d ", col); fprintf(stderr, "%s: Unknown Node <%s>, type %d\n", qPrintable(s), qPrintable(e.tagName()), e.nodeType()); if (e.isText()) fprintf(stderr, " text node <%s>\n", qPrintable(e.toText().data())); } //--------------------------------------------------------- // domNotImplemented //--------------------------------------------------------- void domNotImplemented(QDomElement e) { if (!debugMsg) return; QString s = domElementPath(e); if (!docName.isEmpty()) fprintf(stderr, "<%s>:", qPrintable(docName)); fprintf(stderr, "%s: Node not implemented: <%s>, type %d\n", qPrintable(s), qPrintable(e.tagName()), e.nodeType()); if (e.isText()) fprintf(stderr, " text node <%s>\n", qPrintable(e.toText().data())); } //--------------------------------------------------------- // htmlToString //--------------------------------------------------------- void Xml::htmlToString(QDomElement e, int level, QString* s) { *s += QString("<%1").arg(e.tagName()); QDomNamedNodeMap map = e.attributes(); int n = map.size(); for (int i = 0; i < n; ++i) { QDomAttr a = map.item(i).toAttr(); *s += QString(" %1=\"%2\"").arg(a.name()).arg(a.value()); } *s += ">"; ++level; for (QDomNode ee = e.firstChild(); !ee.isNull(); ee = ee.nextSibling()) { if (ee.nodeType() == QDomNode::ElementNode) htmlToString(ee.toElement(), level, s); else if (ee.nodeType() == QDomNode::TextNode) *s += Qt::escape(ee.toText().data()); } *s += QString("").arg(e.tagName()); --level; } QString Xml::htmlToString(QDomElement e) { QString s; htmlToString(e, 0, &s); return s; } //--------------------------------------------------------- // writeHtml //--------------------------------------------------------- void Xml::writeHtml(const QString& s) { QStringList sl(s.split("\n")); // // remove first line from html (DOCTYPE...) // for (int i = 1; i < sl.size(); ++i) *this << sl[i] << "\n"; } } // namespace al