初學時,我經常採用流方式讀取xml,該方式簡單直觀,容易理解。以後遇到了須要修改xml並從新寫回的狀況,流方式就顯得捉襟見肘了。html
sax方式接觸很少,歷來沒有在實際生產中使用過。node
dom方式概念複雜,對於我的來講,文檔也不是很清晰,致使我一直對這個方式不甚瞭解,最近下定決心好好研究一番,也算是大體清楚了箇中「套路」,在此記錄,以便從此查閱。dom
注意:若是你對QDomDocument沒有任何瞭解,則不適合閱讀此文章。若是你在使用QDomDocumentde的過程當中產生了疑惑,則此文可能對你產生幫助。函數
若有疏漏,還望指正。code
初見QDomDocument時,我被這些東西搞得一頭霧水。
直到我看到了某博客中這樣一段話:xml
QDom前綴的都是表明節點類型。因此有,QDomElement表明一個Element節點,而QDomText表明一個Text節點。QDomNode類能夠存儲任意類型的節點。若是想進一步處理一個節點,首先必須把它轉化爲正確的數據類型。QDomNode調用toElement()以把它轉化成QDomElement,而後調用tagName()來得到元素的標籤名稱。若是節點不是Element類型,那麼toElement()函數就返回一個空QDomElement對象和一個空標籤。1htm
咱們對xml操做,無非對節點文本,節點屬性進行操做,所以,我着重在這個基礎上整理一下。對象
QDomNode 兼容全部節點類型。
這裏只討論QDomNode爲QDomElemet的狀況;此時讀者內心一驚,難道,還有不是的狀況?固然有!blog
舉個簡單例子
你看!文檔
<bookstore category="xml"> <book category="CHILDREN"> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <!-- asdasd--> <book category="WEB"> <title>Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> <test>hello</test> </bookstore>
有以下代碼:
QDomElement root = doc.documentElement(); QDomNode node= root.firstChild(); qDebug() << root.attributeNode("category").value(); while(!node.isNull()) { qDebug() << "xx"; node = node.nextSibling(); }
結果會輸出幾個xx呢?
代碼作出以下更改
QDomElement root = doc.documentElement(); QDomElement node= root.firstChildElement(); qDebug() << root.attributeNode("category").value(); while(!node.isNull()) { qDebug() << "xx"; node = node.nextSiblingElement(); }
結果會輸出幾個xx呢?
答案分別是4和3!:smirk: :smirk:
結論:註釋
是QDomNode
而不是QDomElement
到這裏,你們應該就能明白二者的區別了。也應該能讀懂上邊的
QDomNode調用toElement()以把它轉化成QDomElement,而後調用tagName()來得到元素的標籤名稱。若是節點不是Element類型,那麼toElement()函數就返回一個空QDomElement對象和一個空標籤
[========]
通過上面的試驗,咱們還能夠獲得另外一個結論,那就是
屬性
不是QDomELement
的子QDomELement
屬性
不是QDomNode
的子QDomNode
還有一件事咱們不知道,那就是QDomELement
中的文本算是它的子QDomELement
麼?
<bookstore category="xml">hello</bookstore>
QDomElement ele= root.firstChildElement(); while(!ele.isNull()) { qDebug() << "xx"; ele = ele.nextSiblingElement(); }
程序不會有任何輸出
文本
不是QDomELement
的子QDomELement
QDomNode node= root.firstChild(); while(!node.isNull()) { qDebug() << "xx"; node = node.nextSibling(); }
程序將會輸出一個xx
文本
是QDomNode
的子QDomNode
瞭解了它們之間的聯繫以後,咱們如今迫切的須要知道一個問題,既然文本和屬性都不是子QDomELement,如何獲取到文本和屬性呢?
<bookstore category="xml"> <book category="CHILDREN"> <title>Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title>Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> <test>hello</test> </bookstore>
QDomDocument doc = QDomDocument(); QFile file("./test.xml"); file.open(QFile::ReadWrite); doc.setContent(&file); QDomElement root = doc.documentElement(); QDomElement ele= root.firstChildElement(); while(!ele.isNull()) { //do something ele = ele.nextSiblingElement(); }
doc.documentElement()
獲取最頂級的QDomDocument
,接下來的循環遍歷了它全部的QDomDocument
,對於它的子QDomDocument
,一樣可使用以上方法。
若是一個QDomDocument
的firstChildElement()
返回的QDomElement
爲空(ele.isNull() 爲 true
),則說明他沒有子QDomElement
,也就意味着他是xml的最底層了,接下來介紹獲取文本和屬性的方法。
QDomDocument doc = QDomDocument(); QFile file("./test.xml"); file.open(QFile::ReadWrite); doc.setContent(&file); QDomElement root = doc.documentElement(); QDomElement ele= root.firstChildElement(); qDebug() << root.attributeNode("category").nodeValue(); while(!ele.isNull()) { //此處能夠有多種斷定方法,此處只是採用了子元素爲空斷定 //實際生產中你極可能不須要這樣判斷,根據xml結構直接斷定元素名稱便可 //如 if(ele.tagName() == "xxxx") if(ele.firstChildElement().isNull()) { qDebug() << ele.tagName(); qDebug() << ele.text(); //文本是ele的子QDomNode,而不是ele自己! 因此這樣不會輸出任何東西! qDebug() << ele.toText().nodeValue(); //若是真的須要轉化爲QDomText QDomNode node = ele.firstChild(); while (!node.isNull()) { if(node.isText()) { qDebug() << node.toText().nodeValue(); } node = node.nextSibling(); } } ele = ele.nextSiblingElement(); }
輸出
"xml" "test" "hello" "" "hello"
修改很簡單,只須要將上邊的nodeValue
函數改成setNodeValue
便可。記得要寫回文件改動纔會生效哦(詳情請查看save方法的幫助文檔)。
除此以外QDomDocument還提供了替換節點的方法,自行探索。
轉載請註明出處