本文咱們經過一個讀取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來展現解析出來的結構和內容:
完整代碼見連接。