Qt文件:XML文件

XML文件

  • [1. XML文件结构](#1. XML文件结构)
    • [1.1 基本结构](#1.1 基本结构)
    • [1.2 XML 格式规则](#1.2 XML 格式规则)
    • [1.3 XML vs HTML](#1.3 XML vs HTML)
  • [2. XML文件操作](#2. XML文件操作)
    • [2.1 DOM 方式(QDomDocument)](#2.1 DOM 方式(QDomDocument))
    • [2.2 SAX 方式(QXmlStreamReader/QXmlStreamWriter)](#2.2 SAX 方式(QXmlStreamReader/QXmlStreamWriter))
    • [2.3 对比分析](#2.3 对比分析)
  • [3. 使用场景](#3. 使用场景)
    • [3.1 存储配置信息](#3.1 存储配置信息)
    • [3.2 数据交换与存储](#3.2 数据交换与存储)
    • [3.3 界面布局与资源定义](#3.3 界面布局与资源定义)
    • [3.4 网络通信与 API 交互](#3.4 网络通信与 API 交互)
    • [3.5 插件与扩展系统](#3.5 插件与扩展系统)
    • [3.6 国际化(i18n)与翻译文件](#3.6 国际化(i18n)与翻译文件)

1. XML文件结构

XML(eXtensible Markup Language,可扩展标记语言)是一种用于存储和传输数据的标记语言,具有平台无关性、结构清晰、易于阅读和编写等特点。

1.1 基本结构

一个标准的 XML 文件通常包含以下部分:

  1. XML 声明(可选):指定 XML 版本、编码方式(如 UTF-8)等信息。
xml 复制代码
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
复制代码
version:必填,指定 XML 版本(常用1.0)。
encoding:可选,指定字符编码(默认UTF-8,需与文件实际编码一致)。
standalone:可选,指定是否为独立文件(yes表示不依赖外部 DTD / 模式,no表示依赖)。
  1. 文档类型定义(DTD,可选):定义 XML 文档的结构和元素规则(可引用外部 DTD 或内嵌)。
xml 复制代码
<!DOCTYPE root-element SYSTEM "filename.dtd">
复制代码
root-element:根元素名称。
SYSTEM:引用外部 DTD 文件。
xml 复制代码
<!DOCTYPE books [
    <!ELEMENT books (book+)>
    <!ELEMENT book (title, author)>
    <!ATTLIST book id CDATA #REQUIRED>
]>
  1. 根元素:XML 文档的顶级元素,所有内容必须包含在根元素内。
xml 复制代码
<root>
    <!-- 子元素 -->
</root>
xml 复制代码
<books>
    <book id="1">
        <title>Qt编程</title>
    </book>
</books>
  1. 元素(标签):由开始标签()、结束标签()和内容(可选)组成。
    规则:
    • 标签名区分大小写(如和是不同标签)。
    • 必须正确嵌套,不能交叉。
    • 空元素可使用自闭合标签(如<-img src="image.jpg" />)。
xml 复制代码
<book id="1">
    <title>XML入门</title>
    <author>John Doe</author>
</book>
  1. 属性:为元素提供额外信息(键值对形式)。
    规则:
    • 属性值必须用双引号(")或单引号(')包裹。
    • 同一元素中属性名唯一。
xml 复制代码
<book id="1" category="technology">
    <title>XML实战</title>
</book>
  1. 文本内容:元素内部的文本内容,可包含转义字符或 CDATA 节。

    CDATA 节:用于包含无需转义的原始文本(如代码片段),语法:
xml 复制代码
<description><![CDATA[内容不转义 <script>...</script>]]></description>

1.2 XML 格式规则

  1. 严格区分大小写:标签名、属性名、属性值均区分大小写(如和<title>是不同标签)。
  2. 正确闭合标签:每个开始标签必须有对应的结束标签,空元素需自闭合(如<''br />)。
  3. 唯一根元素:每个 XML 文档必须有且仅有一个根元素,所有其他元素都是根元素的子元素。
  4. 正确嵌套标签:标签必须逐层嵌套,不能交叉。例如:
xml 复制代码
<!-- 正确嵌套 -->
<parent>
    <child>内容</child>
</parent>

<!-- 错误(交叉嵌套) -->
<parent>
    <child>内容
</parent>
</child>
  1. 属性值必须加引号:属性值必须用单引号或双引号包裹,例如:
xml 复制代码
<book id='1' name="XML教程" />
  1. 禁止使用特殊字符:文本内容中不能直接使用<、>、&等特殊字符,需用转义代码或 CDATA 节处理。

1.3 XML vs HTML

特性 XML HTML
设计目标 存储和传输数据 展示数据和定义网页结构
标签定义 自定义标签(可扩展) 预定义标签(如 , )
语法严格性 严格(必须正确闭合、嵌套) 相对宽松(部分浏览器可容错)
用途 配置文件、数据交换、API 返回格式等 网页内容呈现
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student id="S001">
        <name>Alice</name>
        <age>20</age>
        <courses>
            <course name="Math" score="90" />
            <course name="Physics" score="85" />
        </courses>
    </student>
    <student id="S002">
        <name>Bob</name>
        <age>21</age>
        <courses>
            <course name="Programming" score="95" />
        </courses>
    </student>
</students>

2. XML文件操作

在 Qt 中处理 XML 文件主要有两种方式:DOM 方式(使用QDomDocument)和SAX 方式(使用QXmlStreamReader和QXmlStreamWriter)。

2.1 DOM 方式(QDomDocument)

特点:

  1. 将整个 XML 文档加载到内存中,形成树形结构。
  2. 支持随机访问和修改节点。
  3. 适合处理小型 XML 文件。

读取 XML

cpp 复制代码
#include <QFile>
#include <QDomDocument>
#include <QDebug>

void readXmlWithDom() {
    QFile file("example.xml");
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file!";
        return;
    }

    QDomDocument doc;
    if (!doc.setContent(&file)) {
        qDebug() << "Failed to parse XML!";
        file.close();
        return;
    }
    file.close();

    // 获取根节点
    QDomElement root = doc.documentElement();
    qDebug() << "Root tag:" << root.tagName();

    // 遍历子节点
    QDomNode node = root.firstChild();
    while (!node.isNull()) {
        if (node.isElement()) {
            QDomElement element = node.toElement();
            qDebug() << "Tag:" << element.tagName()
                     << "Text:" << element.text();
        }
        node = node.nextSibling();
    }
}

写入XML

cpp 复制代码
void writeXmlWithDom() {
    QDomDocument doc;
    
    // 添加XML声明
    QDomProcessingInstruction instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
    doc.appendChild(instruction);
    
    // 创建根节点
    QDomElement root = doc.createElement("books");
    doc.appendChild(root);
    
    // 添加子节点
    QDomElement book1 = doc.createElement("book");
    book1.setAttribute("id", "1");
    
    QDomElement title1 = doc.createElement("title");
    title1.appendChild(doc.createTextNode("Qt Programming"));
    book1.appendChild(title1);
    
    root.appendChild(book1);
    
    // 保存到文件
    QFile file("output.xml");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream stream(&file);
        stream << doc.toString();
        file.close();
    }
}

2.2 SAX 方式(QXmlStreamReader/QXmlStreamWriter)

特点

  1. 流式解析,逐行读取 XML,不加载整个文档。
  2. 内存占用小,适合处理大型 XML 文件。
  3. 只支持顺序访问,不支持随机修改。

读取XML

cpp 复制代码
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>

void readXmlWithStream() {
    QFile file("example.xml");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file!";
        return;
    }

    QXmlStreamReader xml(&file);
    while (!xml.atEnd() && !xml.hasError()) {
        QXmlStreamReader::TokenType token = xml.readNext();
        
        if (token == QXmlStreamReader::StartElement) {
            if (xml.name() == "book") {
                QString id = xml.attributes().value("id").toString();
                qDebug() << "Book ID:" << id;
            } else if (xml.name() == "title") {
                qDebug() << "Title:" << xml.readElementText();
            }
        }
    }

    if (xml.hasError()) {
        qDebug() << "XML error:" << xml.errorString();
    }
    file.close();
}

写入XML

cpp 复制代码
void writeXmlWithStream() {
    QFile file("output.xml");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file!";
        return;
    }

    QXmlStreamWriter xml(&file);
    xml.setAutoFormatting(true);  // 自动格式化XML
    xml.writeStartDocument();
    
    xml.writeStartElement("books");
    
    xml.writeStartElement("book");
    xml.writeAttribute("id", "1");
    xml.writeTextElement("title", "Qt Programming");
    xml.writeEndElement();  // </book>
    
    xml.writeEndElement();  // </books>
    xml.writeEndDocument();
    
    file.close();
}

2.3 对比分析

场景 推荐类 优点
小型 XML 文件,需随机修改 QDomDocument 操作简单,支持 DOM 树遍历
大型 XML 文件,仅需读取 QXmlStreamReader 内存占用低,解析速度快
生成 XML 文件 QXmlStreamWriter 代码简洁,性能高
需要 XPath 查询 QXmlQuery 支持 XPath 表达式
Qt Quick 应用 XmlListModel 直接集成到 QML 中
  1. 命名空间处理:
    DOM 方式:使用QDomNode::namespaceURI()获取命名空间。
    流方式:使用QXmlStreamReader::namespaceUri()。
  2. 错误处理:
    DOM 方式:检查QDomDocument::setContent()的返回值。
    流方式:检查QXmlStreamReader::hasError()。
  3. 性能考虑:
    处理大型文件时,优先选择 SAX 方式,避免内存溢出。

3. 使用场景

在 Qt 应用开发中,XML 文件常用于存储配置信息、交换数据、定义界面结构等场景。Qt 提供了多种处理 XML 的类和工具,使 XML 文件成为应用程序与外部数据交互的重要载体。

3.1 存储配置信息

XML 文件可用于保存应用程序的配置参数,如窗口尺寸、用户偏好等。通过读取和写入 XML 配置文件,实现应用状态的持久化。

xml 复制代码
<!-- config.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <window>
        <width>800</width>
        <height>600</height>
        <maximized>true</maximized>
    </window>
    <appearance>
        <theme>dark</theme>
        <font>Roboto</font>
        <fontSize>12</fontSize>
    </appearance>
</config>
  • 读取文件:
cpp 复制代码
#include <QFile>
#include <QXmlStreamReader>

void loadConfig() {
    QFile file("config.xml");
    if (file.open(QIODevice::ReadOnly)) {
        QXmlStreamReader xml(&file);
        
        while (!xml.atEnd()) {
            if (xml.readNextStartElement()) {
                if (xml.name() == "window") {
                    // 读取窗口配置
                    xml.readNextStartElement(); // <width>
                    int width = xml.readElementText().toInt();
                    xml.readNextStartElement(); // <height>
                    int height = xml.readElementText().toInt();
                    // 设置窗口大小...
                } else if (xml.name() == "appearance") {
                    // 读取外观配置
                    // ...
                }
            }
        }
        
        file.close();
    }
}

3.2 数据交换与存储

XML 是一种通用的数据交换格式,可用于在 Qt 应用与其他系统(如 Web 服务、数据库)之间传输数据。

xml 复制代码
<!-- books.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="1">
        <title>Qt编程实战</title>
        <author>John Doe</author>
        <price currency="CNY">89.00</price>
    </book>
    <book id="2">
        <title>C++ Primer</title>
        <author>Stanley Lippman</author>
        <price currency="USD">45.99</price>
    </book>
</books>

解析数据:

cpp 复制代码
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>

struct Book {
    int id;
    QString title;
    QString author;
    double price;
    QString currency;
};

QList<Book> parseBooks() {
    QList<Book> bookList;
    QFile file("books.xml");
    
    if (file.open(QIODevice::ReadOnly)) {
        QXmlStreamReader xml(&file);
        Book currentBook;
        
        while (!xml.atEnd()) {
            if (xml.readNextStartElement()) {
                if (xml.name() == "book") {
                    currentBook.id = xml.attributes().value("id").toInt();
                } else if (xml.name() == "title") {
                    currentBook.title = xml.readElementText();
                } else if (xml.name() == "author") {
                    currentBook.author = xml.readElementText();
                } else if (xml.name() == "price") {
                    currentBook.price = xml.readElementText().toDouble();
                    currentBook.currency = xml.attributes().value("currency").toString();
                }
            } else if (xml.tokenType() == QXmlStreamReader::EndElement && 
                       xml.name() == "book") {
                bookList.append(currentBook);
            }
        }
        
        file.close();
    }
    
    return bookList;
}

3.3 界面布局与资源定义

XML 可用于定义 Qt 应用的界面结构(如 Qt Designer 生成的.ui文件)或资源文件(如.qrc)。

UI文件片段:

xml 复制代码
<!-- mainwindow.ui (简化版) -->
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
    <class>MainWindow</class>
    <widget class="QMainWindow" name="MainWindow">
        <property name="geometry">
            <rect>
                <x>0</x>
                <y>0</y>
                <width>800</width>
                <height>600</height>
            </rect>
        </property>
        <widget class="QWidget" name="centralWidget">
            <layout class="QVBoxLayout" name="verticalLayout">
                <widget class="QLabel" name="label">
                    <property name="text">
                        <string>Hello Qt!</string>
                    </property>
                </widget>
                <widget class="QPushButton" name="pushButton">
                    <property name="text">
                        <string>Click Me</string>
                    </property>
                </widget>
            </layout>
        </widget>
    </widget>
</ui>

3.4 网络通信与 API 交互

Qt 应用可通过 XML 格式与 Web 服务通信(如 SOAP 协议),或解析远程 API 返回的 XML 数据。

cpp 复制代码
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QXmlStreamReader>

void fetchRemoteXml() {
    QNetworkAccessManager manager;
    QNetworkRequest request(QUrl("https://api.example.com/data.xml"));
    
    QNetworkReply *reply = manager.get(request);
    QEventLoop loop;
    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    loop.exec();
    
    if (reply->error() == QNetworkReply::NoError) {
        QXmlStreamReader xml(reply->readAll());
        // 解析XML数据...
    }
    
    reply->deleteLater();
}

3.5 插件与扩展系统

XML 可用于描述插件信息或应用扩展点,使应用支持动态加载插件。

xml 复制代码
<!-- plugin.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <id>com.example.texteditor</id>
    <name>Text Editor Plugin</name>
    <version>1.0.0</version>
    <author>Example Inc.</author>
    <class>TextEditorPlugin</class>
    <dependencies>
        <dependency>core</dependency>
    </dependencies>
</plugin>

3.6 国际化(i18n)与翻译文件

Qt 的翻译文件(.ts)基于 XML 格式,用于存储不同语言的翻译文本。

xml 复制代码
<!-- translations.ts -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
    <context>
        <name>MainWindow</name>
        <message>
            <source>File</source>
            <translation>文件</translation>
        </message>
        <message>
            <source>Edit</source>
            <translation>编辑</translation>
        </message>
    </context>
</TS>
相关推荐
Knight_AL1 小时前
Spring 事务传播行为 + 事务失效原因 + 传播行为为什么不用其他模式
数据库·sql·spring
倔强的石头_1 小时前
时序数据时代的“存储与分析困局”解析及金仓解决方案
数据库
计算机毕设VX:Fegn08951 小时前
计算机毕业设计|基于springboot + vue小型房屋租赁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
倔强的石头_2 小时前
场景化落地指南——金仓时序数据库在关键行业的应用实践
数据库
SelectDB2 小时前
驾驭 CPU 与编译器:Apache Doris 实现极致性能的底层逻辑
运维·数据库·apache
zbguolei3 小时前
MySQL根据身份证号码计算出生日期和年龄
数据库·mysql
hqwest3 小时前
码上通QT实战12--监控页面04-绘制6个灯珠及开关
开发语言·qt·qpainter·qt事件·stackedwidget
马克学长3 小时前
SSM校园图书借阅服务系统jd2z8(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·图书管理系统·ssm 框架·ssm 校园图书借阅系统
软件派3 小时前
高斯数据库使用心得——从性能优化到行业实践的深度解析
数据库·oracle
Chan165 小时前
场景题:CPU 100% 问题怎么排查?
java·数据库·redis·后端·spring