Qt中幾種操作xml的方式
- 流方式
- sax方式
- dom方式
初學時,我常常採用流方式讀取xml,該方式簡單直觀,容易理解。之後遇到了需要修改xml並重新寫回的情況,流方式就顯得捉襟見肘了。
sax方式接觸不多,從來沒有在實際生產中使用過。
dom方式概念複雜,對於個人來說,文件也不是很清晰,導致我一直對這個方式不甚瞭解,最近下定決心好好研究一番,也算是大致清楚了箇中“套路”,在此記錄,以便今後查閱。
注意:如果你對QDomDocument沒有任何瞭解,則不適合閱讀此文章。如果你在使用QDomDocumentde的過程中產生了疑惑,則此文可能對你產生幫助。
如有疏漏,還望指正。
QDomNode ? QDomElemet? QDomAttr?QDomText?
初見QDomDocument時,我被這些東西搞得一頭霧水。
直到我看到了某部落格中這樣一段話:
QDom字首的都是代表節點型別。所以有,QDomElement代表一個Element節點,而QDomText代表一個Text節點。QDomNode類可以儲存任意型別的節點。如果想進一步處理一個節點,首先必須把它轉化為正確的資料型別。QDomNode呼叫toElement()以把它轉化成QDomElement,然後呼叫tagName()來獲得元素的標籤名稱。如果節點不是Element型別,那麼toElement()函式就返回一個空QDomElement物件和一個空標籤。1
我們對xml操作,無非對節點文字,節點屬性進行操作,因此,我著重在這個基礎上整理一下。
QDomNode 相容所有節點型別。
這裡只討論QDomNode為QDomElemet的情況;此時讀者心裡一驚,難道,還有不是的情況?當然有!
QDomNode QDomElemet
舉個簡單例子
你看!
- 有如下xml
<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>
有如下程式碼:
- code 01
QDomElement root = doc.documentElement();
QDomNode node= root.firstChild();
qDebug() << root.attributeNode("category").value();
while(!node.isNull())
{
qDebug() << "xx";
node = node.nextSibling();
}
結果會輸出幾個xx呢?
程式碼做出如下更改
- code 02
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物件和一個空標籤
[========]
QDomElemet 與 QDomAttr QDomText
經過上面的試驗,我們還可以得到另一個結論,那就是
屬性
不是QDomELement
的子QDomELement
屬性
不是QDomNode
的子QDomNode
還有一件事我們不知道,那就是QDomELement
中的文字算是它的子QDomELement
麼?
<bookstore category="xml">hello</bookstore>
- code 03
QDomElement ele= root.firstChildElement();
while(!ele.isNull())
{
qDebug() << "xx";
ele = ele.nextSiblingElement();
}
程式不會有任何輸出
文字
不是QDomELement
的子QDomELement
- code 04
QDomNode node= root.firstChild();
while(!node.isNull())
{
qDebug() << "xx";
node = node.nextSibling();
}
程式將會輸出一個xx
文字
是QDomNode
的子QDomNode
瞭解了它們之間的聯絡之後,我們現在迫切的需要知道一個問題,既然文字和屬性都不是子QDomELement,如何獲取到文字和屬性呢?
讀寫xml
遍歷某QDomELement的 子QDomELement
- 示例xml
<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>
- code 05 遍歷
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的最底層了,接下來介紹獲取文字和屬性的方法。
- code 06 讀取
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還提供了替換節點的方法,自行探索。
轉載請註明出處