Qt:QXMLStreamReader、QXMLStreamWriter,讀寫XML檔案例項
阿新 • • 發佈:2019-01-26
效果圖:
需求:
開啟對應格式的XML檔案,讀入到QTreewidget樹中,並能將XML檔案另存為,寫入到磁碟。
原始碼:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
XbelReader.h
#ifndef XBELREADER_H #define XBELREADER_H #include <QIcon> #include <QXmlStreamReader> #include <QTreeWidget> #include <QTreeWidgetItem> #include <QIcon> class XbelReader { public: XbelReader(QTreeWidget *tree); bool read(QIODevice *device); QString errorString()const; private: void readXBEL(); void readTitle(QTreeWidgetItem *item); void readSeparator(QTreeWidgetItem *item); void readFolder(QTreeWidgetItem *item); void readBookmark(QTreeWidgetItem *item); QTreeWidgetItem *createChildItem(QTreeWidgetItem *item); private: QXmlStreamReader xml; QTreeWidget *treeWidget; QIcon folderIcon; QIcon bookmarkIcon; }; #endif // XBELREADER_H
XbelReader.cpp
#include <QStyle> #include <QDebug> #include "xbelreader.h" XbelReader::XbelReader(QTreeWidget *tree) { treeWidget = tree; QStyle *style = treeWidget->style(); folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirClosedIcon), QIcon::Normal,QIcon::Off); folderIcon.addPixmap(style->standardPixmap(QStyle::SP_DirOpenIcon), QIcon::Normal,QIcon::On); bookmarkIcon.addPixmap(style->standardPixmap(QStyle::SP_FileIcon)); } bool XbelReader::read(QIODevice *device) { xml.setDevice(device); if (xml.readNextStartElement()) // { if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0") readXBEL(); else xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file.")); } return !xml.error(); //非運算,有錯返回0,無錯返回1 } QString XbelReader::errorString() const { return QObject::tr("%1\nLine %2, column %3") .arg(xml.errorString()) .arg(xml.lineNumber()) .arg(xml.columnNumber()); } void XbelReader::readXBEL() { Q_ASSERT(xml.isStartElement() && xml.name() == "xbel"); while (xml.readNextStartElement()) { if (xml.name() == "folder") readFolder(0); else if (xml.name() == "bookmark") readBookmark(0); else if (xml.name() == "separator") readSeparator(0); else xml.skipCurrentElement(); } } void XbelReader::readTitle(QTreeWidgetItem *item) { Q_ASSERT(xml.isStartElement() && xml.name() == "title"); QString title = xml.readElementText(); item->setText(0,title); } void XbelReader::readSeparator(QTreeWidgetItem *item) { Q_ASSERT(xml.isStartElement() && xml.name() == "separator"); QTreeWidgetItem *separator = createChildItem(item); separator->setFlags(item->flags() & ~Qt::ItemIsSelectable); separator->setText(0,QString(30,0xB7)); xml.skipCurrentElement(); } void XbelReader::readFolder(QTreeWidgetItem *item) { Q_ASSERT(xml.isStartElement() && xml.name() == "folder"); QTreeWidgetItem *folder = createChildItem(item); bool folded = (xml.attributes().value("folded") != "no"); treeWidget->setItemExpanded(folder, !folded); while (xml.readNextStartElement()) { if (xml.name() == "title") readTitle(folder); else if (xml.name() == "folder") readFolder(folder); else if (xml.name() == "bookmark") readBookmark(folder); else if (xml.name() == "separator") readSeparator(folder); else xml.skipCurrentElement(); } } void XbelReader::readBookmark(QTreeWidgetItem *item) { Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark"); QTreeWidgetItem *bookmark = createChildItem(item); bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable); bookmark->setIcon(0,bookmarkIcon); bookmark->setText(0,QObject::tr("Unknown title")); bookmark->setText(1,xml.attributes().value("href").toString()); while(xml.readNextStartElement()) { if(xml.name() == "title") readTitle(bookmark); else xml.skipCurrentElement(); } } QTreeWidgetItem *XbelReader::createChildItem(QTreeWidgetItem *item) { QTreeWidgetItem *childItem; if (item) { childItem = new QTreeWidgetItem(item); } else { childItem = new QTreeWidgetItem(treeWidget); } childItem->setData(0, Qt::UserRole, xml.name().toString()); return childItem; }
XbelWriter.h
#ifndef XBELWRITER_H #define XBELWRITER_H #include <QXmlStreamWriter> #include <QTreeWidget> #include <QTreeWidgetItem> class XbelWriter { public: XbelWriter(QTreeWidget *tree); bool writeFile(QIODevice *device); private: void writeItem(QTreeWidgetItem *item); QXmlStreamWriter xml; QTreeWidget *treeWidget; }; #endif // XBELWRITER_H
XbelWriter.cpp
#include "xbelwriter.h"
XbelWriter::XbelWriter(QTreeWidget *tree)
{
treeWidget = tree;
xml.setAutoFormatting(true); //自動格式化文字
}
bool XbelWriter::writeFile(QIODevice *device)
{
xml.setDevice(device);
xml.writeStartDocument();
xml.writeDTD("<!DOCTYPE xbel>");
xml.writeStartElement("xbel");
xml.writeAttribute("version", "1.0");
for(int i=0 ; i < treeWidget->topLevelItemCount() ; ++i)
writeItem(treeWidget->topLevelItem(i));
xml.writeEndDocument();
return true;
}
void XbelWriter::writeItem(QTreeWidgetItem *item)
{
QString tagName = item->data(0, Qt::UserRole).toString();
if(tagName == "folder")
{
bool folded = !treeWidget->isItemExpanded(item);
xml.writeStartElement(tagName);
xml.writeAttribute("folded",folded ? "yes" : "no");//三目運算
xml.writeTextElement("title", item->text(0));
for(int i=0 ; i<item->childCount() ; ++i)
writeItem(item->child(i));
xml.writeEndElement();
}
else if(tagName == "bookmark")
{
xml.writeStartElement(tagName);
if(!item->text(1).isEmpty())
xml.writeAttribute("href", item->text(1));
xml.writeTextElement("title" , item->text(0));
xml.writeEndElement();
}
else if(tagName == "separator")
{
xml.writeEmptyElement(tagName);
}
}