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還提供了替換節點的方法,自行探索。
轉載請注明出處