Qt开发(四) DOM读、写XML

1. XML DOM简介
DOM( Document Object Model 文档对象模型) 是一种用来解析 XML 文档的标准应用程序编程接口,它由万维网(W3C)所开发以及所推荐的标准。DOM 定义了所有文档元素的对象和属性,以及访问它们的方法(接口),它把 XML 文件表示成 内存 中的一棵树。使得我们可以按照需要去遍历这个 DOM 树,同时也可以对其进行修改操作,并且将其 作为 XML 文件保存到磁盘中。对于 DOM ,这里有几个重要的概念需要理解和掌握:
(1)XML 文档中的每个成分都是一个节点
DOM 是这样定义的:
①整个文档是一个文档节点
②每个 XML 标签是一个元素节点
③包含在 XML 元素中的文本是文本节点
④每一个 XML 属性是一个属性节点
⑤注释属于注释节点

(2)文本总是存储在文本节点中
在 DOM 处理中一个普遍的错误是,认为元素节点包含文本。其实是元素节点的文本是存储在文本节点中的。
比如:
<age>25</age>,元素节点 <age>,拥有一个值为 "25" 的文本节点。
"25" 不是 <age> 元素的值!

(3)XML DOM 把 XML DOM 文档视为一棵节点树 (node-tree)。树中的所有节点彼此之间都有关系

为了更加深刻的理解上面对 XML DOM的描述,下面将一个 XML 文档 用 DOM 树描述出来,注意它们之间的对应关系。

XML 文档如下:

<?xml version="1.0" encoding="UTF-8"?>
<bookcase>
    <book category="computer">
        <title lang="en"> GUI Qt</title>
        <author>Jasmin Blanchette</author>
        <year>2013</year>
        <price>75.0</price>
    </book>
    <book category="database">
        <title lang="en">MongoDB</title>
        <author>Kristina Chodorow</author>
        <year>2017</year>
        <price>63.0</price>
    </book>
    <book category="web" cover="paperback">
        <title lang="en">Learning XML</title>
        <author>Rick Coperland</author>
        <year>2015</year>
        <price>42.90</price>
    </book>
</bookcase>

对应的 DOM 树:
这里写图片描述

========== 使用DOM 读取 XML 文件 ==========

2. DOM 解析上面的 XML 文件 代码一

domxmlparse.h文件

#ifndef DOMXMLPARSE_H
#define DOMXMLPARSE_H

#include <QString>
#include <QDebug>
#include <QFile>
#include <QtXml/QDomDocument>
#include <QtXml/QDomElement>
#include <QTXML/QDomNode>


class DomXmlParse
{
public:
    DomXmlParse();
    ~DomXmlParse();

    void readDomXmlFile(const QString filePath);
};

#endif // DOMXMLPARSE_H

domxmlparse.cpp 文件

#include "domxmlparse.h"

DomXmlParse::DomXmlParse()
{
}

DomXmlParse::~DomXmlParse()
{
}


/**
 * @brief    DomXmlParse::readDomXmlFile
 * @param    filePath
 * @return   NONE
 */
void DomXmlParse::readDomXmlFile(const QString filePath)
{
     if(true == filePath.isEmpty() || 0 == filePath.length())
    {
        qDebug()<<"Error: filePath is empty .";
        return;
    }

    //以读方式打开XML文件
    QFile file(filePath);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<<"Error: open filePath failure.";
        return;
    }

    QString errorStr;
    int errorLine;
    int errorColumn;

    QDomDocument doc;

    //将XML文件加载到Dom 文档对象模型内存中
    if(!doc.setContent(&file,false,&errorStr,&errorLine,&errorColumn))
    {
        qDebug()<<"Error setContent, errorStr["<<errorStr<<"]"<<"errorLine["<<errorLine<<"]" \
                  <<"errorColumn["<<errorColumn<<"]";
        return;
    }

    //获取DOM树中的第一个节点元素
    QDomElement root = doc.documentElement();
    if("bookcase" != root.tagName())
    {
        qDebug()<<"Error: documentElement ";
        return;
    }
    else
    {
        QDomNode node = root.firstChild();
        while(!node.isNull())
        {
            if("book" == node.toElement().tagName())
            {
                QDomNode subNode = node.firstChild();
                while(!subNode.isNull())
                {
                    if("title" == subNode.toElement().tagName())
                    {
                        QString title = subNode.toElement().text();
                        qDebug()<<title;
                    }
                    if("author" == subNode.toElement().tagName())
                    {
                        QString author = subNode.toElement().text();
                        qDebug()<<author;
                    }
                    if("year" == subNode.toElement().tagName())
                    {
                        QString year = subNode.toElement().text();
                        qDebug()<<year;
                    }
                    if("price" == subNode.toElement().tagName())
                    {
                        QString price = subNode.toElement().text();
                        qDebug()<<price;
                    }

                    subNode = subNode.nextSibling();
                }
            }
            else
            {
                qDebug()<<"Error: not find subnode.";
            }
            node = node.nextSibling();
        }
    }

    return;
}




main.cpp 文件

#include "widget.h"
#include "domxmlparse.h"


#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    DomXmlParse parseXml;
    parseXml.readDomXmlFile("D:\\code\\untitled\\doc\\DomXml02.xml"); 
    return a.exec();
}

编译运行结果:

" GUI Qt"
"Jasmin Blanchette"
"2013"
"75.0"
"MongoDB"
"Kristina Chodorow"
"2017"
"63.0"
"Learning XML"
"Rick Coperland"
"2015"
"42.90"

3. DOM 解析如下XML文件 代码二

<?xml version="1.0" encoding="UTF-8"?>
<sports>
    <entry term = "basketball">
        <page>10</page>
        <page>34-35</page>
        <page>307-308</page>
    </entry>
    <entry term = "football">
        <entry term ="A football team">
            <page>115</page>
            <page>244</page>
        </entry>
        <entry term = "B football team">
            <page>9</page>
        </entry>
    </entry>
</sports>

说明:其他不改变,只需要修改 readDomXmlFile 函数即可

/**
 * @brief    DomXmlParse::readDomXmlFile
 * @param    filePath
 * @return   NONE
 */
void DomXmlParse::readDomXmlFile(const QString filePath)
{
    if(true == filePath.isEmpty() || 0 == filePath.length())
    {
        qDebug()<<"Error: filePath is empty .";
        return;
    }

    //以读方式打开XML文件
    QFile file(filePath);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<<"Error: open filePath failure.";
        return;
    }

    QString errorStr;
    int errorLine;
    int errorColumn;

    QDomDocument doc;

    //将XML文件加载到Dom 文档对象模型内存中
    if(!doc.setContent(&file,false,&errorStr,&errorLine,&errorColumn))
    {
        qDebug()<<"Error setContent, errorStr["<<errorStr<<"]"<<"errorLine["<<errorLine<<"]" \
                  <<"errorColumn["<<errorColumn<<"]";
        return;
    }

    //获取DOM树中的第一个节点元素
    QDomElement root = doc.documentElement();
    if("sports" != root.tagName())
    {
        qDebug()<<"Error: documentElement ";
        return;
    }
    else
    {
        QDomNode node = root.firstChild();
        while(!node.isNull())
        {
            if("entry" == node.toElement().tagName())
            {
                //打印节点元素的属性值
                QString attr = node.toElement().attribute("term");
                qDebug()<<attr;
                QDomNode child = node.toElement().firstChild();
                while(!child.isNull())
                {
                    if("page" == child.toElement().tagName())
                    {
                        QString page = child.toElement().text();
                        qDebug()<<page;
                    }
                    else if("entry" == child.toElement().tagName())
                    {
                        //打印节点元素的属性值
                        QString attru = child.toElement().attribute("term");
                        qDebug()<<attru;
                        QDomNode subChild = child.toElement().firstChild();
                        while(!subChild.isNull())
                        {
                            if("page" == subChild.toElement().tagName())
                            {
                                QString page = subChild.toElement().text();
                                qDebug()<<page;
                            }
                            else
                            {
                                qDebug()<<"Error: Dom file";
                            }
                            subChild = subChild.nextSibling();
                        }
                    }
                    child = child.nextSibling();
                }
            }
            node = node.nextSibling();
        }
    }

    return;
}

编译运行执行结果:

"basketball"
"10"
"34-35"
"307-308"
"football"
"A football team"
"115"
"244"
"B football team"
"9"

========= 使用DOM 生成(写) XML 文件 ========

4. 使 DOM 方式生成(写)代码一中的 XML 文件,该 XML 如下:

<?xml version="1.0" encoding="UTF-8"?>
<bookcase>
    <book category="computer">
        <title lang="en"> GUI Qt</title>
        <author>Jasmin Blanchette</author>
        <year>2013</year>
        <price>75.0</price>
    </book>
    <book category="database">
        <title lang="en">MongoDB</title>
        <author>Kristina Chodorow</author>
        <year>2017</year>
        <price>63.0</price>
    </book>
    <book category="web" cover="paperback">
        <title lang="en">Learning XML</title>
        <author>Rick Coperland</author>
        <year>2015</year>
        <price>42.90</price>
    </book>
</bookcase>

在 DomXmlParse 类中新增加一个成员函数,writeDomXmlFile ,具体代码为:

void DomXmlParse::writeDomXmlFile(const QString filePath)
{
    //打开或创建文件
    QFile file(filePath); //相对路径、绝对路径、资源路径都可以
    if(!file.open(QFile::WriteOnly|QFile::Truncate)) //可以用QIODevice,Truncate表示清空原来的内容
        return;

    QDomDocument doc;
    //写入xml头部
    QDomProcessingInstruction instruction; //添加处理命令

    //创建XML文档的版本号和编码
    instruction=doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(instruction);

    //添加根节点
    QDomElement root=doc.createElement("bookcase");
    doc.appendChild(root);

    //添加第一个子节点及其子元素; //方式一:创建属性  其中键值对的值可以是各种类型
    QDomElement book=doc.createElement("book");
    book.setAttribute("category","computer");

    /*//创建节点属性值:方式二:创建属性 值必须是字符串
    QDomAttr time=doc.createAttribute("category");
    time.setValue("computer");
    */

    QDomElement title=doc.createElement("title"); //创建子元素
    title.setAttribute("lang","en");

    QDomText text; //设置括号标签中间的值
    text=doc.createTextNode("GUI Qt");
    book.appendChild(title);
    title.appendChild(text);

    QDomElement author=doc.createElement("author"); //创建子元素
    text=doc.createTextNode("Jasmin Blanchette");
    author.appendChild(text);
    book.appendChild(author);

    QDomElement year=doc.createElement("year"); //创建子元素
    text=doc.createTextNode("2013");
    year.appendChild(text);
    book.appendChild(year);

    QDomElement price=doc.createElement("price"); //创建子元素
    text=doc.createTextNode("Jasmin Blanchette");
    price.appendChild(text);
    book.appendChild(price);

    root.appendChild(book);

    //添加第二个子节点及其子元素,部分变量只需重新赋值
    book=doc.createElement("book");
    book.setAttribute("category","database");

    title = doc.createElement("titile");
    title.setAttribute("lang","en");            //设置节点属性值
    text = doc.createTextNode("MongoDB");
    title.appendChild(text);
    book.appendChild(title);

    author=doc.createElement("author");
    text=doc.createTextNode("Kristina Chodorow");
    author.appendChild(text);
    book.appendChild(author);


    year=doc.createElement("year");
    text=doc.createTextNode("2017");
    year.appendChild(text);
    book.appendChild(year);

    price=doc.createElement("price");
    text=doc.createTextNode("63.0");
    price.appendChild(text);
    book.appendChild(price);

    root.appendChild(book);

    //添加第三个节点
    book=doc.createElement("book");
    book.setAttribute("category","web");

    //创建节点属性值:方式二:创建属性 值必须是字符串
    QDomAttr cover=doc.createAttribute("cover");
    cover.setValue("paperback");
    book.setAttributeNode(cover);

    title = doc.createElement("titile");
    title.setAttribute("lang","en");

    text = doc.createTextNode("Learning XML");
    title.appendChild(text);
    book.appendChild(title);

    author=doc.createElement("author");
    text=doc.createTextNode("Rick Coperland");
    author.appendChild(text);
    book.appendChild(author);


    year=doc.createElement("year");
    text=doc.createTextNode("2015");
    year.appendChild(text);
    book.appendChild(year);

    price=doc.createElement("price");
    text=doc.createTextNode("42.90");
    price.appendChild(text);
    book.appendChild(price);


    root.appendChild(book);

    //输出到文件
    QTextStream out_stream(&file);
    doc.save(out_stream,4); //缩进4格
    file.close();

    return;
}

main.cpp 文件中 main 函数调用方式如下:

#include "widget.h"
#include "domxmlparse.h"


#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    DomXmlParse parseXml;
    parseXml.writeDomXmlFile("D:\\code\\untitled\\doc\\DomXml03.xml");
    return a.exec();
}

编译并运行该代码后,会在该目录下生成一个名为 DomXml03.xml 的文件。
这里写图片描述

其 DomXml03.xml 文件的内容为:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lixiaogang_theanswer/article/details/80870318