Qt文件:XML文件

1. XML文件结构

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

1.1 基本结构

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

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

1.2 XML 格式规则

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

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

1.3 XML vs HTML

特性XMLHTML
设计目标存储和传输数据展示数据和定义网页结构
标签定义自定义标签(可扩展)预定义标签(如
,

语法严格性严格(必须正确闭合、嵌套)相对宽松(部分浏览器可容错)
用途配置文件、数据交换、API 返回格式等网页内容呈现
<?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

#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

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

#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

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 配置文件,实现应用状态的持久化。

<!-- 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>
  • 读取文件:
#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 服务、数据库)之间传输数据。

<!-- 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>

解析数据:

#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文件片段:

<!-- 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 数据。

#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 可用于描述插件信息或应用扩展点,使应用支持动态加载插件。

<!-- 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 格式,用于存储不同语言的翻译文本。

<!-- 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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值