QT读写改XML格式文件

最近因业务需要,需要更改XML文件中某一结点的值,于是搜索相关资料,但是网上搜出来资料的没有详细解释,好不容易才搞明白,因此,特写一篇明白易懂的文章,以供各位少走弯路。

本人采用的是QDom方式读写XML,然后用QTreeWidget显示。

最终达到的目的是:
首先,通过代码创建一个XML文件,例如:
XML
然后更改其中的Text节点的内容,就像这样:
XML
最后再用程序读出来:
读取

话不多说,先上代码,最后再解释:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTreeWidget>
#include <QFrame>

//自定义对象--输入
typedef struct FileInput
{
    QString     Name;
    int         Text;
    int         Count;
}FileInput;

//自定义对象--接收
typedef struct FileReceive
{
    QString     Name;
    int         Text;
    int         Count;
}FileReceive;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QTreeWidget* m_pTreeWidget;
    QFrame* m_pTreeFrame;
    FileInput inputFile;

    void openFile(QString path);//读取XML
    void changeXML(QString path);//更改XML

private slots:
    void slot_readXMl();
    void slot_saveXMl();//写XML
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include <QPushButton>
#include <QHBoxLayout>
#include <QFile>
#include <QFileDialog>
#include <QDomDocument>
#include <QTextStream>
#include <QDebug>
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setMinimumSize(400,400);
    setMaximumSize(400,400);

    m_pTreeWidget = new QTreeWidget(this);
    m_pTreeWidget->setGeometry(0,0,400,300);

    QFrame* pButtonFrame = new QFrame(this);
    pButtonFrame->setGeometry(0,300,400,100);

    QPushButton* pReadBtn = new QPushButton(pButtonFrame);
    pReadBtn->setText("保存XML");
    connect(pReadBtn,SIGNAL(clicked()),this,SLOT(slot_saveXMl()));

    QPushButton* pQuitBtn = new QPushButton(pButtonFrame);
    pQuitBtn->setText("读取XML");
    connect(pQuitBtn,SIGNAL(clicked()),this,SLOT(slot_readXMl()));

    QHBoxLayout* pHLayout = new QHBoxLayout(pButtonFrame);
    pHLayout->addWidget(pReadBtn);
    pHLayout->addWidget(pQuitBtn);

    inputFile.Name = "Name";
    inputFile.Text = 10086;
    inputFile.Count = 2;
}

MainWindow::~MainWindow()
{

}

//读取XML
void MainWindow::openFile(QString path)
{
    changeXML(path); //更改XML

    FileReceive receiveFile;
    QString name;
    QDomDocument doc;
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly))
    {
        return;
    }
    if (!doc.setContent(&file))
    {
        file.close();
        return;
    }
    QDomElement rootElem = doc.documentElement();
    QDomNode rootNode = rootElem.firstChild();
    QTreeWidgetItem *root = new QTreeWidgetItem(m_pTreeWidget, QStringList(rootElem.tagName()));
    while(!rootNode.isNull())
    {
        QDomElement fileElem = rootNode.toElement();
        if(!fileElem.isNull())
        {
            name = fileElem.tagName();
            if(name == "Name")
            {
                for(QDomNode childNode = fileElem.firstChild(); !childNode.isNull();
                    childNode = childNode.nextSibling())
                {
                    QDomText childText = childNode.toText();
                    receiveFile.Name = childText.data();
                    QTreeWidgetItem *itemFileName = new QTreeWidgetItem(root,
                                                                        QStringList(name+tr("     ")+receiveFile.Name));
                    root->addChild(itemFileName);
                }
            }
            else if(name == "Text")
            {
                for(QDomNode childNode = fileElem.firstChild(); !childNode.isNull();
                    childNode = childNode.nextSibling())
                {
                    QDomText childText = childNode.toText();
                    receiveFile.Text = childText.data().toInt();
                    QTreeWidgetItem *itemText = new QTreeWidgetItem(root,
                                                                    QStringList(name+tr("     ")
                                                                                +QString("%1").arg(receiveFile.Text)));
                    root->addChild(itemText);
                }
            }
            else if(name == "Count")
            {
                for(QDomNode childNode = fileElem.firstChild(); !childNode.isNull();
                    childNode = childNode.nextSibling())
                {
                    QDomText childText = childNode.toText();
                    receiveFile.Count = childText.data().toInt();
                    QTreeWidgetItem *itemCount = new QTreeWidgetItem(root,
                                                                     QStringList(name+tr("     ")
                                                                                 +QString("%1").arg(receiveFile.Count)));
                    root->addChild(itemCount);
                }
            }
        }
        rootNode = rootNode.nextSibling();
    }
    file.close();
}

//更改XML
void MainWindow::changeXML(QString path)
{
    QString name;
    QDomDocument doc;
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly))
    {
        return;
    }
    if (!doc.setContent(&file))
    {
        file.close();
        return;
    }

    file.close();

    QDomElement rootElem = doc.documentElement();
    QDomNode rootNode = rootElem.firstChild();
    while(!rootNode.isNull())
    {
        QDomElement fileElem = rootNode.toElement();
        if(!fileElem.isNull())
        {
            name = fileElem.tagName();
            if(name == "Text")
            {
                QDomElement newnode = doc.createElement("Text");
                QDomText text = doc.createTextNode("10000");
                newnode.appendChild(text);
                rootElem.replaceChild(newnode,rootNode);
            }
        }
        rootNode = rootNode.nextSibling();
    }

    QString xml = doc.toString();

    if(!file.open(QFile::WriteOnly|QFile::Truncate))
    {
        return;
    }

    QTextStream out(&file);
    out<<xml;
    file.close();
}

//写XML
void MainWindow::slot_saveXMl()
{
    QString dirPath = QFileDialog::getSaveFileName (this,tr("save file"),
                                                    " ",tr("XML files (*.xml)"));
    QDomDocument doc;
    QString strHeader("version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild( doc.createProcessingInstruction("xml", strHeader));
    QFile file(dirPath);
    if (!file.open(QIODevice::WriteOnly))
    {
        return;
    }
    QDomElement rootFile = doc.createElement("File");
    doc.appendChild(rootFile);
    QDomElement rootFileName = doc.createElement("Name");
    rootFile.appendChild(rootFileName);
    QDomText textFileName = doc.createTextNode(inputFile.Name);
    rootFileName.appendChild(textFileName);

    QDomElement rootText = doc.createElement("Text");
    rootFile.appendChild(rootText);
    QDomText textText = doc.createTextNode(QString("%1").arg(inputFile.Text));
    rootText.appendChild(textText);

    QDomElement rootCount = doc.createElement("Count");
    rootFile.appendChild(rootCount);
    QDomText textCount = doc.createTextNode(QString("%1").arg(inputFile.Count));
    rootCount.appendChild(textCount);

    QString xml = doc.toString();

    QTextStream txtOutput(&file);
    txtOutput<<xml;
    file.close();
}

void MainWindow::slot_readXMl()
{
    QString filePath = QFileDialog::getOpenFileName(this,tr("open file")," ",
                                                    tr("XML files (*.xml);;ALL files (*.*)"));
    openFile(filePath);
}

代码解释如下:
这里我用两个结构体储存XML文件的值,写的时候从结构体读值,读的时候,将值写入结构体中,方便调用,当然,你也可以直接读取,相信看一下Qt帮助文档就可以轻松操作,在这里,我主要解释一下修改XML中结点的代码。
我这里使用的changeXML(QString path)函数,更改的。

//更改XML
void MainWindow::changeXML(QString path)
{
    QString name;
    QDomDocument doc;
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly))
    {
        return;
    }
    if (!doc.setContent(&file))
    {
        file.close();
        return;
    }

    file.close();

    QDomElement rootElem = doc.documentElement();
    QDomNode rootNode = rootElem.firstChild();
    while(!rootNode.isNull())
    {
        QDomElement fileElem = rootNode.toElement();
        if(!fileElem.isNull())
        {
            name = fileElem.tagName();
            if(name == "Text")
            {
                QDomElement newnode = doc.createElement("Text");
                QDomText text = doc.createTextNode("10000");
                newnode.appendChild(text);
                rootElem.replaceChild(newnode,rootNode);
            }
        }
        rootNode = rootNode.nextSibling();
    }

    QString xml = doc.toString();

    if(!file.open(QFile::WriteOnly|QFile::Truncate))
    {
        return;
    }

    QTextStream out(&file);
    out<<xml;
    file.close();
}

首先和读取XML文件一样,先遍历,当遍历到想要更改的节点时(我这里是Text节点),中心思想是,再写一个更改后的Text结点,然后用replaceChild(const QDomNode &newChild, const QDomNode &oldChild)函数更改。
如图:
这里写图片描述
仔细观察,可以发现,这和写XML文件时操作基本一样:
这里写图片描述
上图是写XML文件,只不过把中间的添加结点去掉了,最后用replaceChild()实现替换。

记住,更改完最后一定要重新载入XML,要不然无法更改,即

 QString xml = doc.toString();

    if(!file.open(QFile::WriteOnly|QFile::Truncate))
    {
        return;
    }

    QTextStream out(&file);
    out<<xml;
    file.close();

不可省略!!!!!

最后,附上一张图,提示一下其他注意事项
这里写图片描述
rootNode为旧的节点,即待更改的节点。

最终实现结果:
首先将更改XML语句注释掉。
这里写图片描述
点击保存XML
这里写图片描述
保存
这里写图片描述
打开看一下,写XML成功
这里写图片描述
再点击读取XML
这里写图片描述
读取成功
这里写图片描述
将更改XML注释去掉
这里写图片描述
再点击读取XML
这里写图片描述
更改成功,读取成功
这里写图片描述
打开XML文件看一下
这里写图片描述

源码下载:http://download.csdn.net/download/fan_xingwang/10246768

猜你喜欢

转载自blog.csdn.net/fan_xingwang/article/details/79295667
今日推荐