QDomDocument 讀取和編輯xml文件

Qt中幾種操做xml的方式

  • 流方式
  • sax方式
  • dom方式

初學時,我經常採用流方式讀取xml,該方式簡單直觀,容易理解。以後遇到了須要修改xml並從新寫回的狀況,流方式就顯得捉襟見肘了。html

sax方式接觸很少,歷來沒有在實際生產中使用過。node

dom方式概念複雜,對於我的來講,文檔也不是很清晰,致使我一直對這個方式不甚瞭解,最近下定決心好好研究一番,也算是大體清楚了箇中「套路」,在此記錄,以便從此查閱。dom

注意:若是你對QDomDocument沒有任何瞭解,則不適合閱讀此文章。若是你在使用QDomDocumentde的過程當中產生了疑惑,則此文可能對你產生幫助。函數

若有疏漏,還望指正。code

QDomNode ? QDomElemet? QDomAttr?QDomText?

初見QDomDocument時,我被這些東西搞得一頭霧水。
直到我看到了某博客中這樣一段話:xml

QDom前綴的都是表明節點類型。因此有,QDomElement表明一個Element節點,而QDomText表明一個Text節點。QDomNode類能夠存儲任意類型的節點。若是想進一步處理一個節點,首先必須把它轉化爲正確的數據類型。QDomNode調用toElement()以把它轉化成QDomElement,而後調用tagName()來得到元素的標籤名稱。若是節點不是Element類型,那麼toElement()函數就返回一個空QDomElement對象和一個空標籤。1htm

咱們對xml操做,無非對節點文本,節點屬性進行操做,所以,我着重在這個基礎上整理一下。對象

QDomNode 兼容全部節點類型。
這裏只討論QDomNode爲QDomElemet的狀況;此時讀者內心一驚,難道,還有不是的狀況?固然有!blog

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;">



相關文章
相關標籤/搜索