本文我们通过一个读取Xml文件的小例子来学习QXmlStreamReader。

Xml 简介

Xml的全称是可扩展标记语言(EXtensible Markup Language),同HTML一样是一种标记语言。但是与HTML不同,XML:

  • 被设计为具有自我描述性
  • 没有预定义标签,需要使用者自行定义。
  • 设计宗旨是传输数据,而非显示数据(HTML)。大多数Android App开发都用Xml文件作为界面开发的数据载体。

QXmlStreamReader 简介

QXmlStreamReader is a faster and more convenient replacement for Qt's own SAX parser (see QXmlSimpleReader).

官方宣称这是一个比Qt的SAX(Simple API for XML)解析器更快、更方便的替代,也就是说建议你优先使用它来解析Xml文件。

QXmlStreamReader和SAX的工作原理类似,都是以Token为单位对Xml文件进行读取解析。使用QXmlStreamReader基本上有两种模式:

这两种方法的区别就是处理单位的不同,分别以Token、Element为单位:前者粒度更细,把控可以更精准,但相对的需要花更多的功夫在细节处理上;后者只关注元素,对于简单的处理使用起来很方便。在QXmlStreamReader中,读取Token需要调用QXmlStreamReader::readNext()函数,该函数返回读取到的Token,不同的Token类型需要调用不同的函数来获取相关的内容,详细内容参见Qt官方链接;而读取元素则是调用QXmlStreamReader::readNextStartElement()函数,注意此函数简单地区别头元素和尾元素,如果是头元素则返回true,否则(尾元素或出错)返回false。

解析Xml 元素

Xml中的元素与HTML一样:

<title>Colombia Earthquake</title>

这就是一个title元素,包含一些文本内容。我们通过调用QXmlStreamReader::readNextStartElement()来读取它,当读取的是一个元素的时候,QXmlStreamReader::name()函数返回元素的名字,QXmlStreamReader::readElementText()返回元素内的文本。

解析Xml 文档元素

<?xml version="1.0" encoding="ISO-8859-1"?>

Xml文档元素包含常见的xml版本、编码、独立文档(standalone)等元数据,这些属性分别对应QXmlStreamReader的documentVersion()documentEncoding()isStandaloneDocument()等函数,但是在调用这些函数前我们需要先调用readNext()函数让解析器先去读取这个特殊元素。

void MainWindow::readDocumentElement()
{
m_xmlReader.readNext();
if (m_xmlReader.isStartDocument()) {
auto item = new QTreeWidgetItem(
QStringList("Document Element"));
item->setText(1, "xml version:" + m_xmlReader.documentVersion().toString() +
" encoding:" + m_xmlReader.documentEncoding().toString() +
" is standalone:" + (m_xmlReader.isStandaloneDocument() ? QString("true") : QString("false")));
item->setBackgroundColor(1, QColor(Qt::green));
m_treeWidget.addTopLevelItem(item);
}
}

解析Xml CDATA

CDATA(Character Data) 代表字符数据,这个区段中的文本不会被Xml 解析器解析,而是原样保留输出。CDATA区段以<![CDATA[开始,以]]>结束,这两个标记符号中间的文本可以是]]>以外的任何字符。CDATA经常被用来存储那些包含特殊字符(Xml关键字或者保留字符)的文本,如下:

<![CDATA[ This is a <CDATA> section text! ]]>

<在Xml是特殊字符,用来标识元素的开始,如果上面这段文字不写在CDATA区段中,这块内容就会被解析为头元素;通过CDATA区段,Xml 解析器会把这块内容原样输出。使用QXmlStreamReader,我们的代码类似如下:

void MainWindow::readCDATA()
{
while (!m_xmlReader.isCDATA()) {
m_xmlReader.readNext();
}
auto item = new QTreeWidgetItem(QStringList("[CDATA]"));
item->setText(1, m_xmlReader.text().toString());
item->setBackgroundColor(1, QColor(Qt::cyan));
m_treeWidget.addTopLevelItem(item);
}

因为CDATA区段不是元素,因此我们需要调用QXmlStreamReader::readNext()函数。

解析Xml DTD

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。

简而言之,DTD是用来描述Xml文档的结构的,语法如下:

<!DOCTYPE 根元素 [元素声明]>

例如下面这个DTD:

<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>

该DTD 解释如下:

!DOCTYPE note (第1行)定义此文档是 note 类型的文档。

!ELEMENT note (第2行)定义 note 元素有四个元素:"to、from、heading,、body"

!ELEMENT to (第3行)定义 to 元素为 "#PCDATA" 类型

!ELEMENT from (第4行)定义 from 元素为 "#PCDATA" 类型

!ELEMENT heading (第5行)定义 heading 元素为 "#PCDATA" 类型

!ELEMENT body (第6行)定义 body 元素为 "#PCDATA" 类型

用QXmlStreamReader解析DTD也非常方便,方法与解析CDATA一样,只是换了个判断函数:

while (!m_xmlReader.isDTD()) {
m_xmlReader.readNext();
}
auto item = new QTreeWidgetItem(QStringList("[DTD]"));
item->setText(1, m_xmlReader.text().toString());
item->setBackgroundColor(1, QColor(Qt::darkMagenta));
m_treeWidget.addTopLevelItem(item);

解析Xml 注释

Xml 的注释也与HTML相同,<!-- XXXXXXXXXXXXXXXXXXX -->,代码与上一小节基本一样,只是判断处改用了QXmlStreamReader::isComment()

while (!m_xmlReader.isComment()) {
m_xmlReader.readNext();
}
...

解析Xml Processing Instruction

XMl PI(Processing Instruction) 处理指令使用这种格式<?PITarget PIContent?>,前一部分是Target,后一部分是Content。Processing Instruction用来告诉Xml应用程序进行一些Xml以外的操作,例如在有一些应用中,Xml文件需要包含一些CSS文件用以应用样式来渲染自身:

<?xml-stylesheet type="text/css" href="tutorials.css"?>

在QXmlStreamReader中,好像紧贴<?的被识别位Target,后面的内容都被认为是Content:

while (!m_xmlReader.isProcessingInstruction()) {
m_xmlReader.readNext();
}
auto item = new QTreeWidgetItem(QStringList("[ProcessingInstruction]"));
item->setText(1, "target: " + m_xmlReader.processingInstructionTarget().toString() +
" content: " + m_xmlReader.processingInstructionData().toString());
item->setBackgroundColor(1, QColor(Qt::yellow));
m_treeWidget.addTopLevelItem(item);

获取PI相关内容需要分别调用QXmlStreamReader::processingInstructionTarget()QXmlStreamReader::processingInstructionData()

示例运行结果

因为Xml的元素是自定义的,这就意味着往往不同的Xml内部的元素结构都不一样,不同的约定格式需要编写不同的逻辑代码处理。这个示例我们用QTreeWidget来展示解析出来的结构和内容:

完整代码见链接

Qt---Xml文件解析的更多相关文章

  1. 通过正则表达式实现简单xml文件解析

    这是我通过正则表达式实现的xml文件解析工具,有些XHTML文件中包含特殊符号,暂时还无法正常使用. 设计思路:常见的xml文件都是单根树结构,工具的目的是通过递归的方式将整个文档树装载进一个Node ...

  2. 八、Android学习第七天——XML文件解析方法(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...

  3. android基础知识13:AndroidManifest.xml文件解析

    注:本文转载于:http://blog.csdn.net/xianming01/article/details/7526987 AndroidManifest.xml文件解析. 1.重要性 Andro ...

  4. Android之AndroidManifest.xml文件解析

    转自:Android学习笔记之AndroidManifest.xml文件解析 一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文 ...

  5. 9.XML文件解析

    一.XML简介 XML(EXtensible Markup Language),可扩展标记语言 特点:XML与操作系统.编程语言的开发平台无关 实现不同系统之间的数据交换 作用:数据交互 配置应用程序 ...

  6. Python实现XML文件解析

    1. XML简介 XML(eXtensible Markup Language)指可扩展标记语言,被设计用来传输和存储数据,已经日趋成为当前许多新生技术的核心,在不同的领域都有着不同的应用.它是web ...

  7. Python3将xml文件解析为Python对象

    一.说明 从最开始写javascript开始,我就很烦感使用getElementById()等函数来获取节点的方法,获取了一个节点要访问其子孙节点要么child半天要么就再来一个getElementB ...

  8. XML文件解析-DOM4J方式和SAX方式

    最近遇到的工作内容都是和xml内容解析相关的. 1图片数据以base64编码的方式保存在xml的一个标签中,xml文件通过接口的方式发送给我,然后我去解析出图片数据,对图片进行进一步处理. 2.xml ...

  9. java基础之概谈xml文件解析

    XML已经成为一种非常通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便. 诸多web应用框架,其可配置的编程方式,给我们的开发带来了非常大程度的便捷,但细细 ...

  10. XML文件解析之JDOM解析

    1.JDOM介绍 JDOM的官方网站是http://www.jdom.org/,JDOM解析用到的jar包可以在http://www.jdom.org/dist/binary/中下载,最新的JDOM2 ...

随机推荐

  1. 继承“HibernateDaoSupport”后,报“The hierarchy of the type AccoutDaoImpl is inconsistent”的解决方案

    解决办法: 今天写了一段很简单的代码,Eclipse竟然报错 import org.springframework.jdbc.core.support.JdbcDaoSupport; import c ...

  2. jfinal使用jstl表达的存在的问及解决

    问题 使用jstl 的el表达式 传递数据刷新页面,页面数据不显示,经过验证,数据的确传递过去,但是官方文档并没有详细描述,getModel() 不需要设get set() ,但是使用jstl el表 ...

  3. LINUX 笔记-文件名的匹配

    特殊的匹配符号: * 匹配文件名中的任何字符串,包括空字符串 ? 匹配文件名中的任何单个字符串 [...] 匹配[]中包含的任何字符 [!...] 匹配[]中非感吧号!之后的字符

  4. 前端-如何用gulp快速搭建项目(sass预编译,代码压缩,css前缀,浏览器自动刷新,雪碧图合成)

    一:gulp优点: 易于使用 通过代码优于配置的策略,Gulp 让简单的任务简单,复杂的任务可管理: 插件高质 Gulp 严格的插件指南确保插件如你期望的那样简洁高质得工作. 构建快速 利用 Node ...

  5. Redis主从环境配置

    1.Redis主从同步原理 redis主服务器会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,然后将数据文件同步给从服务器,从服务器加载记录文件,在内存库中更新新数据. 2.VMWar ...

  6. SQL语句查询表中的所有约束

    select * from sysobjects where parent_obj in(select id from sysobjects where name='表名') 或者 exec sp_h ...

  7. Ubuntu配置OpenStack 二:配置时间同步NTP和安装数据库Maridb以及问题总结

    继上一节Ubuntu配置OpenStack 一:配置主机环境,下面继续为安装时间同步,以及配置openstack的安装包源和安装数据库Maridb.(全文截图都是由自己徒手搭建完成并且截图) 一.安装 ...

  8. 利用wsdl.exe自动将wsdl文档转换为C#代码

    1.获取完整的wsdl文档 获取下面这个博客中提到的wsdl http://www.cnblogs.com/LCCRNblog/p/3716406.html 将获取到的wsdl放到一个文本中,改后缀( ...

  9. FatMouse and Cheese

    FatMouse and Cheese Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  10. web前端优化--DOM性能优化

    1.DOM访问与修改的优化: DOM访问是有代价的,修改DOM则会引起DOM的重绘与重排,而这两种操作会消耗性能. (1)缓存DOM:将频繁访问的对象或属性使用变量缓存起来,每次访问的时候,直接使用变 ...