天天看點

用 Qt 中的 QDomDocument類 處理 XML 檔案(下)

QDomDocument doc;

1).建立根節點:QDomElement root = doc.documentElement("rootName " );

2).建立元素節點:QDomElement element = doc.createElement_x("nodeName");

3).添加元素節點到根節點:root. appendChild(element);

4).建立元素文本:QDomText nodeText=doc.createTextNode("text");

5).添加元素文本到元素節點:element. appendChild(nodeText);

在本項目中,假設便簽的屬性有序号、名字、内容、字型、字号、顔色、粗細、斜體、下劃線這幾項,則在檔案中添加一個便簽節點的操作如下:

QDomDocument doc;

instruction = doc.createProcessingInstruction("xml","version="1.0" encoding="UTF-8"");

doc.appendChild(instruction);

QDomElement root = doc.createElement_x("Notes");

doc.appendChild(root);

QDomElement note = doc.createElement_x("note");

root.appendChild(note);

QDomElement no = doc.createElement_x("no");

note.appendChild(no);

...

...

QDomText no_text = doc.createTextNode("001");

...

...

則得到一個便簽節點,将其儲存到test.xml檔案中,代碼如下:

QFile file("test.xml");

if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate |QIODevice::Text))

return ;

QTextStream out(&file);

out.setCodec("UTF-8");

doc.save(out,4,QDomNode::EncodingFromTextStream);

file.close();

則test.xml檔案:

<?xml version="1.0" encoding="UTF-8"?>

<Notes>

<note>

<no>001</no>

<name>2010-05-10(13:53:24)</name>

<content>A meeting!</content>

<font>Script MT Bold</font>

<fontSize>16</fontSize>

<color> #00ffff</color>

<weight>0</weight>

<fontItalic>true</fontItalic>

<fontUnderline>true</fontUnderline>

</note>

</Notes>

上面是建立一個便簽節點,若要繼續添加便簽節點,則需要在已有節點後增加一個新節點,并重寫入XML檔案。

2. 加載、查找便簽時要讀取XML文檔中的節點資訊,DOM實作方式是将整個文檔當作一個對象來裝入記憶體進行處理,然後開發者可以通路這個對象中的每一個節點,每一個節點對應XML檔案裡

的一個标記。

主要操作包括:

1).讀取根節點:QDomElement root = doc.documentElement();

2).讀取第一個子節點:QDomNode node = root.firstChild();

3).讀取下一個子節點:node = node.nextSibling();

4).比對結點标記:node.toElement().tagName() == "note"

5).讀取節點文本:no = childNode.toText().data();

//========================周遊節點================

可以通過doc.childNodes()獲得doc的所有的子節點清單QDomNodeList。比如

QDomNodeList list=doc.childNodes();

for(int i=0;i<list.count();i++){

QDomNode node=list.at(i);//好的風格當然是把定義寫在外面:(

//qDebug()<<”node name is “<<node.nodeName();

//qDebug()<<”node type is “<<.nodeType();

}

//==============================================

以下是項目中讀取便簽屬性的函數實作代碼:

void MainWindow::parseAttr(const QDomElement &element)

{

QString no,name,content,font,fontSize,color;

QDomNode node = element.firstChild();

while (!node.isNull()) {

if (node.toElement().tagName() == "note") {//比對note節點

parseAttr(node.toElement());

} else if (node.toElement().tagName() == "no") {//比對屬性no

QDomNode childNode = node.firstChild();

if (childNode.nodeType() == QDomNode::TextNode) {

no = childNode.toText().data();

}

}

else if (node.toElement().tagName() == "name") //比對屬性name

...

...

node = node.nextSibling();//讀取兄弟節點

}

}

3. 删除便簽時,要删除相應的XML節點,用到的主要函數為:root.removeChild(node); 但在删除某個節點後要重寫整個檔案。

以上對XML檔案的重寫操作是必須的,是以在檔案的打開方式中要加上QIODevice::Truncate,表示覆寫重寫。目前還沒有找到可以直接修改檔案的方法,但若檔案很大的情況下,必須考慮相

應的效率問題。

由于本項目在啟動時需要将所有便簽加載到記憶體,是以選用DOM方式比較合适,但如果處理的XML檔案很大,而且不需要全部讀到記憶體時,可以用SAX實作方式,它按階段将文檔讀取到記憶體中,

在碰到标簽或者其它階段的時候,可以調用開發者預先設計好的回調函數去處理,這樣效率比DOM方式更高。

4.讀取XML檔案内容:

//===================打開document===============add me ======

 QString xmlPath = "filename.xml";

 QFile file(xmlPath);

 if (!file.open(QFile::ReadOnly | QFile::Text))

  return ;

 QString errorStr;

 int errorLine;

 int errorColumn;

 QDomDocument doc;

 if (!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn))

  return ;

 file.close();

//也可以用doc.setContent(&file)帶一個參數就行。

//=============================================================

然後按照上面方式周遊資料,修改後在以上面相同的方式寫入到XML檔案中。

//=========================================附加一段代碼 建立XML檔案===============

int main( int argc, char **argv )

{

 QApplication a( argc, argv );

 QString xmlPath = "InitInfo.xml";

 QFile file(xmlPath);

 if (!file.open(QFile::ReadOnly | QFile::Text))

  return 1;

 QString errorStr;

 int errorLine;

 int errorColumn;

 QDomDocument doc;

 if (!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn))

  return 1;

 file.close();

 QDomElement root = doc.documentElement();

 QString str = root.tagName();

 if (root.tagName() != "Root")

  return 1;

 QDomElement element =  doc.createElement_x("device3");

 element.setAttribute("ChildName","Content");

 QDomElement el_address = doc.createElement_x("Content ");

 el_address.setAttribute("key","equipmentname");

 el_address.setAttribute("value","CSC101B");

 el_address.setAttribute("name","裝置名稱");

 //QDomText text_address = doc.createTextNode("key");

 //el_address.appendChild(text_address);

 element.appendChild(el_address);

 QDomElement el_path = doc.createElement_x("path");

 QDomText text_path = doc.createTextNode("aa");

 el_path.appendChild(text_path);

 element.appendChild(el_path);

 root.appendChild(element);

 QFile f(xmlPath);

 if (!f.open(QFile::WriteOnly | QFile::Text))

  return 1;

 QTextStream out(&f);

 QTextCodec * codec = QTextCodec::codecForName("GBK");

 out.setCodec(codec);

 QDomDocument xmlDoc;

 QString strHead("version="1.0" encoding="GB2312"");

 xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", strHead));

 out<<xmlDoc.toString();

 root.save(out, 3);

 f.close();

 return 0;

}