QT讀寫XML
QQ:609162385
一、DOM簡介
1、DOM簡介
DOM是Document Object Model的簡寫,即XML文件物件模型,是由W3C提出的一種處理XML文件的標準介面。
DOM 一次性讀入整個XML文件,在記憶體中構造為一棵樹(DOM樹)將XML檔案表示成一棵樹,便於隨機訪問其中的節點,但消耗記憶體相對多一些。能夠在這棵樹上進行導航,比如移動到下一節點或者返回上一節點,也可以對這棵樹進行修改,或者是直接將這顆樹儲存為硬碟上的一個 XML 檔案。
2、XML DOM節點
XML 文件中的每個成分都是一個節點,整個文件是一個文件節點,每個XML 標籤是一個元素節點,包含在XML元素中的文字是文字節點, 每一個XML屬性是一個屬性節點,註釋屬於註釋節點。
QT中使用QDomDocument來表示XML文件,QDomElement表示XML文件的元素,QDomProcessingInstruction表示XML處理指令,QDomAttr表示元素的屬性,QDomText表示XML文件中的文字資料。所有的DOM節點如處理指令、元素、屬性和文字資料等,都使用QDomNode來表示,然後使用對應的 isProcessingInstruction()、isElement()、isAttr()和isText()等函式來判斷是否是該型別的節點,如果是,那麼就可以使用toProcessingInstruction()、toElement()、toAttr()和toText()等函式轉換為具體型別的節點。 文字資料總是儲存在文字節點中,元素節點的文字資料是儲存在文字節點中的。
二、QDomDocument
1、QDomDocument簡介
QDomDocument類用於顯示XML文件,是文件樹的根節點,提供了對文件資料的主要訪問。由於元素、文字節點、註釋、說明等不能在文件外部,QDomDocument包含了建立這些物件的工廠函式。
需要解析的XML文件在內部顯示為一棵被QDOM其它類訪問的物件樹。所有的QDOM類只能引用物件樹中的物件。一旦或是QDomDocument根節點被刪除,DOM樹中的所有內部物件將被刪除。 元素、文字節點等的建立由QDomDocument類提供的工廠函式完成。使用預設的QDOM類的建構函式只能得到一個不能操作、插入文件的空物件。 QDomDocument類有多個用於建立文件資料的函式,如createElement、createTextNode、createComment、createCDATASection、createProcessingInstruction、createAttribute和createEntityReference。這些函式中的一些支援名稱空間的版本。createDocumentFragment函式為了持有文件中的部分內容,對於操作複雜文件是很有用的。 設定文件的整體內容使用setContent()函式。setContent函式通過XML文件和建立顯示文件的DOM樹來解析文件。 對於較大的XML文件,DOM樹會佔用較大的記憶體空間。對於較大的XML文件,使用QXmlStreamReader或QXmlQuery會使更好的解決方案。
2、QDomDocument成員函式
QDomDocument::QDomDocument(const QString &name)
QDomDocument::QDomDocument(const QDomDocumentType &doctype)
QDomDocument::QDomDocument(const QDomDocument &x)
建構函式
QDomAttr QDomDocument::createAttribute(const QString &name)
建立一個能夠插入到元素的名為name的新屬性
QDomAttr QDomDocument::createAttributeNS(const QString &nsURI, const QString &qName)
建立一個能夠插入到元素的支援名稱空間的新屬性,名字為qName,名稱空間為nsURI
QDomCDATASection QDomDocument::createCDATASection(const QString &value)
建立一個能插入文件的值為value的新CDATA段
QDomComment QDomDocument::createComment(const QString &value)
建立一個能插入文件的值為value的新註釋
QDomDocumentFragment QDomDocument::createDocumentFragment()
建立一個持有文件部分內容的文件段
QDomElement QDomDocument::createElement(const QString &tagName)
建立一個能插入DOM樹的名為tagName的新元素
QDomElement QDomDocument::createElementNS(const QString &nsURI, const QString &qName)
建立一個能插入DOM樹的支援名稱空間的名為qName的新元素,名稱空間為nsURI
QDomEntityReference QDomDocument::createEntityReference(const QString &name)
建立一個能插入文件的名為name的新實體引用
QDomProcessingInstruction QDomDocument::createProcessingInstruction(const QString &target, const QString &data)
建立一個能插入文件的新的說明,設定說明的目標為target,資料為data
QDomText QDomDocument::createTextNode(const QString &value)
建立一個能插入文件樹的值為value的新文字節點
QDomDocumentType QDomDocument::doctype() const
返回文件的文件型別
QDomElement QDomDocument::documentElement() const
返回文件的根元素
QDomElement QDomDocument::elementById(const QString &elementId)
返回ID為elementId的元素
QDomNodeList QDomDocument::elementsByTagName(const QString &tagname) const
返回包含tagname文件的所有元素的節點連結串列
QDomNodeList QDomDocument::elementsByTagNameNS(const QString &nsURI, const QString &localName)
返回包含本地名為localName、名稱空間為nsURI的文件的所有元素的節點連結串列
QDomImplementation QDomDocument::implementation() const
返回QDomImplementation物件
QDomNode QDomDocument::importNode(const QDomNode &importedNode, bool deep)
從另一個文件匯入importedNode節點到文件,如果deep為true,匯入importedNode節點的子樹,否則匯入importedNode節點。
QDomNode::NodeType QDomDocument::nodeType() const
返回節點型別
bool QDomDocument::setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg = Q_NULLPTR, int *errorLine = Q_NULLPTR, int *errorColumn = Q_NULLPTR)
從位元組陣列資料data解析XML文件,並設定為文件的內容
bool QDomDocument::setContent(const QString &text, bool namespaceProcessing, QString *errorMsg = Q_NULLPTR, int *errorLine = Q_NULLPTR, int *errorColumn = Q_NULLPTR)
從字串text中讀取XML文件,如果成功解析了內容,返回true
bool QDomDocument::setContent(QIODevice *dev, bool namespaceProcessing, QString *errorMsg = Q_NULLPTR, int *errorLine = Q_NULLPTR, int *errorColumn = Q_NULLPTR)
從裝置dev中讀取XML文件,如果成功解析了內容,返回true
bool QDomDocument::setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg = Q_NULLPTR, int *errorLine = Q_NULLPTR, int *errorColumn = Q_NULLPTR)
從QXmlInputSource中讀取XML文件,如果成功解析了內容,返回true
QByteArray QDomDocument::toByteArray(int indent = 1) const
返回解析後的文件的文字內容的UTF-8格式的位元組陣列資料
QString QDomDocument::toString(int indent = 1) const
返回解析後的文件的文字內容
三、QDomElement
1、QDomElement簡介
QDomElement表示DOM樹中的一個元素節點。元素有一個標籤名和0個或多個屬性。
2、QDomElement成員函式
QString QDomElement::attribute(const QString &name, const QString &defValue = QString()) const
返回元素的名字為name的屬性,如果不存在,返回defValue預設值
QDomAttr QDomElement::attributeNode(const QString &name)
返回元素中名字為name的屬性的QDomAttr物件
QDomNamedNodeMap QDomElement::attributes() const
返回元素中所有屬性的通過名字訪問屬性節點的集合
QDomNodeList QDomElement::elementsByTagName(const QString &tagname) const
返回元素名為tagname的元素的所有子節點的前序遍歷的節點連結串列
bool QDomElement::hasAttribute(const QString &name) const
如果元素中有名字為name的屬性,返回true
void QDomElement::removeAttribute(const QString &name)
刪除元素中名字為name的屬性
void QDomElement::setAttribute(const QString &name, const QString &value)
在元素中新增一個名字為name,值為value的屬性,如果已經存在,使用value替換值
void QDomElement::setTagName(const QString &name)
設定元素的標籤名為name
QString QDomElement::tagName() const
返回元素的標籤名
QString QDomElement::text() const
返回元素的文字
四、QDomAttr
QDomAttr表示元素的屬性
QString QDomAttr::name() const
返回屬性的名字
QDomElement QDomAttr::ownerElement() const
返回屬性所屬的元素節點
void QDomAttr::setValue(const QString &v)
設定屬性的值為v
bool QDomAttr::specified() const
如果屬性已經由使用者設定,返回true
QString QDomAttr::value() const
返回屬性的值
五、DOM方式操作XML檔案
DOM方式解析XML檔案先開啟XML檔案,將XML檔案整體載入到記憶體中建立DOM樹,對於XML文件的任何操作在記憶體中的DOM樹直接操作,最後儲存時將DOM樹的所有節點寫回XML文件。需要注意的是,通常開啟XML檔案,將XML檔案載入到記憶體中建立DOM樹後,XML檔案就可以關閉了。如果要儲存改變後的XML文件內容,需要在儲存時以清空檔案的方式開啟XML檔案,將改變後DOM樹的所有節點寫入XML檔案即可。
1、讀取XML檔案
<?xml version="1.0" encoding="UTF-8"?><book time="2013/6/13" id="1">
<title>C++ primer</title>
<author>Stanley Lippman</author>
</book>
<book time="2007/5/25" id="2">
<title>Thinking in Java</title>
<author>Bruce Eckel</author>
</book>
讀取的XML檔案的程式碼如下:
//開啟或建立檔案
QFile file(“test.xml”);
if(!file.open(QFile::ReadOnly))
return;
QDomDocument doc;
//設定test.xml到文件
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();
//返回根節點
QDomElement root=doc.documentElement();
qDebug()<<root.nodeName();
//獲得第一個子節點
QDomNode node=root.firstChild();
while(!node.isNull()) //如果節點不空
{
if(node.isElement()) //如果節點是元素
{
//轉換為元素
QDomElement e=node.toElement();
qDebug()<<e.tagName()<<" "<<e.attribute("id")<<" "<<e.attribute("time");
QDomNodeList list=e.childNodes();
for(int i=0;i<list.count();i++)
{
QDomNode n=list.at(i);
if(node.isElement())
qDebug()<<n.nodeName()<<":"<<n.toElement().text();
}
}
//下一個兄弟節點
node=node.nextSibling();
}
2、寫XML檔案
//開啟或建立檔案
QFile file(“test.xml”);
//QIODevice::Truncate表示清空原來的內容
if(!file.open(QFile::WriteOnly|QFile::Truncate))
return;
QDomDocument doc;
//新增處理命令
QDomProcessingInstruction instruction;
instruction=doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
//新增根節點
QDomElement root=doc.createElement("library");
doc.appendChild(root);
//新增第一個子節點及其子元素
QDomElement book=doc.createElement("book");
//方式一:建立屬性 其中鍵值對的值可以是各種型別
book.setAttribute("id",1);
//方式二:建立屬性 值必須是字串
QDomAttr time=doc.createAttribute("time");
time.setValue("2013/6/13");
book.setAttributeNode(time);
QDomElement title=doc.createElement("title"); //建立子元素
QDomText text; //設定括號標籤中間的值
text=doc.createTextNode("C++ primer");
book.appendChild(title);
title.appendChild(text);
QDomElement author=doc.createElement("author"); //建立子元素
text=doc.createTextNode("Stanley Lippman");
author.appendChild(text);
book.appendChild(author);
//新增節點book做為根節點的子節點
root.appendChild(book);
//新增第二個子節點及其子元素
book=doc.createElement("book");
book.setAttribute("id",2);
time=doc.createAttribute("time");
time.setValue("2007/5/25");
book.setAttributeNode(time);
title=doc.createElement("title");
text=doc.createTextNode("Thinking in Java");
book.appendChild(title);
title.appendChild(text);
author=doc.createElement("author");
text=doc.createTextNode("Bruce Eckel");
author.appendChild(text);
book.appendChild(author);
root.appendChild(book);
//輸出到檔案
QTextStream out_stream(&file);
doc.save(out_stream,4); //縮排4格
file.close();
寫入XML檔案如下:
<?xml version="1.0" encoding="UTF-8"?><book time="2013/6/13" id="1">
<title>C++ primer</title>
<author>Stanley Lippman</author>
</book>
<book time="2007/5/25" id="2">
<title>Thinking in Java</title>
<author>Bruce Eckel</author>
</book>
3、增加XML檔案內容
//開啟檔案
QFile file(“test.xml”);
if(!file.open(QFile::ReadOnly))
return;
//增加一個一級子節點以及元素
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement root=doc.documentElement();
QDomElement book=doc.createElement("book");
book.setAttribute("id",3);
book.setAttribute("time","1813/1/27");
QDomElement title=doc.createElement("title");
QDomText text;
text=doc.createTextNode("Pride and Prejudice");
title.appendChild(text);
book.appendChild(title);
QDomElement author=doc.createElement("author");
text=doc.createTextNode("Jane Austen");
author.appendChild(text);
book.appendChild(author);
root.appendChild(book);
if(!file.open(QFile::WriteOnly|QFile::Truncate))
return;
//輸出到檔案
QTextStream out_stream(&file);
doc.save(out_stream,4); //縮排4格
file.close();
4、刪除XML檔案
//開啟檔案
QFile file(“test.xml”);
if(!file.open(QFile::ReadOnly))
return;
//刪除一個一級子節點及其元素,外層節點刪除內層節點於此相同
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement root=doc.documentElement();
QDomNodeList list=doc.elementsByTagName("book"); //由標籤名定位
for(int i=0;i<list.count();i++)
{
QDomElement e=list.at(i).toElement();
if(e.attribute("time")=="2007/5/25")
root.removeChild(list.at(i));
}
if(!file.open(QFile::WriteOnly|QFile::Truncate))
return;
//輸出到檔案
QTextStream out_stream(&file);
doc.save(out_stream,4); //縮排4格
file.close();
5、修改XML檔案
//開啟檔案
QFile file(“test.xml”);
if(!file.open(QFile::ReadOnly))
return;
//更新一個標籤項,如果知道xml的結構,直接定位到那個標籤上定點更新
//或者用遍歷的方法去匹配tagname或者attribut,value來更新
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement root=doc.documentElement();
QDomNodeList list=root.elementsByTagName("book");
QDomNode node=list.at(list.size()-1).firstChild();
QDomNode oldnode=node.firstChild();
node.firstChild().setNodeValue("Emma");
QDomNode newnode=node.firstChild();
node.replaceChild(newnode,oldnode);
if(!file.open(QFile::WriteOnly|QFile::Truncate))
return;
//輸出到檔案
QTextStream out_stream(&file);
doc.save(out_stream,4); //縮排4格
file.close();