QDomDocument 讀取和編輯xml文件


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,同樣可以使用以上方法。
如果一個QDomDocumentfirstChildElement()返回的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還提供了替換節點的方法,自行探索。

轉載請注明出處

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM