Qt的Xml操作QDomDocument

Posted mtn007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt的Xml操作QDomDocument相关的知识,希望对你有一定的参考价值。

Qt对于Xml的支持是很好的,一些我们需要的操作应有尽有,下面简单介绍一下怎样使用。主要有以下几点使用:

  1. 写xml到文件
  2. 读xml
  3. 添加节点到xml
  4. 删除xml中某节点信息
  5. 修改xml中某节点信息

准备工作

  1. .pro加入QT += xml
  2. 需要include QDomDocument QTextStream QFile三个头文件

直接上代码

WriteXml

  1 void writeXml()
  2 {
  3     QDomDocument doc;
  4     QDomProcessingInstruction xmlInstruction = doc.createProcessingInstruction("xml", "version="1.0" encoding="UTF-8" standalone="yes"");
  5     QDomComment comment = doc.createComment(QString::fromLocal8Bit("离开是为了更好的归来"));
  6     QDomProcessingInstruction styleInstruction = doc.createProcessingInstruction("xml-stylesheet", "type="text/css" href="style.css"");
  7     doc.appendChild(xmlInstruction);  // 开始文档(XML 声明)
  8     doc.appendChild(comment);  // 注释
  9     doc.appendChild(styleInstruction);  // 处理指令
 10     // 根元素 <Blogs>
 11     QDomElement root = doc.createElement("Books");
 12     root.setAttribute("Version", "1.0");  // 属性
 13     doc.appendChild(root);
 14 
 15     // 元素 <Blog>
 16     QDomElement child = doc.createElement("Book");
 17     root.appendChild(child);
 18 
 19     // 元素 <作者>、<时间>、<个人说明>
 20     QDomElement author = doc.createElement(QString::fromLocal8Bit("作者"));
 21     QDomElement home = doc.createElement(QString::fromLocal8Bit("时间"));
 22     QDomElement instruction = doc.createElement(QString::fromLocal8Bit("个人说明"));
 23     child.appendChild(author);
 24     child.appendChild(home);
 25     child.appendChild(instruction);
 26 
 27     // 元素的文本数据
 28     QDomText authorText = doc.createTextNode(QString::fromLocal8Bit("Vincent"));
 29     QDomText homeText = doc.createTextNode("2017年4月13日");
 30     QDomText instructionText = doc.createTextNode(QString::fromLocal8Bit("大宋枢密院常任委员会_委员"));
 31     author.appendChild(authorText);
 32     home.appendChild(homeText);
 33     instruction.appendChild(instructionText);
 34 
 35     // 保存 XML 文件
 36     QString strFile("Books.xml");
 37     QFile file(strFile);
 38     // 只写模式打开文件
 39     if (file.open(QFile::WriteOnly | QFile::Text))
 40     {
 41         QTextStream out(&file);
 42         doc.save(out, QDomNode::EncodingFromDocument);
 43         file.close();
 44     }
 45 }
 46 void writeXML()
 47 {
 48     //打开或创建文件
 49     QString fileName{"test.xml"};
 50     QFile file(fileName);
 51     //QIODevice::Truncate表示清空原来的内容
 52     if(!file.open(QFile::WriteOnly|QFile::Truncate))
 53         return;
 54 
 55     //创建xml文档在内存中
 56     QDomDocument doc;
 57     //添加处理命令
 58     QDomProcessingInstruction instruction;
 59     instruction = doc.createProcessingInstruction("xml", "version="1.0" encoding="UTF-8"");
 60     //创建注释
 61     QDomComment comment;
 62     comment = doc.createComment(QString::fromLocal8Bit("离开是为了更好的归来"));
 63     QDomProcessingInstruction styleInstruction;
 64     styleInstruction= doc.createProcessingInstruction("xml-stylesheet", "type="text/css" href="style.css"");
 65     doc.appendChild(instruction); //文档开始声明
 66     doc.appendChild(comment);
 67     doc.appendChild(styleInstruction);  // 处理指令
 68 
 69 
 70     //添加根节点
 71     QDomElement root=doc.createElement("library");
 72     root.setAttribute("Version","2.1");
 73     doc.appendChild(root);
 74     //添加第一个子节点及其子元素
 75     QDomElement book=doc.createElement("book");
 76     //方式一:创建属性  其中键值对的值可以是各种类型
 77     book.setAttribute("id",1);
 78     //方式二:创建属性 值必须是字符串
 79     QDomAttr time=doc.createAttribute("time");
 80     time.setValue("2013/6/13");
 81     book.setAttributeNode(time);
 82     QDomElement title=doc.createElement("title"); //创建子元素
 83     QDomText text; //设置括号标签中间的值
 84     text=doc.createTextNode("C++ primer");
 85     book.appendChild(title);
 86     title.appendChild(text);
 87     QDomElement author=doc.createElement("author"); //创建子元素
 88     text=doc.createTextNode("Stanley Lippman");
 89     author.appendChild(text);
 90     book.appendChild(author);
 91     //添加节点book做为根节点的子节点
 92     root.appendChild(book);
 93 
 94     //添加第二个子节点及其子元素
 95     book=doc.createElement("book");
 96     book.setAttribute("id",2);
 97     time=doc.createAttribute("time");
 98     time.setValue("2007/5/25");
 99     book.setAttributeNode(time);
100     title=doc.createElement("title");
101     text=doc.createTextNode("Thinking in Java");
102     book.appendChild(title);
103     title.appendChild(text);
104 
105     author=doc.createElement("author");
106     text=doc.createTextNode("Bruce Eckel");
107     author.appendChild(text);
108     book.appendChild(author);
109     root.appendChild(book);
110 
111     //输出到文件
112     QTextStream out_stream(&file);
113     doc.save(out_stream,4); //缩进4格
114     file.close();
115 }

ReadXml

  1 void readXML()
  2 {
  3     //打开或创建文件
  4         QFile file("test.xml");
  5         if(!file.open(QFile::ReadOnly))
  6             return;
  7 
  8         QDomDocument doc;
  9         //设置wangfei1.xml到文档
 10         if(!doc.setContent(&file))
 11         {
 12             file.close();
 13             return;
 14         }
 15 
 16         file.close();
 17 
 18         //返回根节点
 19         QDomElement root=doc.documentElement();
 20         qDebug()<<root.nodeName();
 21         //如果xml根元素有属性(Version)将输出,Vinsion是用户自定义的属性,没有继续执行下一条命令
 22         if (root.hasAttribute("Version"))  // 属性
 23             qDebug() << root.attribute("Version");
 24         /**********根元素之上(XML 声明、注释等)**********/
 25         QDomNode node = root.previousSibling();
 26         while (!node.isNull())
 27         {
 28             switch (node.nodeType())
 29             {
 30             case QDomNode::ProcessingInstructionNode :
 31             {
 32                 QDomProcessingInstruction instruction = node.toProcessingInstruction();
 33                 //输出处理指令,是用户自定义的,比如字符串“name”对应处理指令得到名字,这个命令是用户写的
 34                 qDebug() << instruction.target() << instruction.data();
 35                 if (QString::compare(instruction.target(), "xml") == 0) // 开始文档(XML 声明)
 36                 {
 37                     //cout<<"处理命令xml"<<endl;
 38                     // ...
 39                 }
 40                 else if (QString::compare(instruction.target(), "xml-stylesheet") == 0) // 处理指令
 41                 {
 42                     //cout<<"处理命令xml-stylesheet"<<endl;
 43                     // ...
 44                 }
 45                 break;
 46             }
 47             case QDomNode::CommentNode :
 48             {
 49                 QDomComment comment = node.toComment();
 50                 qDebug() << comment.data();
 51                 break;
 52             }
 53             default:
 54                 break;
 55             }
 56             node = node.previousSibling();
 57         }
 58 
 59         //获得第一个子节点
 60         node=root.firstChild();
 61         while(!node.isNull())  //如果节点不空
 62         {
 63             if(node.isElement()) //如果节点是元素
 64             {
 65                 //转换为元素
 66                 QDomElement element=node.toElement();
 67                 if (!element.isNull())// 节点的确是一个元素
 68                 {
 69                     //输出第一个节点,包括第一个节点的属性,这个属性需要指定属性值,才能输出,如果没有输出空
 70                     qDebug()<<element.tagName()<<" "<<element.attribute("id")<<" "<<element.attribute("time");
 71                     QDomNodeList list=element.childNodes();
 72                     for(int i=0;i<list.count();++i)
 73                     {
 74                         QDomNode n=list.at(i);
 75                         //node = list.at(i);
 76                         if(node.isElement())
 77                         {
 78                             qDebug()<<n.nodeName()<<":"<<n.toElement().text();
 79                             element = n.toElement();
 80                             //qDebug()<<element.nodeName()<<":"<<element.toElement().text();
 81                             if (QString::compare(element.tagName(), QStringLiteral("作者")) == 0)
 82                             {
 83                                 // ...处理命令
 84                                 //cout<< "处理命令作者"<<endl;
 85                             }
 86                             else if (QString::compare(element.tagName(), QStringLiteral("时间")) == 0)
 87                             {
 88                                 //cout<<"处理命令时间"<<endl;
 89                                 // ...处理命令
 90                             }
 91                             else if (QString::compare(element.tagName(), QStringLiteral("个人说明")) == 0)
 92                             {
 93                                 //cout<<"处理命令个人说明"<<endl;
 94                                 // ...处理命令
 95                             }
 96                         }
 97 
 98                     }
 99                 }
100             }
101             //下一个兄弟节点
102             node=node.nextSibling();
103         }
104 }

AddXml

 1 void addXML()
 2 {
 3     //打开文件
 4     QFile file("test.xml");
 5     if(!file.open(QFile::ReadOnly))
 6         return;
 7     //增加一个一级子节点以及元素
 8     QDomDocument doc;
 9     if(!doc.setContent(&file))
10     {
11         file.close();
12         return;
13     }
14     file.close();
15     //创建根节点
16     QDomElement root = doc.documentElement();
17     //创建next子节点book
18     QDomElement book = doc.createElement("book");
19     book.setAttribute("id",3);
20     book.setAttribute("time","1813/1/27");
21     QDomElement title = doc.createElement("title");
22     QDomText text;
23     text = doc.createTextNode("Pride and Prejudice");
24     //添加text内容到title节点
25     title.appendChild(text);
26     //添加title到book节点
27     book.appendChild(title);
28     //添加book到根节点
29     root.appendChild(book);
30 
31     if(!file.open(QFile::WriteOnly|QFile::Truncate))
32         return;
33     //输出到文件
34     QTextStream out_stream(&file);
35     doc.save(out_stream,4); //以缩进4格方式输出,也有其他输出方式(格式)
36     file.close();
37 }

DeleteXml

 1 void deleteXML()
 2 {
 3     //打开文件
 4     QFile file("test.xml");
 5     if(!file.open(QFile::ReadOnly))
 6         return;
 7 
 8     //删除一个一级子节点及其元素,外层节点删除内层节点于此相同
 9     QDomDocument doc;
10     if(!doc.setContent(&file))
11     {
12         file.close();
13         return;
14     }
15     file.close();
16 
17     QDomElement root=doc.documentElement();
18     //由标签名定位,本标签为book,以后可以是用string类型的字符串替换,实现动态
19     QDomNodeList list=doc.elementsByTagName("book");
20 
21     //删除方式一,通过标签book后面的属性删除<book>到</book>
22     for(int i=0;i<list.count();i++)
23     {
24         //转化为元素
25         QDomElement e=list.at(i).toElement();
26         //找到time是2007/5/25这一条数据将其删除
27         if(e.attribute("time")=="2007/5/25")
28             root.removeChild(list.at(i));
29     }
30     //删除方式二,可以通过索引直接删除
31 //    root.removeChild(list.at(1));
32 
33     if(!file.open(QFile::WriteOnly|QFile::Truncate))
34         return;
35     //输出到文件
36     QTextStream out_stream(&file);
37     doc.save(out_stream,4); //缩进4格
38     file.close();
39 }

AmendXml

  1 void amendXML()
  2 {
  3     //打开文件
  4     QFile file("wangfei1.xml");
  5     if(!file.open(QFile::ReadOnly))
  6         return;
  7 
  8     //更新一个标签项,如果知道xml的结构,直接定位到那个标签上定点更新
  9     //或者用遍历的方法去匹配tagname或者attribut,value来更新
 10     QDomDocument doc;
 11     //设置wangfei.xml读到doc文档
 12     if(!doc.setContent(&file))
 13     {
 14         file.close();
 15         return;
 16     }
 17     file.close();
 18 
 19     /**
 20      *    知道xml结构,直接定位修改
 21       *   提取根节点
 22       *
 23       */
 24     QDomElement root=doc.documentElement();
 25     //以book标签存入list
 26 //    QDomNodeList list=root.elementsByTagName("book");
 27 //    QDomNode listNode=list.at(list.size()-2).firstChild();
 28 //    QDomNode oldnode=listNode.firstChild();
 29 //    //把title改成Emma
 30 //    listNode.firstChild().setNodeValue("aaaaaaa");
 31 //    QDomNode newnode=listNode.firstChild();
 32 //    listNode.replaceChild(newnode,oldnode);
 33 
 34 
 35     //使用遍历方法选择要修改的元素
 36 //    QDomNodeList lists =doc.childNodes();
 37 //    QDomNodeList list=root.elementsByTagName("book");
 38 
 39     QDomNode node = root.firstChild();
 40 
 41     //QDomNodeList list=root.elementsByTagName("book");
 42 
 43     while(!node.isNull())  //如果节点不空
 44     {
 45         if(node.isElement()) //如果节点是元素
 46         {
 47             //转换为元素
 48             QDomElement element=node.toElement();
 49             if (!element.isNull() && element.attribute("id") == "3")// 节点的确是一个元素
 50             {
 51                 //输出第一个节点,包括第一个节点的属性,这个属性需要指定属性值,才能输出,如果没有输出空
 52                 //qDebug()<<element.tagName()<<" "<<element.attribute("id")<<" "<<element.attribute("time");
 53                 QDomNodeList list=element.childNodes();
 54                 for(int i=0;i<list.count();++i)
 55                 {
 56                     QDomNode n=list.at(i);
 57                     //node = list.at(i);
 58                     if(node.isElement())
 59                     {
 60                         //qDebug()<<n.nodeName()<<":"<<n.toElement().text();
 61                         element = n.toElement();
 62                         //与上面qDebug效果相同
 63                         //qDebug()<<element.nodeName()<<":"<<element.toElement().text();
 64 
 65 
 66                         //这个if可以不需要,如果需要精确定位,以防数据相同所以要加这个嵌套if
 67                         if (QString::compare(element.tagName(), QStringLiteral("title")) == 0)
 68                         {
 69 
 70                             if("Pride and Prejudice" == element.toElement().text())
 71                             {
 72                                 // ...处理命令,在这个if里可以遍历想要的节点进行修改
 73                                 //新建一个旧的node缓存
 74                                 QDomNode oldNode = n.firstChild();
 75                                 n.firstChild().setNodeValue("changchun1");
 76                                 //新建一个新的newNode子节点
 77                                 QDomNode newNode = n.firstChild();
 78                                 //使用replaceChild替换node
 79                                 n.replaceChild(newNode,oldNode);
 80                             }
 81 
 82                         }
 83 
 84                         else if (QString::compare(element.tagName(), QStringLiteral("时间")) == 0)
 85                         {
 86                             //cout<<"处理命令时间"<<endl;
 87                             // ...处理命令
 88                         }
 89                         else if (QString::compare(element.tagName(), QStringLiteral("个人说明")) == 0)
 90                         {
 91                             //cout<<"处理命令个人说明"<<endl;
 92                             // ...处理命令
 93                         }
 94                     }
 95 
 96                 }
 97             }
 98         }
 99         //下一个兄弟节点
100         node=node.nextSibling();
101     }
102 
103 
104     if(!file.open(QFile::WriteOnly|QFile::Truncate))
105         return;
106     //输出到文件
107     QTextStream out_stream(&file);
108     doc.save(out_stream,4); //缩进4格
109     file.close();
110 
111 }

以上是关于Qt的Xml操作QDomDocument的主要内容,如果未能解决你的问题,请参考以下文章

Qt读写三种文件,QSettings读ini配置文件,QJsonDocument读JSON文件,QDomDocument读xml文件

QDomDocument 读取和编辑xml文件

关于Qt 报QDomDocument: No such file or directory错误解决办法

12.5.2 解析XML文件相关类介绍

Qt QMetaObjects 和从 QWidget 到 QObject 的转换

DOM解析xml实现读写增删改