Qt6.5示例:QDomDocument类解析XML文档和文件

01 QDomDocument介绍

QDomDocument类是用于处理XML文档的一个类。QDomDocument提供了对XML文档数据访问的一系列功能,主要功能包括如下:

解析XML文档:QDomDocument可以将XML文档解析为树形结构,每个节点都是一个QDomNode对象,可以通过QDomNode对象的方法来访问和修改节点属性和内容。

创建XML元素和文本节点:QDomDocument类提供了创建新元素(createElement)和创建新文本节点(createTextNode)的工厂方法。

生成XML文档:QDomDocument类提供了生成XML文档的方法,如toByteArray()和toString(),可以将生成的XML文档转换为字节数组或字符串。

查询和修改XML文档:QDomDocument类提供了一些常用的操作,如获取或设置元素的属性、获取或修改元素的内容等。

02 如何使用QDomDocument

头文件:#include <QDomDocument>

cmake:find_package(Qt6 REQUIRED COMPONENTS Xml)

target_link_libraries(mytarget PRIVATE Qt6::Xml)

qmake:QT += xml

继承于:QDomNode

03 XML文档介绍

XML全称是可扩展标记语言(Extensible Markup Language),XML是标准通用标记语言(SGML)的一个子集。XML主要用于标记电子文件,使其具有结构性。它可以用来标记数据、定义数据类型,是一种允许用户定义自己的标记语言的源语言。

XML文本格式一般包含以下几部分:

声明部分:XML文件的声明部分包括XML版本号和字符集声明,格式例子:。

根元素:一般情况下XML文件中的所有元素都包含在一个根元素中。根元素是XML文件的起点。

元素:XML文件中的元素包含一个开始标记、一个结束标记和中间的数据。元素的格式:data。其中element为元素的名称,data为元素的数据。

属性:XML文件中的元素可以包含属性,属性用于描述元素的特性。属性的格式:data。其中attribute为元素的某个属性名称,对应value是属性的值,元素可以包含多个属性值。

  • XML文档示例:

以下XML文档例子,bookstore是根元素,它包含三个book子元素。每个book元素有一个type属性,同时都有一些子元素,如title、author、genre、price和description,这些子元素分别表示书的标题、作者、类型、价格和描述。

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book type="100">
        <title>标杆人生</title>
        <author>华理克</author>
        <genre>哲理类</genre>
        <price>25.99</price>
        <description>第一本书。</description>
    </book>
    <book type="200">
        <title>原则</title>
        <author>瑞利欧</author>
        <genre>管理类</genre>
        <price>35.99</price>
        <description>第二本书。</description>
    </book>
    <book type="300">
        <title>系统之美</title>
        <author>德内拉梅多斯</author>
        <genre>管理学</genre>
        <price>45.99</price>
        <description>第三本书。</description>
    </book>
        
</bookstore>

04 QDomDocument解析XML文档方法

  • setContent方法:

QDomDocument支持通过文件(QIODevice)、原始数据(QByteArray)和字符串(QString)等方式解析XML。

// 访问函数。
bool setContent(QIODevice* dev, QString *errorMsg=nullptr, int *errorLine=nullptr, int *errorColumn=nullptr );
bool setContent(const QByteArray& text, QString *errorMsg=nullptr, int *errorLine=nullptr, int *errorColumn=nullptr );
bool setContent(const QString& text, QString *errorMsg=nullptr, int *errorLine=nullptr, int *errorColumn=nullptr );
bool setContent(QXmlInputSource *source, QString *errorMsg=nullptr, int *errorLine=nullptr, int *errorColumn=nullptr );
  • 打开XML文件示例:

文档类QDomDocument继承于QDomNode类。

/**** 例子: ****/

#include <QDomDocument>
#include <QFile>

// 打开XML文件。
QFile file("bookstore.xml");
file.open(QIODevice::ReadOnly);

// 创建 QDomDocument 对象。
QDomDocument doc;
doc.setContent(&file);
  • 获取根节点元素示例:

根节点QDomElement继承于QDomNode类。

/**** 例子: ****/

// 获取根节点元素。
QDomElement root_element = doc.documentElement();
  • 遍历子节点示例一:

/**** 例子: ****/

// 获取第一个子节点。
QDomNode node = root_element.firstChild();
while (!node.isNull())
{
    if (node.isElement())
    {
        // 解析元素节点。
        QDomElement element = node.toElement();
        QString name = element.tagName();
        QString text = element.text();
        // 元素属性。
        QDomNamedNodeMap arrtibutes = element.attributes();
    }
    else if (node.isText())
    {
        // 解析文本节点。
        QDomText text = node.toText();
        QString textValue = text.data();
    }
    else if (node.isAttr())
    {
        // 解析属性节点。   
        QDomAttr attr = node.toAttr();
        QString attrName = attr.name();
        QString attrValue = attr.value();
    }
    // else if (...) {}
    
    // 移动到下一个节点继续处理。
    node = node.nextSibling();
}
  • QDomNode::NodeType节点类型:

QDomNode::NodeType用于表示DOM(文档对象模型)节点类型。

QDomNode::NodeType宏定义如下:

QDomNode::ElementNode 1 元素节点。

QDomNode::AttributeNode 2 属性节点。

QDomNode::TextNode 3 文本节点。

QDomNode::CDATASectionNode 4 字符数据节点。

QDomNode::EntityReferenceNode 5 实体引用节点。

QDomNode::EntityNode 6 实体节点。

QDomNode::ProcessingInstructionNode 7 处理指令节点。

QDomNode::CommentNode 8 注释节点。

QDomNode::DocumentNode 9 文档节点。

QDomNode::DocumentTypeNode 10 文档类型节点。

QDomNode::DocumentFragmentNode 11 文档片段节点。

QDomNode::NotationNode 12 符号节点。

  • 遍历子节点示例二:

/**** 例子: ****/

// 获取子节点列表。
QDomNodeList child_nodes = root_element.childNodes();
// 遍历子元素。
for (int i=0; i<child_nodes.size(); ++i)
{
    QDomNode node = child_nodes.at(i);
    if (node.isElement())
    {
        // 解析元素。
        QDomElement element = node.toElement();
        QString name = element.tagName();
        QString text = element.text();
        // 元素属性。
        QDomNamedNodeMap arrtibutes = element.attributes();
    }
    // else if (...) {}    
}
  • 通过标签名称(节点名称)查询节点示例:

/**** 例子: ****/

// 通过标签名称,查找所有子节点。
QDomNodeList node_list = root_element.elementsByTagName("book");
// 遍历所有子节点。
for (int i=0; i<node_list.count(); ++i)
{
    QDomElement element = node_list.at(i).toElement();
    // 通过节点名称,再获取它的子节点。
    QDomElement title_element = element.namedItem("title").toElement();
    QDomElement author_element = element.namedItem("author").toElement();
    QString qstr_title = title_element.text();
    QString qstr_author = author_element.text();
    qDebug() << "book child: title = " << qstr_title << ", author = " << qstr_author;
}
  • 遍历元素属性列表示例:

/**** 例子: ****/

// 元素属性。
QDomNamedNodeMap arrtibutes = element.attributes();
// 遍历属性。
for (int i=0; i<arrtibutes.count(); ++i)
{
    // 属性节点。
    QDomAttr dom_attr = arrtibutes.item(i).toAttr();
    // 属性名称。
    QString arrtibute_name = dom_attr.name();
    // 属性值。
    QString arrtibute_value =dom_attr.value();
    qDebug() << "arrtibute: " << arrtibute_name << " = " << arrtibute_value;
}

05 QDomDocument解析XML文件完整示例

首先创建一个QFile对象,打开"bookstore.xml"文件。然后,我们创建一个QDomDocument对象,并将文件设备传递给它。接下来,我们获取根元素节点,然后遍历根元素所有子节点,并且根据子节点不同类型,做相应转换处理,并在屏幕上打印节点的名称,节点文本和节点属性值等功能。

  • 示例代码:

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

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    // 打开XML文件。
    QFile file("bookstore.xml");
    if (!file.open(QIODevice::ReadOnly))
    {
        return -1;    
    }
    
    // 创建QDomDocument对象。
    QDomDocument doc;
    if (!doc.setContent(&file)) // 指定解析QFile内容。
    {
        file.close();
        return -1;    
    }
    file.close();
    
    // 获取根节点。
    QDomElement root_element = doc.documentElement();
    
    // 遍历子节点并处理。
    QDomNode node = root_element.firstChild();
    while (!node.isNull())
    {
        if (node.isElement())
        {
            // 元素节点。
            QDomElement element = node.toElement();
            QString name = element.tagName();
            QString value = element.text();
            qDebug() << "isElement:" << node.nodeName() << ", " << name << " : " << value;

            // 元素属性和内容。            
            QDomNamedNodeMap arrtibutes = element.attributes();
            // 遍历元素属性。
            for (int i=0; i<arrtibutes.count(); ++i)
            {
                QDomNode arrtibute_node = arrtibutes.item(i);
                // 属性名称。
                QString arrtibute_name = arrtibute_node.nodeName();
                // 属性值。
                QString arrtibute_value = arrtibute_node.nodeValue();
                qDebug() << "arrtibute: " << arrtibute_name << " = " << arrtibute_value;
            }
            
            // 如果有子节点,可以继续处理。
            // ...
                    
        }
        else if (node.isText())
        {
            // 文本节点。
            QDomText dom_text = node.toText();
            // 文本内容。
            QString text = dom_text.data();
            qDebug() << "isText:" << node.nodeName() << " : " << text;
            
        }
        else if (node.isAttr())
        {
            // 属性节点。
            QDomAttr dom_attr = node.toAttr();
            // 属性名称。
            QString name = dom_attr.name();
            // 属性值。
            QString value = dom_attr.value();
            qDebug() << "isAttr:" << node.nodeName() << ", " << name << " = " << value;

        }
        // else if (...) {}
        // 更多节点类型处理逻辑。

        // 移动到下一个节点继续处理
        node = node.nextSibling();
    }
    
    return 0;
}

06 附录:完整源码

关注公众号下载本示例完整工程源码(01_QDomDocument_ReadXml.zip)。

-【End】-

#想了解更多精彩内容,关注下方公众号,还有示例源码、开发工具免费下载。

喜欢本文章,记得点赞、分享、关注哦~

  • 21
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

20YC编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值