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

桃扇骨 2022-11-13 12:23 180阅读 0赞

00. 目录

文章目录

      1. 目录
      1. 概述
      1. 开发环境
      1. 创建XML文档
      1. 读取XML文档
      1. 增加XML节点
      1. 查找、删除、更新XML文档
      1. 附录

01. 概述

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

02. 开发环境

Windows系统:Windows10

Qt版本:Qt5.15或者Qt6

03. 创建XML文档

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

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

  1. QT += core gui xml

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

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

  1. MainWindow::MainWindow(QWidget *parent)
  2. : QMainWindow(parent)
  3. , ui(new Ui::MainWindow)
  4. {
  5. ui->setupUi(this);
  6. QFile file("test.xml");
  7. bool ret = file.open(QIODevice::WriteOnly | QIODevice::Truncate);
  8. if (!ret)
  9. {
  10. qDebug() << "打开文件失败";
  11. return;
  12. }
  13. //创建文档
  14. QDomDocument doc;
  15. //添加处理指令
  16. QDomProcessingInstruction instruction;
  17. instruction = doc.createProcessingInstruction("xml",
  18. "version=\"1.0\" encoding=\"UTF-8\"");
  19. doc.appendChild(instruction);
  20. QDomElement root =doc.createElement(tr("书库"));
  21. //添加根元素
  22. doc.appendChild(root);
  23. //添加第一个book元素及其子元素
  24. QDomElement book = doc.createElement(tr("图书"));
  25. QDomAttr id = doc.createAttribute(tr("编号"));
  26. QDomElement title = doc.createElement(tr("书名"));
  27. QDomElement author = doc.createElement(tr("作者"));
  28. QDomText text;
  29. id.setValue("1");
  30. book.setAttributeNode(id);
  31. text = doc.createTextNode("Qt");
  32. title.appendChild(text);
  33. text = doc.createTextNode("shiming");
  34. author.appendChild(text);
  35. book.appendChild(title);
  36. book.appendChild(author);
  37. root.appendChild(book);
  38. //添加第二个book元素及其子元素
  39. book = doc.createElement(tr("图书"));
  40. id = doc.createAttribute(tr("编号"));
  41. title = doc.createElement(tr("书名"));
  42. author = doc.createElement(tr("作者"));
  43. id.setValue("2");
  44. book.setAttributeNode(id);
  45. text = doc.createTextNode("Linux");
  46. title.appendChild(text);
  47. text = doc.createTextNode("LiMing");
  48. author.appendChild(text);
  49. book.appendChild(title);
  50. book.appendChild(author);
  51. root.appendChild(book);
  52. QTextStream out(&file);
  53. doc.save(out, 4);
  54. file.close();
  55. }

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

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <书库>
  3. <图书 编号="1">
  4. <书名>Qt</书名>
  5. <作者>shiming</作者>
  6. </图书>
  7. <图书 编号="2">
  8. <书名>Linux</书名>
  9. <作者>LiMing</作者>
  10. </图书>
  11. </书库>

04. 读取XML文档

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

  1. //查看全部信息
  2. void MainWindow::on_pushButton_5_clicked()
  3. {
  4. //清空内容
  5. ui->listWidget->clear();
  6. QFile file("test.xml");
  7. if (!file.open(QIODevice::ReadOnly))
  8. {
  9. return;
  10. }
  11. QDomDocument doc;
  12. if (!doc.setContent(&file))
  13. {
  14. file.close();
  15. return;
  16. }
  17. file.close();
  18. //返回根节点及其子节点的元素标记名
  19. //返回根元素
  20. QDomElement docElem = doc.documentElement();
  21. //返回根节点的第一个子节点
  22. QDomNode n = docElem.firstChild();
  23. while(!n.isNull())
  24. {
  25. //如果子节点是元素
  26. if (n.isElement())
  27. {
  28. //将其转换为元素
  29. QDomElement e = n.toElement();
  30. ui->listWidget->addItem(e.tagName() + e.attribute(tr("编号")));
  31. QDomNodeList list = e.childNodes();
  32. for (int i = 0; i < list.count(); i++)
  33. {
  34. QDomNode node = list.at(i);
  35. if (node.isElement())
  36. {
  37. ui->listWidget->addItem(" " + node.toElement().tagName()
  38. + " : " + node.toElement().text());
  39. }
  40. }
  41. }
  42. n = n.nextSibling();
  43. }
  44. }

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

05. 增加XML节点

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

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

  1. //添加按钮
  2. void MainWindow::on_pushButton_3_clicked()
  3. {
  4. //我们先清空显示,然后显示“无法添加!”
  5. ui->listWidget->clear();
  6. ui->listWidget->addItem(tr("无法添加!"));
  7. QFile file("test.xml");
  8. if (!file.open(QIODevice::ReadOnly))
  9. return;
  10. QDomDocument doc;
  11. if (!doc.setContent(&file))
  12. {
  13. file.close();
  14. return;
  15. }
  16. file.close();
  17. QDomElement root = doc.documentElement();
  18. QDomElement book = doc.createElement("图书");
  19. QDomAttr id = doc.createAttribute("编号");
  20. QDomElement title = doc.createElement("书名");
  21. QDomElement author = doc.createElement("作者");
  22. QDomText text;
  23. // 我们获得了最后一个孩子结点的编号,然后加1,便是新的编号
  24. QString num = root.lastChild().toElement().attribute("编号");
  25. int count = num.toInt() +1;
  26. id.setValue(QString::number(count));
  27. book.setAttributeNode(id);
  28. text = doc.createTextNode(ui->lineEdit_title->text());
  29. title.appendChild(text);
  30. text = doc.createTextNode(ui->lineEdit_author->text());
  31. author.appendChild(text);
  32. book.appendChild(title);
  33. book.appendChild(author);
  34. root.appendChild(book);
  35. if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
  36. return ;
  37. QTextStream out(&file);
  38. doc.save(out,4); //将文档保存到文件,4为子元素缩进字符数
  39. file.close();
  40. ui->listWidget->clear(); //最后更改显示为“添加成功!”
  41. ui->listWidget->addItem(tr("添加成功!"));
  42. }

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

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

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

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

  1. void doXml(const QString operate);

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

  1. void MainWindow::doXml(const QString operate)
  2. {
  3. ui->listWidget->clear();
  4. ui->listWidget->addItem(tr("没有找到相关内容!"));
  5. QFile file("test.xml");
  6. if (!file.open(QIODevice::ReadOnly)) return ;
  7. QDomDocument doc;
  8. if (!doc.setContent(&file))
  9. {
  10. file.close();
  11. return ;
  12. }
  13. file.close();
  14. QDomNodeList list = doc.elementsByTagName("图书");
  15. // 以标签名进行查找
  16. for(int i=0; i < list.count(); i++)
  17. {
  18. QDomElement e = list.at(i).toElement();
  19. // 如果元素的“编号”属性值与我们所查的相同
  20. if(e.attribute("编号") == ui->lineEdit_id->text())
  21. {
  22. // 如果元素的“编号”属性值与我们所查的相同
  23. if(operate == "delete") //如果是删除操作
  24. {
  25. QDomElement root = doc.documentElement(); //取出根节点
  26. root.removeChild(list.at(i)); //从根节点上删除该节点
  27. QFile file("test.xml"); //保存更改
  28. if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
  29. return ;
  30. QTextStream out(&file);
  31. doc.save(out,4);
  32. file.close();
  33. ui->listWidget->clear();
  34. ui->listWidget->addItem(tr("删除成功!"));
  35. }
  36. else if(operate == "update") //如果是更新操作
  37. {
  38. QDomNodeList child = list.at(i).childNodes();
  39. //找到它的所有子节点,就是“书名”和“作者”
  40. child.at(0).toElement().firstChild().setNodeValue(
  41. ui->lineEdit_title->text());
  42. //将它子节点的首个子节点(就是文本节点)的内容更新
  43. child.at(1).toElement().firstChild().setNodeValue(
  44. ui->lineEdit_author->text());
  45. QFile file("test.xml"); //保存更改
  46. if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
  47. return ;
  48. QTextStream out(&file);
  49. doc.save(out,4); //保存文档,4为子元素缩进字符数
  50. file.close();
  51. ui->listWidget->clear();
  52. ui->listWidget->addItem(tr("更新成功!"));
  53. }
  54. else if(operate == "find") //如果是查找操作
  55. {
  56. ui->listWidget->clear();
  57. ui->listWidget->addItem(e.tagName()
  58. +e.attribute(tr("编号")));
  59. QDomNodeList list = e.childNodes();
  60. for(int i=0; i < list.count(); i++)
  61. {
  62. QDomNode node = list.at(i);
  63. if(node.isElement())
  64. ui->listWidget->addItem(" "
  65. +node.toElement().tagName()
  66. +" : "+node.toElement().text());
  67. }
  68. }
  69. }
  70. }
  71. }

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

  1. //查找
  2. void MainWindow::on_pushButton_clicked()
  3. {
  4. doXml("find");
  5. }
  6. //删除
  7. void MainWindow::on_pushButton_2_clicked()
  8. {
  9. doXml("delete");
  10. }
  11. //更新
  12. void MainWindow::on_pushButton_4_clicked()
  13. {
  14. doXml("update");
  15. }

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

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

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

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

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

温馨提示

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

07. 附录

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

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

发表评论

表情:
评论列表 (有 0 条评论,180人围观)

还没有评论,来说两句吧...

相关阅读

    相关 创建XML文档

    .Net3.5以前的版本使用DOM,以后的版本则推荐使用Linq to XML,它方便快捷,代码更具有可读性。写代码就是要快,不是吗? 1、方法一 XmlDocum