1. 程式人生 > >QT讀寫XML

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();