当前位置: 首页 > news >正文

Qt XML 与 JSON 数据处理方法

Qt 提供了强大且易用的 XML 和 JSON 数据处理模块,使开发者能够轻松解析、生成和操作结构化数据。本文将从基础到高级全面解析 Qt 中处理 XML 和 JSON 的方法,包括核心类、使用示例和最佳实践。

一、XML 数据处理

1. Qt XML 模块核心类
类名作用
QXmlStreamReader基于流的 XML 读取器,逐行解析 XML,适合处理大型文件(内存效率高)
QXmlStreamWriter基于流的 XML 写入器,用于生成 XML 文档
QDomDocument基于 DOM(文档对象模型)的 XML 解析器,将整个文档加载到内存中,支持随机访问和修改
QDomElement表示 XML 文档中的元素节点
QDomNode表示 XML 文档中的通用节点(可表示元素、文本、注释等)
2. XML 解析示例:QXmlStreamReader
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>void parseXML(const QString &fileName) {QFile file(fileName);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "无法打开文件:" << fileName;return;}QXmlStreamReader xml(&file);// 遍历 XML 文档while (!xml.atEnd() && !xml.hasError()) {QXmlStreamReader::TokenType token = xml.readNext();// 处理开始元素if (token == QXmlStreamReader::StartElement) {if (xml.name() == "book") {// 获取元素属性QXmlStreamAttributes attributes = xml.attributes();if (attributes.hasAttribute("id")) {QString id = attributes.value("id").toString();qDebug() << "Book ID:" << id;}} else if (xml.name() == "title") {// 获取元素文本QString title = xml.readElementText();qDebug() << "Title:" << title;} else if (xml.name() == "author") {QString author = xml.readElementText();qDebug() << "Author:" << author;}}}if (xml.hasError()) {qDebug() << "XML 解析错误:" << xml.errorString();}file.close();
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);parseXML("books.xml");return a.exec();
}
3. XML 生成示例:QXmlStreamWriter
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamWriter>void createXML(const QString &fileName) {QFile file(fileName);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {return;}QXmlStreamWriter xml(&file);xml.setAutoFormatting(true);  // 自动格式化(缩进)// 写入 XML 声明xml.writeStartDocument();// 写入根元素xml.writeStartElement("library");// 写入第一个书籍元素xml.writeStartElement("book");xml.writeAttribute("id", "1");xml.writeTextElement("title", "C++ Primer");xml.writeTextElement("author", "Stanley Lippman");xml.writeEndElement();  // 结束 book 元素// 写入第二个书籍元素xml.writeStartElement("book");xml.writeAttribute("id", "2");xml.writeTextElement("title", "Qt 5 C++ GUI Programming Cookbook");xml.writeTextElement("author", "Mark Summerfield");xml.writeEndElement();  // 结束 book 元素// 结束根元素xml.writeEndElement();  // 结束 library 元素// 写入 XML 文档结束xml.writeEndDocument();file.close();
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);createXML("library.xml");return a.exec();
}
4. DOM 方式处理 XML(QDomDocument)
#include <QCoreApplication>
#include <QFile>
#include <QDomDocument>
#include <QDomElement>
#include <QDebug>void modifyXML(const QString &fileName) {QFile file(fileName);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {return;}QDomDocument doc;QString errorMsg;int errorLine, errorColumn;// 加载 XML 文档if (!doc.setContent(&file, &errorMsg, &errorLine, &errorColumn)) {qDebug() << "XML 加载错误:" << errorMsg << "Line:" << errorLine << "Column:" << errorColumn;file.close();return;}file.close();// 获取根元素QDomElement root = doc.documentElement();// 遍历所有书籍元素QDomNodeList bookList = root.elementsByTagName("book");for (int i = 0; i < bookList.size(); ++i) {QDomElement book = bookList.at(i).toElement();if (!book.isNull()) {// 修改书籍元素的属性if (book.attribute("id") == "1") {book.setAttribute("category", "Programming");}// 添加新元素QDomElement publisher = doc.createElement("publisher");QDomText publisherText = doc.createTextNode("Addison-Wesley");publisher.appendChild(publisherText);book.appendChild(publisher);}}// 保存修改后的 XMLif (file.open(QIODevice::WriteOnly | QIODevice::Text)) {QTextStream stream(&file);doc.save(stream, 4);  // 缩进为4个空格file.close();}
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);modifyXML("library.xml");return a.exec();
}

二、JSON 数据处理

1. Qt JSON 模块核心类
类名作用
QJsonDocument表示完整的 JSON 文档,可从 JSON 文本解析或生成 JSON 文本
QJsonObject表示 JSON 对象(键值对集合),类似 std::map<QString, QJsonValue>
QJsonArray表示 JSON 数组(值的有序列表)
QJsonValue表示 JSON 值(可以是 null、bool、number、string、object 或 array)
QJsonParseError用于存储 JSON 解析过程中的错误信息
2. JSON 解析示例
#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>void parseJSON(const QString &fileName) {QFile file(fileName);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qDebug() << "无法打开文件:" << fileName;return;}// 读取 JSON 数据QByteArray jsonData = file.readAll();file.close();// 解析 JSONQJsonParseError parseError;QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parseError);if (parseError.error != QJsonParseError::NoError) {qDebug() << "JSON 解析错误:" << parseError.errorString();return;}// 检查是否为 JSON 对象if (jsonDoc.isObject()) {QJsonObject jsonObj = jsonDoc.object();// 获取基本类型值if (jsonObj.contains("name") && jsonObj["name"].isString()) {QString name = jsonObj["name"].toString();qDebug() << "Name:" << name;}// 获取数组if (jsonObj.contains("books") && jsonObj["books"].isArray()) {QJsonArray booksArray = jsonObj["books"].toArray();qDebug() << "Books:";for (int i = 0; i < booksArray.size(); ++i) {if (booksArray[i].isObject()) {QJsonObject bookObj = booksArray[i].toObject();QString title = bookObj["title"].toString();QString author = bookObj["author"].toString();qDebug() << "  Title:" << title;qDebug() << "  Author:" << author;}}}}
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);parseJSON("data.json");return a.exec();
}
3. JSON 生成示例
#include <QCoreApplication>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>void createJSON(const QString &fileName) {// 创建 JSON 对象QJsonObject rootObj;rootObj["name"] = "My Library";rootObj["location"] = "Beijing";rootObj["established"] = 2020;// 创建书籍数组QJsonArray booksArray;// 添加第一本书QJsonObject book1;book1["title"] = "C++ Primer";book1["author"] = "Stanley Lippman";book1["year"] = 2012;book1["available"] = true;booksArray.append(book1);// 添加第二本书QJsonObject book2;book2["title"] = "Qt 5 C++ GUI Programming Cookbook";book2["author"] = "Mark Summerfield";book2["year"] = 2018;book2["available"] = false;booksArray.append(book2);// 将书籍数组添加到根对象rootObj["books"] = booksArray;// 创建 JSON 文档QJsonDocument jsonDoc(rootObj);// 写入文件QFile file(fileName);if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {file.write(jsonDoc.toJson(QJsonDocument::Indented));file.close();}
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);createJSON("library.json");return a.exec();
}

三、XML 与 JSON 的对比与选择

1. 适用场景
特性XMLJSON
数据结构层次结构(元素嵌套)键值对和数组
语法复杂度较高(需要标签闭合、命名空间等)较低(简洁的键值对语法)
可读性较好(标签提供明确语义)好(简洁直观)
解析性能较低(DOM 方式需加载整个文档)较高(轻量级,解析速度快)
数据大小较大(标签增加冗余)较小(紧凑格式)
适用场景配置文件、文档交换(如 RSS、SOAP)网络 API(如 RESTful)、配置文件
2. 转换工具
  • XML → JSON:可通过解析 XML 并手动构建 JSON 对象实现转换。
  • JSON → XML:需创建 XML 结构,将 JSON 键值对映射为 XML 元素或属性。

以下是一个简单的 XML 到 JSON 转换示例:

QJsonValue xmlToJson(const QDomNode &node) {if (node.isElement()) {QDomElement element = node.toElement();QJsonObject obj;// 添加元素属性QDomNamedNodeMap attributes = element.attributes();for (int i = 0; i < attributes.size(); ++i) {QDomNode attribute = attributes.item(i);obj["@" + attribute.nodeName()] = attribute.nodeValue();}// 处理子节点QDomNodeList children = element.childNodes();if (children.size() == 1 && children.at(0).isText()) {// 如果只有文本内容,直接返回文本return QJsonValue(children.at(0).toText().data());} else {// 处理子元素QHash<QString, QJsonArray> childArrays;for (int i = 0; i < children.size(); ++i) {QDomNode child = children.at(i);if (child.isElement()) {QString name = child.nodeName();QJsonValue value = xmlToJson(child);if (childArrays.contains(name)) {childArrays[name].append(value);} else {QJsonArray array;array.append(value);childArrays[name] = array;}}}// 将子元素添加到对象QHashIterator<QString, QJsonArray> it(childArrays);while (it.hasNext()) {it.next();if (it.value().size() == 1) {obj[it.key()] = it.value().at(0);} else {obj[it.key()] = it.value();}}}return QJsonValue(obj);}return QJsonValue();
}

四、最佳实践与注意事项

1. XML 处理建议
  • 大型文件:使用 QXmlStreamReader 逐行解析,避免内存溢出。
  • 复杂操作:若需频繁修改或随机访问,使用 QDomDocument
  • 命名空间:处理含命名空间的 XML 时,使用 QXmlStreamReader::namespaceUri()
  • 错误处理:始终检查解析错误(如 QXmlStreamReader::hasError())。
2. JSON 处理建议
  • 网络数据:优先使用 JSON,因其轻量且易于解析。
  • 严格格式:JSON 格式严格(如键需用双引号),解析前需验证。
  • 空值处理:使用 QJsonValue::isNull()QJsonValue::isUndefined() 区分空值和未定义值。
  • 嵌套结构:处理深层嵌套的 JSON 时,建议先定义数据模型类进行映射。
3. 性能考虑
  • XML:DOM 方式加载整个文档到内存,适合小型文件;流解析适合大型文件。
  • JSON:解析速度通常快于 XML,尤其适合移动端和网络传输。

五、总结

Qt 提供了全面的 XML 和 JSON 处理工具,开发者可根据需求选择合适的方式:

  • XML:适合需要严格结构、丰富元数据和文档交换的场景,提供 DOM 和流两种处理方式。
  • JSON:适合轻量级数据交换、网络 API 和配置文件,语法简洁且解析高效。

掌握这些技术后,可轻松实现数据的存储、传输和交换,为应用开发提供强大的数据处理能力。

http://www.lryc.cn/news/599103.html

相关文章:

  • InfluxDB Line Protocol 协议深度剖析(二)
  • Qt 拔网线等情况下收不到disconnected()信号
  • 安卓上的迷之K_1171477665
  • Android悬浮窗导致其它应用黑屏问题解决办法
  • 【HarmonyOS】鸿蒙应用开发中常用的三方库介绍和使用示例
  • SpringBoot与ApacheSpark、MyBatis实战整合
  • [python][flask]flask静态资源
  • Spring Boot License 认证系统
  • 从零开始的云计算生活——番外6,使用zabbix对中间件监控
  • [SAP ABAP] 请求释放及传输
  • 二开---01
  • 基于多种主题分析、关键词提取算法的设计与实现【TF-IDF算法、LDA、NMF分解、BERT主题模型】
  • 【vue vapor jsx 未雨绸缪】
  • 篇五 网络通信硬件之PHY,MAC, RJ45
  • 统一调度与编排:构建自动化数据驱动平台
  • 【Java、C、C++、Python】飞机订票系统---文件版本
  • Fluent自动化仿真(TUI命令脚本教程)
  • RCE真实漏洞初体验
  • 制造业低代码平台实战评测:简道云、钉钉宜搭、华为云Astro、金蝶云·苍穹、斑斑低代码,谁更值得选?
  • NBIOT模块 BC28通过MQTT协议连接到EMQX
  • 栈与队列:数据结构核心解密
  • 《Uniapp-Vue 3-TS 实战开发》自定义环形进度条组件
  • 数据结构 二叉树(1)
  • 《Uniapp-Vue 3-TS 实战开发》自定义年月日时分秒picker组件
  • uniapp创建vue3+ts+pinia+sass项目
  • Linux 桌面市场份额突破 5%:开源生态的里程碑与未来启示
  • 【数据结构与算法】数据结构初阶:详解二叉树(六)——二叉树应用:二叉树选择题
  • 数据结构3-单双链表的泛型实现及ArrayList与LinkedList的区别
  • SpringBoot(黑马)
  • 【Unity笔记】OpenXR 之VR串流开发笔记:通过RenderTexture实现仅在PC端展示UI,在VR眼镜端隐藏UI