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