本文咱们经过一个读取Xml文件的小例子来学习QXmlStreamReader。css
Xml的全称是可扩展标记语言(EXtensible Markup Language),同HTML同样是一种标记语言。可是与HTML不一样,XML:html
QXmlStreamReader is a faster and more convenient replacement for Qt's own SAX parser (see QXmlSimpleReader).git
官方宣称这是一个比Qt的SAX(Simple API for XML)解析器更快、更方便的替代,也就是说建议你优先使用它来解析Xml文件。github
QXmlStreamReader和SAX的工做原理相似,都是以Token为单位对Xml文件进行读取解析。使用QXmlStreamReader基本上有两种模式:函数
这两种方法的区别就是处理单位的不一样,分别以Token、Element为单位:前者粒度更细,把控能够更精准,但相对的须要花更多的功夫在细节处理上;后者只关注元素,对于简单的处理使用起来很方便。在QXmlStreamReader中,读取Token须要调用QXmlStreamReader::readNext()
函数,该函数返回读取到的Token,不一样的Token类型须要调用不一样的函数来获取相关的内容,详细内容参见Qt官方连接;而读取元素则是调用QXmlStreamReader::readNextStartElement()
函数,注意此函数简单地区别头元素和尾元素,若是是头元素则返回true,不然(尾元素或出错)返回false。学习
Xml中的元素与HTML同样:编码
<title>Colombia Earthquake</title>
这就是一个title元素,包含一些文本内容。咱们经过调用QXmlStreamReader::readNextStartElement()
来读取它,当读取的是一个元素的时候,QXmlStreamReader::name()
函数返回元素的名字,QXmlStreamReader::readElementText()
返回元素内的文本。设计
<?xml version="1.0" encoding="ISO-8859-1"?>
Xml文档元素包含常见的xml版本、编码、独立文档(standalone)等元数据,这些属性分别对应QXmlStreamReader的documentVersion()
、documentEncoding()
、isStandaloneDocument()
等函数,可是在调用这些函数前咱们须要先调用readNext()
函数让解析器先去读取这个特殊元素。code
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); } }
CDATA(Character Data) 表明字符数据,这个区段中的文本不会被Xml 解析器解析,而是原样保留输出。CDATA区段以<![CDATA[
开始,以]]>
结束,这两个标记符号中间的文本能够是]]>
之外的任何字符。CDATA常常被用来存储那些包含特殊字符(Xml关键字或者保留字符)的文本,以下:xml
<![CDATA[ This is a <CDATA> section text! ]]>
<
在Xml是特殊字符,用来标识元素的开始,若是上面这段文字不写在CDATA区段中,
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()
函数。
文档类型定义(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 的注释也与HTML相同,<!-- XXXXXXXXXXXXXXXXXXX -->
,代码与上一小节基本同样,只是判断处改用了QXmlStreamReader::isComment()
。
while (!m_xmlReader.isComment()) { m_xmlReader.readNext(); } ...
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来展现解析出来的结构和内容:
完整代码见连接。