【Qt】DOM读取XML文档

00. 目录

01. 概述

DOM(Document Object Model,文档对象模型),是W3C的推荐标准。它提供了一个接口来访问和改变一个XML文件的内容和结构,可以将XML文档表示为一个存储在内存中具有层次的树视图。文档本身由QDomDocument对象来表示,而文档树中所有的DOM节点都是QDomNode类的子类。

在Qt中使用QDomProcessingInstruction类来表示XML说明。元素对应QDomElement类。属性对应QDomAttr类。文本内容由QDomText类表示。所有的DOM节点,比如这里的说明、元素、属性和文本等,都使用QDomNode来表示。

元素对应QDomElement 类。元素可以包含属性,用来描述元素的相关信息,属性名和属性值在元素的起始标签中给出。

属性值必须在单引号或者双引号中。属性对应QDomAttr 类。

元素中可以包含子元素,也可以只包含文本内容,比如这里<first-name> Mary </first-name>中的Mary就是文本内容,文本内容由QDomText 类表示。
在这里插入图片描述

XML(ExtensibleMarkup Language,可扩展标记语言),是一种类似于HTML的标记语言,但它的设计目的是用来传输数据,而不是显示数据。XML的标签没有被预定义,用户需要在使用时自行进行定义。XML是W3C(万维网联盟)的推荐标准。相对于数据库表格的二维表示,XML使用的树形结构更能表现出数据的包含关系,作为一种文本文件格式,XML简单明了的特性使得它在信息存储和描述领域非常流行。

​ 在Qt中提供了Qt XML模块来进行XML文档的处理,这里主要提供了两种解析方法: DOM方法,可以进行读写;SAX方法,可以进行读取。从Qt 5开始,Qt XML模块不再进行维护,而是推荐使用Qt Core模块中基于流的方法,分别使用QXmlStreamReader和QXmlStreamWriter进行读取和写入。本文档先来讲解一下DOM的方法。要在项目中使用Qt XML模块,需要在项目文件(.pro文件)中添加QT += xml一行代码。

02. 开发环境

Windows系统:Windows10

Qt版本:Qt5.15、Qt6

03. XML文档示例

规范的XML文档如下所示:

<?xml version="1.0"encoding="UTF-8"?>
<library>
   <book id="01">
       <title>Qt</title>
       <author>LiMing</author>
   </book>
   <book id="02">
       <title>Linux</title>
       <author>ZhengGang</author>
   </book>
</library>

每个XML文档都由XML说明(或者称为XML序言)开始,它是对XML文档处理的环境和要求的说明,比如这里的,其中xml version=“1.0”,表明使用的XML版本号,这里字母是区分大小写的;encoding=“UTF-8”是使用的编码,指出文档是使用何种字符集建立的,默认值为Unicode编码。XML文档内容由多个元素组成,一个元素由起始标签<标签名>和终止标签以及两个标签之间的内容组成,而文档中第一个元素被称为根元素,比如这里的,XML文档必须有且只有一个根元素。元素的名称是区分大小写的,元素还可以嵌套,比如这里的library、book、title和author等都是元素。元素可以包含属性,用来描述元素的相关信息,属性名和属性值在元素的起始标签中给出,格式为<元素名 属性名=“属性值”>,如,属性值必须在单引号或者双引号中。在元素中可以包含子元素,也可以只包含文本内容,比如这里的中的Qt就是文本内容。

04. DOM读取XML文档内容

Dom(Document Object Model,即文档对象模型)把XML文档转换成应用程序可以遍历的树形结构,这样便可以随机访问其中的节点。它的缺点是需要将整个XML文档读入内存,消耗内存较多。

在Qt中使用QDomProcessingInstruction类来表示XML说明,元素对应QDomElement类,属性对应QDomAttr类,文本内容由QDomText类表示。所有的DOM节点,比如这里的说明、元素、属性和文本等,都使用QDomNode来表示,然后使用对应的isProcessingInstruction()、isElement()、isAttr()和isText()等函数来判断是否是该类型的元素,如果是,那么就可以使用toProcessingInstruction()、toElement()、toAttr()和toText()等函数转换为具体的节点类型。

4.1 新建Qt控制台应用QtConsole Application,项目名称为16XML。

4.2 在16XML.pro配置文件中添加下一行

QT += xml

4.3 main.cpp内容如下


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //新建QDomDocument类对象 代表一个XML文档
    QDomDocument doc;

    //创建test.xml文件
    QFile file("../test.xml");

    //以只读方式打开该文件
    bool ret = file.open(QIODevice::ReadOnly);
    if (!ret)
    {
        qDebug() << "打开文件失败";
        file.close();
        return 1;
    }

    //将文件内容读到doc中
    ret = doc.setContent(&file);
    if (!ret)
    {
        qDebug() << "设置内容失败";
        file.close();
        return 1;
    }

    file.close();

    //获取doc第一个节点 即XML说明
    QDomNode firstNode = doc.firstChild();

    //输出XML说明
    qDebug() << firstNode.nodeName() << firstNode.nodeValue();


    return 0;
    //return a.exec();
}

执行结果

“xml” “version=‘1.0’ encoding=‘UTF-8’”

不愿意看到字符串两边的引号,可以将源码中得qDebug()语句更改如下:

    //输出XML说明
    //qDebug() << firstNode.nodeName() << firstNode.nodeValue();
    qDebug() << qPrintable(firstNode.nodeName())
             << qPrintable(firstNode.nodeValue());

执行结果

xml version='1.0' encoding='UTF-8'

4.4 继续修改main.cpp文件内容如下:

#include <QCoreApplication>
#include <QDebug>
#include <QDomDocument>
#include <QDomNode>
#include <QtXml>
#include <QFile>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //新建QDomDocument类对象 代表一个XML文档
    QDomDocument doc;

    //创建test.xml文件
    QFile file("../test.xml");

    //以只读方式打开该文件
    bool ret = file.open(QIODevice::ReadOnly);
    if (!ret)
    {
        qDebug() << "打开文件失败";
        file.close();
        return 1;
    }

    //将文件内容读到doc中
    ret = doc.setContent(&file);
    if (!ret)
    {
        qDebug() << "设置内容失败";
        file.close();
        return 1;
    }

    file.close();

    //获取doc第一个节点 即XML说明
    QDomNode firstNode = doc.firstChild();

    //输出XML说明
    //qDebug() << firstNode.nodeName() << firstNode.nodeValue();
    qDebug() << qPrintable(firstNode.nodeName())
             << qPrintable(firstNode.nodeValue());


    //返回根元素
    QDomElement docElem = doc.documentElement();
    //返回根节点的第一个子节点
    QDomNode root = docElem.firstChild();
    while(!root.isNull())
    {
        //如果节点是元素
        if (root.isElement())
        {
            //将其转换为元素
            QDomElement e = root.toElement();
            //返回元素的标记 和id属性的值
            qDebug() << qPrintable(e.tagName())
                     << qPrintable(e.attribute("id"));
        }

        //下一个兄弟节点
        root = root.nextSibling();
    }

    return 0;
    //return a.exec();
}

执行结果如下:

xml version='1.0' encoding='UTF-8'
book 01
book 02

4.5 继续修改main.cpp文件,得到所有节点

#include <QCoreApplication>
#include <QDebug>
#include <QDomDocument>
#include <QDomNode>
#include <QtXml>
#include <QFile>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //新建QDomDocument类对象 代表一个XML文档
    QDomDocument doc;

    //创建test.xml文件
    QFile file("../test.xml");

    //以只读方式打开该文件
    bool ret = file.open(QIODevice::ReadOnly);
    if (!ret)
    {
        qDebug() << "打开文件失败";
        file.close();
        return 1;
    }

    //将文件内容读到doc中
    ret = doc.setContent(&file);
    if (!ret)
    {
        qDebug() << "设置内容失败";
        file.close();
        return 1;
    }

    file.close();

    //获取doc第一个节点 即XML说明
    QDomNode firstNode = doc.firstChild();

    //输出XML说明
    //qDebug() << firstNode.nodeName() << firstNode.nodeValue();
    qDebug() << qPrintable(firstNode.nodeName())
             << qPrintable(firstNode.nodeValue());


    //返回根元素
    QDomElement docElem = doc.documentElement();
    //返回根节点的第一个子节点
    QDomNode root = docElem.firstChild();
    while(!root.isNull())
    {
        //如果节点是元素
        if (root.isElement())
        {
            //将其转换为元素
            QDomElement e = root.toElement();
            //返回元素的标记 和id属性的值
            qDebug() << qPrintable(e.tagName())
                     << qPrintable(e.attribute("id"));

            //获取元素e的所有子节点的列表
            QDomNodeList list = e.childNodes();
            //遍历该列表
            for (int i = 0; i < list.size(); i++)
            {
                QDomNode node = list.at(i);
                if (node.isElement())
                {
                    qDebug() << " " << qPrintable(node.toElement().tagName())
                             << qPrintable(node.toElement().text());
                }
            }


        }

        //下一个兄弟节点
        root = root.nextSibling();
    }

    return 0;
    //return a.exec();
}

使用了childNodes()函数获得了元素所有子节点的列表,然后通过遍历这个列表实现了遍历其所有子元素。 执行结果

xml version='1.0' encoding='UTF-8'
book 01
  title Qt
  author LiMing
book 02
  title Linux
  author ZhengGang

05. 预留

06. 附录

6.1 Qt教程汇总
网址:https://dengjin.blog.csdn.net/article/details/115174639

6.2 源码下载
网址:【Qt】DOM读取XML文档.rar

© 版权声明
THE END
喜欢就支持一下吧
点赞696 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容