【Qt】DOM创建和操作XML文档

00. 目录

01. 概述

使用代码来创建XML文档,并且实现查找、更新、插入等操作。

02. 开发环境

Windows系统:Windows10

Qt版本:Qt5.15或者Qt6

03. 创建XML文档

3.1 新建Qt Widgets应用,项目名称为17XML,基类选择QMainWindow,类名为MainWindow。

3.2 打开17XML.pro文件,添加xml模块

QT       += core gui xml

3.3 进入设计模式,往界面上添加Push Button,Label,Line Edit,List Widget等部件,设计界面如下图所示。
在这里插入图片描述

3.4 mainwindow.cpp文件中构造函数实现如下:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QFile file("test.xml");

    bool ret = file.open(QIODevice::WriteOnly | QIODevice::Truncate);
    if (!ret)
    {
        qDebug() << "打开文件失败";
        return;
    }

    //创建文档
    QDomDocument doc;

    //添加处理指令
    QDomProcessingInstruction instruction;
    instruction = doc.createProcessingInstruction("xml",
                                 "version=\\"1.0\\" encoding=\\"UTF-8\\"");
    doc.appendChild(instruction);

    QDomElement root =doc.createElement(tr("书库"));
    //添加根元素
    doc.appendChild(root);


    //添加第一个book元素及其子元素
    QDomElement book = doc.createElement(tr("图书"));
    QDomAttr id = doc.createAttribute(tr("编号"));
    QDomElement title = doc.createElement(tr("书名"));
    QDomElement author = doc.createElement(tr("作者"));
    QDomText text;
    id.setValue("1");
    book.setAttributeNode(id);
    text = doc.createTextNode("Qt");
    title.appendChild(text);
    text = doc.createTextNode("shiming");
    author.appendChild(text);
    book.appendChild(title);
    book.appendChild(author);
    root.appendChild(book);

    //添加第二个book元素及其子元素
    book = doc.createElement(tr("图书"));
    id = doc.createAttribute(tr("编号"));
    title = doc.createElement(tr("书名"));
    author = doc.createElement(tr("作者"));
    id.setValue("2");
    book.setAttributeNode(id);
    text = doc.createTextNode("Linux");
    title.appendChild(text);
    text = doc.createTextNode("LiMing");
    author.appendChild(text);
    book.appendChild(title);
    book.appendChild(author);
    root.appendChild(book);

    QTextStream out(&file);
    doc.save(out, 4);
    file.close();

}

里先使用QDomDocument类在内存中生成了一棵DOM树,然后调用save()函数利用QTextStream文本流将DOM树保存在了文件中。在生成DOM树时主要使用了createElement()等函数来生成各种节点,然后使用appendChild()将各个节点依次追加进去。

执行程序之后,打开生成的text.xml文件内容如下

<?xml version="1.0" encoding="UTF-8"?>
<书库>
    <图书 编号="1">
        <书名>Qt</书名>
        <作者>shiming</作者>
    </图书>

    <图书 编号="2">
        <书名>Linux</书名>
        <作者>LiMing</作者>
    </图书>
</书库>

04. 读取XML文档

读取整个文档的内容,并显示在List Widget部件上面,这里用的就是上一节讲到的内容。我们从设计模式进入“查看全部信息”按钮单击信号槽,更改如下:

//查看全部信息
void MainWindow::on_pushButton_5_clicked()
{
    //清空内容
    ui->listWidget->clear();

    QFile file("test.xml");
    if (!file.open(QIODevice::ReadOnly))
    {
        return;
    }

    QDomDocument doc;
    if (!doc.setContent(&file))
    {
        file.close();
        return;
    }
    file.close();

    //返回根节点及其子节点的元素标记名
    //返回根元素
    QDomElement docElem = doc.documentElement();
    //返回根节点的第一个子节点
    QDomNode n = docElem.firstChild();

    while(!n.isNull())
    {
        //如果子节点是元素
        if (n.isElement())
        {
            //将其转换为元素
            QDomElement e = n.toElement();
            ui->listWidget->addItem(e.tagName() + e.attribute(tr("编号")));

            QDomNodeList list = e.childNodes();
            for (int i = 0; i < list.count(); i++)
            {
                QDomNode node = list.at(i);
                if (node.isElement())
                {
                    ui->listWidget->addItem(" " + node.toElement().tagName()
                                            + " : " + node.toElement().text());
                }
            }
        }

        n = n.nextSibling();
    }
}

执行程序,结果如下:
在这里插入图片描述

05. 增加XML节点

5.1 首先在设计模式,把书名和作者标签后面的Line Edit部件的objectName分别更改为lineEdit_title和lineEdit_author。

5.2 进入添加按钮的单击信号槽,添加如下代码:

//添加按钮
void MainWindow::on_pushButton_3_clicked()
{
    //我们先清空显示,然后显示“无法添加!”
    ui->listWidget->clear();
    ui->listWidget->addItem(tr("无法添加!"));

    QFile file("test.xml");
    if (!file.open(QIODevice::ReadOnly))
        return;

    QDomDocument doc;
    if (!doc.setContent(&file))
    {
        file.close();
        return;
    }

    file.close();

    QDomElement root = doc.documentElement();
    QDomElement book = doc.createElement("图书");
    QDomAttr id = doc.createAttribute("编号");
    QDomElement title = doc.createElement("书名");
    QDomElement author = doc.createElement("作者");
    QDomText text;

    // 我们获得了最后一个孩子结点的编号,然后加1,便是新的编号
    QString num = root.lastChild().toElement().attribute("编号");
    int count = num.toInt() +1;
    id.setValue(QString::number(count));
    book.setAttributeNode(id);

    text = doc.createTextNode(ui->lineEdit_title->text());
    title.appendChild(text);

    text = doc.createTextNode(ui->lineEdit_author->text());
    author.appendChild(text);

    book.appendChild(title);
    book.appendChild(author);
    root.appendChild(book);

    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return ;
    QTextStream out(&file);
    doc.save(out,4);   //将文档保存到文件,4为子元素缩进字符数
    file.close();
    ui->listWidget->clear(); //最后更改显示为“添加成功!”
    ui->listWidget->addItem(tr("添加成功!"));
}

先用只读方式打开XML文件,将其读入doc中,然后关闭。我们将新的节点加入到最后面,并使其“编号”为以前的最后一个节点的编号加1。最后我们再用只写的方式打开XML文件,将修改完的doc写入其中。运行程序,效果如下图所示。
在这里插入图片描述

06. 查找、删除、更新XML文档

6.1 将界面上“图书编号”后面的Line Edit部件的objectName更改为lineEdit_id。

6.2 在mainwindow.h文件中添加public类型的函数声明:

    void doXml(const QString operate);

6.3 到mainwindow.cpp中添加该函数的定义:

void MainWindow::doXml(const QString operate)
{
    ui->listWidget->clear();
    ui->listWidget->addItem(tr("没有找到相关内容!"));
    QFile file("test.xml");

    if (!file.open(QIODevice::ReadOnly)) return ;

    QDomDocument doc;
    if (!doc.setContent(&file))
    {
        file.close();
        return ;
    }
    file.close();

    QDomNodeList list = doc.elementsByTagName("图书");
    // 以标签名进行查找
    for(int i=0; i < list.count(); i++)
    {
        QDomElement e = list.at(i).toElement();

        // 如果元素的“编号”属性值与我们所查的相同
        if(e.attribute("编号") == ui->lineEdit_id->text())
        {
            // 如果元素的“编号”属性值与我们所查的相同
            if(operate == "delete")  //如果是删除操作
            {
                QDomElement root = doc.documentElement(); //取出根节点
                root.removeChild(list.at(i));  //从根节点上删除该节点
                QFile file("test.xml");     //保存更改
                if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
                    return ;
                QTextStream out(&file);
                doc.save(out,4);
                file.close();
                ui->listWidget->clear();
                ui->listWidget->addItem(tr("删除成功!"));
            }

            else if(operate == "update")  //如果是更新操作
            {
                QDomNodeList child = list.at(i).childNodes();
                //找到它的所有子节点,就是“书名”和“作者”
                child.at(0).toElement().firstChild().setNodeValue(
                            ui->lineEdit_title->text());
                //将它子节点的首个子节点(就是文本节点)的内容更新
                child.at(1).toElement().firstChild().setNodeValue(
                            ui->lineEdit_author->text());
                QFile file("test.xml");     //保存更改
                if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
                    return ;
                QTextStream out(&file);
                doc.save(out,4);   //保存文档,4为子元素缩进字符数
                file.close();
                ui->listWidget->clear();
                ui->listWidget->addItem(tr("更新成功!"));
            }

            else if(operate == "find")  //如果是查找操作
            {
                ui->listWidget->clear();
                ui->listWidget->addItem(e.tagName()
                                        +e.attribute(tr("编号")));
                QDomNodeList list = e.childNodes();
                for(int i=0; i < list.count(); i++)
                {
                    QDomNode node = list.at(i);
                    if(node.isElement())
                        ui->listWidget->addItem("   "
                                    +node.toElement().tagName()
                                                +" : "+node.toElement().text());
                }
            }
        }
    }
}

6.4 分别进入“查找”,“删除”,“更新”三个按钮的单击信号槽,更改如下:

//查找
void MainWindow::on_pushButton_clicked()
{
    doXml("find");
}

//删除
void MainWindow::on_pushButton_2_clicked()
{
    doXml("delete");
}

//更新
void MainWindow::on_pushButton_4_clicked()
{
    doXml("update");
}

运行程序,查找操作结果如下图所示。
在这里插入图片描述

对编号为1的图书进行更新,效果如下图所示。在这里插入图片描述

更新后我们再次查看所有内容。如下图所示。
在这里插入图片描述

然后进行删除操作,如下图所示。
在这里插入图片描述

删除后再次查询所有内容。效果如下图所示。
在这里插入图片描述

温馨提示

使用DOM可以很方便地进行XML文档的随机访问,这也是它最大的优点。

07. 附录

7.1 Qt教程汇总
网址:https://dengjin.blog.csdn.net/article/details/115174639

7.2 源码下载
网址:【Qt】DOM创建和操作XML文档.rar

© 版权声明
THE END
喜欢就支持一下吧
点赞589 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容