XML,全稱為 “可擴展標記語言”(extensible markup language).是一種非常方便的數據交換與數據存儲的工具。
我們在取得一個XML格式的文件后,需要作句法分析去提取發布方提供的信息。而Qt為XML提供了很好的支持,包括DOM方式的實現和SAX方式的實現。
二者主要區別是:
DOM (Document Object Model) 實現方式操作非常簡單,但不適合處理過大文件;而SAX實現方式是能處理很大的XML文件,但是需要開發者寫一些復雜的代碼。Qt提供了對應於這兩種用於 讀取、操作和編寫XML的實現類,分別是QDomDocument類和QXmlStreamReader類,這里我們選QDomDocument類來處理XML文件。
首先是讀取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();
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text)) {
return false;
}
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument doc;
if(!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn))
{ // setContent 是將指定的內容指定給QDomDocument 解析,第一參數可以是QByteArray或者是文件名等。
return false;
}
file.close();
可以通過 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 “<<node.nodeType();
}
通過上面的方法你就能知道每個節點的 名字和類型 了,節點名字就是 標記 的名字。打印出來對照着 xml文件看就很容易明白了。QDomNode類是一個父類, QDomDocument是QDomNode的一個子類,鑒於大部分 QDomNode的類型 都是QDomDocument.那么你可以使用toDocument()函數將QDomNode類型轉換成QDomDocument.
QString text=node.toElement().text();
上面的語句可以將一個節點里的 文本 取出,也就是 標記內的文本 部分。使用該函數獲得的編碼就已經是unicode格式了,不需要再做轉換。
然后是寫入XML
創建節點,將其寫入XML文件,主要操作包括:
1).創建根節點:QDomElement root = doc.documentElement("rootName " );
2).創建元素節點:QDomElement element = doc.createElement_x_x_x("nodeName");
3).添加 元素節點到 根節點:root. a(element);
4).創建文本節點:QDomText nodeText=doc.createTextNode("text");
5).添加 文本節點到 元素節點:element. a(nodeText);
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>
</note>
</Notes>
QFile file(fileName);
if(!file.open(QFile::ReadOnly | QFile::Text))
returnfalse;
QString errorStr;
interrorLine;
interrorColumn;
QDomDocument doc;
if(!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn))
returnfalse;
file.close();
QDomElement root = doc.documentElement();
if(root.tagName() != "root")
returnfalse;
QDomElement element = doc.createElement_x_x_x("file");
QDomElement el_address = doc.createElement_x_x_x("address");
QDomText text_address = doc.createTextNode("text");
el_address.a (text_address);
element.a (el_address);
QDomElement el_path = doc.createElement_x_x_x_x("path");
QDomText text_path = doc.createTextNode("text");
el_path.a (text_path);
element.a (el_path);
root.a (element);
QFile f(fileName);
if(!f.open(QFile::WriteOnly | QFile::Text))
return false;
QTextStream out(&f);
out.setCodec("UTF-8"); //中文編碼
// doc.save(out,4,QDomNode::EncodingFromTextStream);
doc.save(out, 3);
f.close();
這里所有需要append的字節點只能由QDomDocument對象create,而不能直接new它,否則永遠也看不到新添加的節點,另外,讀取和寫入的文件流必須創建兩個,否則會將需要寫入的文檔繼續在原來文檔的后面,造成多個根節點。