1. 程式人生 > >Qt下讀寫XML格式檔案(使用QDomDocument類)

Qt下讀寫XML格式檔案(使用QDomDocument類)

簡述

XML是一種標記語言,被設計用來結構化儲存以及傳輸資訊,是一種常用的文件資料結構。
就我個人而言,Qt下讀寫XML格式檔案可以有三種方法:
一是使用純C++的rapidxml開源庫。優點是速度快,媲美strlen()的速度;缺點是處理中文比較麻煩,編碼只有ANSI格式。
二是使用QXmlStreamReader類,適當結合QXmlQuery類。優點是靈活性強,節約記憶體;缺點是理解起來相對較難,還需要一點資料庫語言的知識。
三是使用QDomDocument類。是Qt下讀寫xml檔案傳統而普遍的做法,缺點就是如果讀寫的檔案很大,會消耗大量的記憶體空間。
QDomDocument類可以理解為一個QFile,這個類的物件代表了整個檔案,通常也是一個xml檔案的主節點。還需使用到的類有QDomNode(節點基類)、QDomElement(節點類)、QDomText(內容)、QDomAttr(屬性)、QDomProcessingInstruction(檔案頭)。

程式碼之路

讀寫一個使用者名稱檔案"user.xml",檔案內容如下:

<?xml version = "1.0" encoding = "UTF-8"?>
<ALL>
  <DATA>
      <Name>1</Name>
      <Password>12</Password>
      <Describe>123</Describe>
      <Flag>1</Flag>
  </DATA>
  <DATA>
      <Name>2</Name>
      <Password>22</Password>
      <Describe>234</Describe>
      <Flag>1</Flag>
  </DATA>
</ALL>

讀取上述內容的xml檔案到一個結構體中

//使用者資訊結構體
struct UserStruct
{
  QString username; 
  QString password;
  QString decribe;
  int flag;    //使用者許可權
  void clear()
  {
    username = "";
    password = "";
    describe = "";
    flag = 1;
  }
};

讀xml格式函式程式碼如下:

void readUserxml()
{
  UserStruct tmpInfo;
  QFile file(filename);
  if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
  {
  	return;
  }
  QDomDocument doc;  //xml格式檔案
  if (!doc.setContent(&file))
  {
  	file.close();
  	return;
  }
  file.close();
  QDomElement root = doc.documentElement(); //節點 ALL
    if (!root.isNull())
    {
        QDomNode node_a = root.firstChild(); //節點DATA
        while (!node_a.isNull())
        {
            QDomElement node_all = node_a.toElement(); //QDomnode轉成QDomElement
            if (!node_all.isNull())
            {
                tmpInfo.clear(); //清空
                QDomElement n_name = node_all.firstChildElement("Name"); //Name節點

                if (!n_name.isNull())
                {
                    tmpInfo.username = n_name.text();
                }
                QDomElement n_passwd = node_all.firstChildElement("Password"); //Password節點
                if (!n_passwd.isNull())
                {
                    tmpInfo.password = n_passwd.text();
                }
                QDomElement n_describe = node_all.firstChildElement("Describe"); //Describe節點
                if (!n_describe.isNull())
                {
                    tmpInfo.describe = n_describe.text();
                }
                QDomElement n_flag = node_all.firstChildElement("Flag"); //Flag節點
                if (!n_flag.isNull())
                {
                    tmpInfo.flag  = n_flag.text().toInt();
                }

             //   //加入vector
             //   UserInfo.push_back(tmpInfo);
            }
            node_a = node_a.nextSibling();       //讀取下一個DATA節點
        }
    }
}

寫XML格式檔案

void writeUserxml()
{
    //寫入xml
    QFile file(Filename);
    if (!file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate))
    {
        return;
    }
    QDomDocument doc;
    QDomProcessingInstruction instruction;
    instruction = doc.createProcessingInstruction("xml", "version = \"1.0\" encoding = \"UTF-8\"");
    doc.appendChild(instruction);         //寫入檔案頭

    QDomElement root = doc.createElement("ALL");
    doc.appendChild(root);

//    UserStruct tmp;
//    tmp.username = "11";
//    tmp.password = "1234";
//    tmp.describe = "321";
//    tmp.flag = 1;
//    UserInfo.push_back(tmp);

    int sum = UserInfo.size();

//    struct UserStruct
//    {
//        QString username;
//        QString password;
//        QString describe;
//        int flag;
//    };

    for (int i = 0; i < sum; ++i)
    {
        QDomElement node_data = doc.createElement("DATA");
        QDomElement node_name = doc.createElement("Name");
        QDomElement node_passwd = doc.createElement("Password");
        QDomElement node_describe = doc.createElement("Describe");
        QDomElement node_flag = doc.createElement("Flag");

        node_name.appendChild(doc.createTextNode(UserInfo[i].username));
        node_passwd.appendChild(doc.createTextNode(UserInfo[i].password));
        node_describe.appendChild(doc.createTextNode(UserInfo[i].describe));
        node_flag.appendChild(doc.createTextNode(QString::number(UserInfo[i].flag)));

        node_data.appendChild(node_name);
        node_data.appendChild(node_passwd);
        node_data.appendChild(node_describe);
        node_data.appendChild(node_flag);

        root.appendChild(node_data);
    }
    QTextStream out(&file);
    doc.save(out, 4);     //寫入檔案中
    file.close();
}

例子中沒有涉及到節點屬性,下面補充一下節點屬性的寫入:

QDomAttr atr = doc.createAttribute("id");
atr.setValue(str_id);
node_date.setAttributeNode(atr);

總結

Qt下使用QDomdocument類書寫xml程式碼量相對不少,但是思路還是很清晰的。