找回密码
 立即注册
收起左侧

第30篇 Qt5之XML(四)使用流读写XML

3
回复
20409
查看
[复制链接]
累计签到:1608 天
连续签到:1 天
来源: 2017-8-20 22:26:59 显示全部楼层 |阅读模式
使用流读写XML
版权声明

该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处!


导语


  Qt 4.3开始引入了两个新的类来读取和写入XML文档:QXmlStreamReaderQXmlStreamWriter QXmlStreamReader类提供了一个快速的解析器通过一个简单的流API来读取格式良好的XML文档,它是作为QtSAX解析器的替代品身份出现的,因为它比SAX解析器更快更方便。QXmlStreamReader可以从QIODevice或者QByteArray中读取数据。流读取器的基本原理就是将XML文档报告为一个记号(tokens)流,这一点与SAX相似,而它们的不同之处在于XML记号被报告的方式。在SAX中,应用程序必须提供处理器(回调函数)来从解析器获得所谓的XML事件;而对于QXmlStreamReader,是应用程序代码自身来驱动循环,在需要的时候可以从读取器中一个接一个的拉出记号。这个是通过调用readNext()函数实现的,它可以读取下一个记号,然后返回一个记号类型,然后可以使用isStartElement()text()等函数来判断这个记号是否包含我们需要的信息。使用这种主动拉取记号的方式的最大的好处就是可以构建递归解析器,也就是可以在不同的函数或者类中来处理XML文档中的不同记号。


环境:Windows 7 + Qt 5.8.0(包含Qt Creator 4.2.1



目录

一、解析XML文档
二、写入XML文档




正文


一、解析XML文档

1.新建Qt控制台应用QtConsole Application,项目名称为myxmlstream,完成后将myxmlstream.pro文件的第一行代码更改为:

  1. QT       += core xml
复制代码

       然后保存该文件。

2.然后打开main.cpp文件,将内容更改如下:

  1. #include <QCoreApplication>
  2. #include <QFile>
  3. #include <QXmlStreamReader>
  4. #include <QXmlStreamWriter>
  5. #include <QDebug>

  6. int main(int argc, char *argv[])
  7. {
  8.     QCoreApplication a(argc, argv);
  9.     QFile file("../myXmlStream/my.xml");
  10.     if (!file.open(QFile::ReadOnly | QFile::Text))
  11.     {
  12.         qDebug()<<"Error: cannot open file";
  13.         return 1;
  14.     }
  15.    
  16.     QXmlStreamReader reader;
  17.    
  18.     // 设置文件,这时会将流设置为初始状态
  19.     reader.setDevice(&file);
  20.    
  21.     // 如果没有读到文档结尾,而且没有出现错误
  22.     while (!reader.atEnd()) {
  23.         // 读取下一个记号,它返回记号的类型
  24.         QXmlStreamReader::TokenType type = reader.readNext();
  25.         
  26.         // 下面便根据记号的类型来进行不同的输出
  27.         if (type == QXmlStreamReader::StartDocument)
  28.             qDebug() << reader.documentEncoding()
  29.                                        << reader.documentVersion();
  30.         if (type == QXmlStreamReader::StartElement) {
  31.             qDebug() << "<" << reader.name() << ">";
  32.             if (reader.attributes().hasAttribute("id"))
  33.                     qDebug() << reader.attributes().value("id");
  34.         }
  35.         if (type == QXmlStreamReader::EndElement)
  36.                  qDebug() << "</" << reader.name() << ">";
  37.         if (type == QXmlStreamReader::Characters
  38.                                          && !reader.isWhitespace())
  39.             qDebug() << reader.text();
  40.     }
  41.    
  42.     // 如果读取过程中出现错误,那么输出错误信息
  43.     if (reader.hasError()) {
  44.         qDebug() << "error: " << reader.errorString();
  45.     }
  46.    
  47.     file.close();
  48.    
  49.     return a.exec();
  50. }
复制代码

可以看到流读取器就是在一个循环中通过使用readNext()来不断读取记号的,这里可以对不同的记号和不同的内容进行不同的处理,既可以在本函数中进行,也可以在其他函数或者其他类中进行。可以将前面生成的my.xml文件复制到源码目录,然后运行程序,查看效果。



二、写入XML文档


与QXmlStreamReader对应的是QXmlStreamWriter,它通过一个简单的流API提供了一个XML写入器。QXmlStreamWriter的使用是十分简单的,只需要调用相应的记号的写入函数来写入相关数据即可。

将前面主函数的内容更改为:

  1. int main(int argc, char *argv[])
  2. {
  3.     QCoreApplication a(argc, argv);

  4.     QFile file("../myXmlStream/my2.xml");
  5.     if (!file.open(QFile::WriteOnly | QFile::Text))
  6.     {
  7.         qDebug() << "Error: cannot open file";
  8.         return 1;
  9.     }

  10.     QXmlStreamWriter stream(&file);
  11.     stream.setAutoFormatting(true);
  12.     stream.writeStartDocument();
  13.     stream.writeStartElement("bookmark");
  14.     stream.writeAttribute("href", "http://qt.io/");
  15.     stream.writeTextElement("title", "Qt Home");
  16.     stream.writeEndElement();
  17.     stream.writeEndDocument();

  18.     file.close();

  19.     qDebug() << "write finished!";

  20.     return a.exec();
  21. }
复制代码

这里使用了setAutoFormatting(true)函数来自动设置格式,这样会自动换行和添加缩进。然后使用了writeStartDocument(),该函数会自动添加首行的XML说明(即<?xmlversion="1.0" encoding="UTF-8"?>),添加元素可以使用writeStartElement(),不过,这里要注意,一定要在元素的属性、文本等添加完成后,使用writeTextElement()来关闭前一个打开的元素。在最后使用writeEndDocument()来完成文档的写入。现在大家可以运行程序了,这时会在项目目录中生成一个XML文档。


结语


数据库和XML在很多程序中都经常用到,它们的使用也总是和数据的显示联系起来,大家只有通过编写实例,通过大量的代码才能真正掌握这些内容。

源码下载:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

累计签到:1 天
连续签到:1 天
2018-3-14 10:10:28 显示全部楼层
不更新了吗,还是已经完结了。。。
回复 支持 反对

使用道具 举报

累计签到:50 天
连续签到:1 天
2018-11-18 21:32:44 显示全部楼层
老师好。    读取文件我有些疑问。      有开始文档, 开始元素,结束元素, 还有Characters。  怎么知道我的属性里面就是这个值呢?  
<?xml version="1.0" encoding="UTF-8"?>
<library>
    <book id="01">
        <title>Qt</title>
        <author>shiming</author>
    </book>
    <book id="02">
        <title>Linux</title>
        <author>yafei</author>
    </book>
</library>


怎么知道这个book   id=1的情况对应的标题和作者  ?     
回复 支持 反对

使用道具 举报

累计签到:1608 天
连续签到:1 天
2018-11-18 22:15:59 显示全部楼层
tan 发表于 2018-11-18 21:32
老师好。    读取文件我有些疑问。      有开始文档, 开始元素,结束元素, 还有Characters。  怎么知道我 ...

可以在程序中进行判断。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了