Qt解析XML文件的两种方式

编程入门 行业动态 更新时间:2024-10-07 08:29:54

Qt解析XML文件的<a href=https://www.elefans.com/category/jswz/34/1768716.html style=两种方式"/>

Qt解析XML文件的两种方式

文章目录

  • 1 XML简介
    • 1.Qt读取文件的方式
    • 2.Qt生成XML文件的方法
  • 2 Qt中DOM的使用
    • 1.写操作
    • 2.读操作
    • 3.添加
    • 4.删除
    • 5.更新
  • 3 Qt中的QXmlStreamWriter和QXmlStreamReader
    • 1.QXmlStreamWriter
    • 2.QXmlStreamReader

1 XML简介

XML是ExtensibleMarkup Language的缩写,即可扩展标记语言。它是一种用来创建的标记的标记语言。使用XML标记语言可以做到数据或数据结构在任何编程语言环境下的共享。XML中有格式正规的XML和有效的XML。
XML文档的元素一般是由标记头、标记末和标记间的字符串数据构成。元素可包含其他元素、文本或者两者的混合物。元素也可以拥有属性。一般格式: Aquotion。元素中可以插入属性,但是属性值一定要用双引号。
XML解析器是读取XML文档并提供对文档内容的访问的软件模块。在应用程序中,和其他系统中使用xml后,可以轻松实现数据交换。

1.Qt读取文件的方式

A、QXmlStreamReader:一种快速的基于流的方式访问良格式 XML 文档,特别适合于实现一次解析器(所谓“一次解析器”,可以理解成我们只需读取文档一次,然后像一个遍历器从头到尾一次性处理 XML 文档,期间不会有反复的情况,也就是不会读完第一个标签,然后读第二个,读完第二个又返回去读第一个,这是不允许的);这种方法是通过调用readNext()函数实现的,可以读取下一个记号,然后返回一个记号类型。这是一种快速解析

B、DOM(Document Object Model):将整个 XML 文档读入内存,构建成一个树结构,允许程序在树结构上向前向后移动导航,这是与另外两种方式最大的区别,也就是允许实现多次解析器(对应于前面所说的一次解析器)。DOM 方式带来的问题是需要一次性将整个 XML 文档读入内存,因此会占用很大内存;但是因为储存在内存里,所以实现频繁修改比较方便

2.Qt生成XML文件的方法

A、QXmlStreamWriterQXmlStreamReader相对应。XML流的方法
B、DOM 方式,首先在内存中生成 DOM 树,然后将 DOM 树写入文件。

2 Qt中DOM的使用

项目配置
pro文件里面添加QT+=xml
include <QtXml>,也可以include <QDomDocument>

1.写操作

void writeXml()
{QString strDir = QCoreApplication::applicationDirPath() + "/xmlfile";QDir dir(strDir);if(!dir.exists(strDir))//先创建个文件夹{dir.cd(strDir);dir.mkdir(strDir);}dir.setCurrent(strDir);m_filePath = strDir + "/text.xml";QFile file(m_filePath); //相对路径、绝对路径、资源路径都可以if(!file.open(QFile::WriteOnly)) //可以用QIODevice,Truncate表示清空原来的内容return;QDomDocument doc;QDomProcessingInstruction instruction; //添加处理命令instruction = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");doc.appendChild(instruction);//添加根节点QDomElement root = doc.createElement("library");doc.appendChild(root);//添加第一个子节点及其子元素QDomElement book = doc.createElement("book");book.setAttribute("id",1); //方式一:创建属性  其中键值对的值可以是各种类型QDomAttr time = doc.createAttribute("time"); //方式二:创建属性 值必须是字符串time.setValue("2013/6/13");book.setAttributeNode(time);QDomElement title = doc.createElement("title"); //创建子元素QDomText text; //设置括号标签中间的值text = doc.createTextNode("C++ primer");book.appendChild(title);title.appendChild(text);QDomElement author = doc.createElement("author"); //创建子元素text = doc.createTextNode("Stanley Lippman");author.appendChild(text);book.appendChild(author);root.appendChild(book);//添加第二个子节点及其子元素,部分变量只需重新赋值book = doc.createElement("book");book.setAttribute("id",2);time = doc.createAttribute("time");time.setValue("2007/5/25");book.setAttributeNode(time);title = doc.createElement("title");text = doc.createTextNode("Thinking in Java");book.appendChild(title);title.appendChild(text);author = doc.createElement("author");text = doc.createTextNode("Bruce Eckel");author.appendChild(text);book.appendChild(author);root.appendChild(book);//输出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //缩进4格file.close();
}

2.读操作

void readXml()
{//打开或创建文件QFile file(m_filePath); //相对路径、绝对路径、资源路径都行if(!file.open(QFile::ReadOnly))return;QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();QDomElement root = doc.documentElement(); //返回根节点qDebug() << root.nodeName();QDomNode node = root.firstChild(); //获得第一个子节点while(!node.isNull())  //如果节点不空{if(node.isElement()) //如果节点是元素{QDomElement e = node.toElement(); //转换为元素,注意元素和节点是两个数据结构,其实差不多qDebug() << e.tagName() << " " << e.attribute("id") << " " << e.attribute("time"); //打印键值对,tagName和nodeName是一个东西QDomNodeList list= e.childNodes();for(int i = 0;i < list.count(); i++) //遍历子元素,count和size都可以用,可用于标签数计数{QDomNode n = list.at(i);if(node.isElement())qDebug()<<n.nodeName()<<":"<<n.toElement().text();}}node = node.nextSibling(); //下一个兄弟节点,nextSiblingElement()是下一个兄弟元素,都差不多}
}

3.添加

void addXml()
{//打开文件QFile file(m_filePath); //相对路径、绝对路径、资源路径都可以if(!file.open(QFile::ReadOnly))return;//增加一个一级子节点以及元素QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();QDomElement root = doc.documentElement();QDomElement book = doc.createElement("book");book.setAttribute("id",3);book.setAttribute("time","1813/1/27");QDomElement title = doc.createElement("title");QDomText text;text = doc.createTextNode("Pride and Prejudice");title.appendChild(text);book.appendChild(title);QDomElement author = doc.createElement("author");text = doc.createTextNode("Jane Austen");author.appendChild(text);book.appendChild(author);root.appendChild(book);if(!file.open(QFile::WriteOnly)) //先读进来,再重写,如果不用truncate就是在后面追加内容,就无效了return;//输出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //缩进4格file.close();
}

4.删除

void removeXml()
{//打开文件QFile file(m_filePath); //相对路径、绝对路径、资源路径都可以if(!file.open(QFile::ReadOnly))return;//删除一个一级子节点及其元素,外层节点删除内层节点于此相同QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();  //一定要记得关掉啊,不然无法完成操作QDomElement root = doc.documentElement();QDomNodeList list = doc.elementsByTagName("book"); //由标签名定位for(int i = 0;i < list.count(); i++){QDomElement e = list.at(i).toElement();if(e.attribute("time")=="2007/5/25")  //以属性名定位,类似于hash的方式,warning:这里仅仅删除一个节点,其实可以加个breakroot.removeChild(list.at(i));}if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//输出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //缩进4格file.close();
}

5.更新

void updateXml()
{//打开文件QFile file(m_filePath); //相对路径、绝对路径、资源路径都可以if(!file.open(QFile::ReadOnly))return;//更新一个标签项,如果知道xml的结构,直接定位到那个标签上定点更新//或者用遍历的方法去匹配tagname或者attribut,value来更新QDomDocument doc;if(!doc.setContent(&file)){file.close();return;}file.close();QDomElement root = doc.documentElement();QDomNodeList list = root.elementsByTagName("book");QDomNode node = list.at(list.size()-1).firstChild(); //定位到第三个一级子节点的子元素QDomNode oldnode = node.firstChild(); //标签之间的内容作为节点的子节点出现,当前是Pride and Projudicenode.firstChild().setNodeValue("Emma");QDomNode newnode = node.firstChild();node.replaceChild(newnode,oldnode);if(!file.open(QFile::WriteOnly|QFile::Truncate))return;//输出到文件QTextStream out_stream(&file);doc.save(out_stream,4); //缩进4格file.close();
}

3 Qt中的QXmlStreamWriter和QXmlStreamReader

1.QXmlStreamWriter

对应常用api介绍:writeStartDocument():写文档头,作用类似于创建一个xml文档,并在文档开头部分写入版本信息和编码信息默认为:<?xml version="1.0" encoding="UTF-8"?>
同时也可以写1个参数与2个参数.
writeEndDocument(): 对应于writeStartDocument(),当调用这个函数时,即表示文档信息写入完毕。
writeStartElement():  写入开始记号 比如<SMS>
writeEndElement():  写入结束记号 比如</SMS>
writeTextElement():  写入文本信息 比如上面的name,phone,time 等等;
void xmlStreamWriter()
{QString strDir = QCoreApplication::applicationDirPath() + "/xmlfile";QDir dir(strDir);if(!dir.exists(strDir))//先创建个文件夹{dir.cd(strDir);dir.mkdir(strDir);}dir.setCurrent(strDir);m_xmlPath = strDir + "/xmltest.xml";QStringList str;str << "通天" << "帝江" << "祖龙" << "红云";QFile file(m_xmlPath);if(!file.open(QFile::WriteOnly|QFile::Text)){qDebug()<< "file cannot open";return;}QXmlStreamWriter stream(&file);stream.setAutoFormatting(true); //stream.writeStartDocument(); //默认: <?xml version="1.0" encoding="UTF-8"?>stream.writeStartElement("DATA");for (int i = 0; i < str.size(); i++){stream.writeStartElement("EP");//stream.writeTextElement("name", str[i]);stream.writeTextElement("phone", "188XXXXXXXXXX");stream.writeTextElement("time", "2022");stream.writeEndElement();}stream.writeEndElement();stream.writeEndDocument();file.close();
}

文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<DATA><EP><name>通天</name><phone>188XXXXXXXXXX</phone><time>2022</time></EP><EP><name>帝江</name><phone>188XXXXXXXXXX</phone><time>2022</time></EP><EP><name>祖龙</name><phone>188XXXXXXXXXX</phone><time>2022</time></EP><EP><name>红云</name><phone>188XXXXXXXXXX</phone><time>2022</time></EP>
</DATA>

2.QXmlStreamReader

常用的api:readNext(): 从xml输入流中读取下一个记号。name(): 记号的名称,即<名称></名称>isStartElement():判断当前已读取的记号是否为开始元素,开始元素即<>isEndElement():判断当前已读取的记号是否为结束元素,结束元素即</>readElementText():读取当前记号对应的文本值,<>文本值</>atEnd():判断是否为文件结尾
void xmlStreamReader()
{QString str;QFile file(m_xmlPath);if(file.open(QFile::ReadOnly|QFile::Text)){QXmlStreamReader reader(&file);reader.readNext(); //过滤掉头一行while(!reader.atEnd()){if(reader.isStartElement()){if(reader.name() == "EP"){str = "EP";}else if (reader.name() == "name"){str = reader.readElementText();qDebug() << str << endl;}else if (reader.name() == "phone"){str = reader.readElementText();qDebug() << str << endl;}else if(reader.name() == "time" ){str = reader.readElementText();qDebug() << str << endl;}}else if (reader.isEndElement()){if(reader.name() == "EP"){qDebug()<<endl;}}reader.readNext();}}else {qDebug() << "not file is here or it's a broken";}file.close();
}

输出结果:

"通天" 
"188XXXXXXXXXX" 
"2022" "帝江" 
"188XXXXXXXXXX" 
"2022" "祖龙" 
"188XXXXXXXXXX" 
"2022" "红云" 
"188XXXXXXXXXX" 
"2022" 

更多推荐

Qt解析XML文件的两种方式

本文发布于:2024-02-14 12:03:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1763338.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:两种   方式   文件   Qt   XML

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!