qt读写xml文件

news2024/11/17 5:23:27

Qt使用XML模块,在.pro文件中添加 QT += xml

Qt 提供了三种读 XML 文档的方法:

QXmlStreamReader/QXmlStreamWriter:

一种快速的基于流的方式访问良格式 XML 文档特别适合于实现一次解析器(所谓“一次解析器”,可以理解成我们只需读取文档一次,然后像一个遍历器从头到尾一次性处理 XML 文档,期间不会有反复的情况,也就是不会读完第一个标签,然后读第二个,读完第二个又返回去读第一个,这是不允许的);

DOM(Document Object Model):

将整个 XML 文档读入内存,构建成一个树结构,允许程序在树结构上向前向后移动导航,这是与另外两种方式最大的区别,也就是允许实现多次解析器(对应于前面所说的一次解析器)。DOM 方式带来的问题是需要一次性将整个 XML 文档读入内存,因此会占用很大内存;

SAX(Simple API for XML):

提供大量虚函数,以事件的形式处理 XML 文档。这种解析办法主要是由于历史原因提出的,为了解决 DOM 的内存占用提出的(在现代计算机上,这个一般已经不是问题了).基本不使用了.

QXmlStreamReader/QXmlStreamWriter

#include <QXmlStreamWriter>

#include <QXmlStreamReader>

写操作

void writeStartDocument();

//写文档头,作用类似于创建一个xml文档,并在文档开头部分写入版本信息和编码信息默认为:

  <?xml version="1.0" encoding="UTF-8"?>

void writeEndDocument();

//当调用这个函数时,即表示文档信息写入完毕

void writeStartElement(const QString &qualifiedName);

//写入开始记号 比如<COMMAND>

void writeEndElement();

//写入结束记号 比如</COMMAND>

void writeTextElement(const QString &qualifiedNameconst QString &text);

//写入文本信息 <OBJECT>USER</OBJECT>

void writeAttribute(const QString &qualifiedNameconst QString &value);

//写入文本的属性   <USER NAME="root" PASSWORD="123456"/>

 

QFile file(fileName);
    if(file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QXmlStreamWriter writer(&file);
        writer.setAutoFormatting(true);
        writer.writeStartDocument();
        writer.writeStartElement("COMMAND");
        writer.writeTextElement("OBJECT", "USER");
        writer.writeTextElement("ACTION", "LOGIN");
        writer.writeStartElement("DATA");
        writer.writeStartElement("USER");
        writer.writeAttribute("NAME", "root");
        writer.writeAttribute("PASSWORD", "123456");
        writer.writeEndElement();
        writer.writeEndElement();
        writer.writeEndElement();
writer.writeEndDocument();
        file.close();
    }
<?xml version="1.0" encoding="UTF-8"?>
<COMMAND>
    <OBJECT>USER</OBJECT>
    <ACTION>LOGIN</ACTION>
    <DATA>
        <USER NAME="root" PASSWORD="123456"/>
    </DATA>
</COMMAND>

读操作

 readNext(): 从xml输入流中读取下一个记号。

 name(): 记号的名称,即<名称></名称>

 isStartElement():判断当前已读取的记号是否为开始元素,开始元素即<>

注意:像上面的 <OBJECT>USER</OBJECT>也是

 isEndElement():判断当前已读取的记号是否为结束元素,结束元素即</>

 readElementText():读取当前记号对应的文本值,<>文本值</>

 atEnd():判断是否为文件结尾

QXmlStreamAttributes attributes() const; 获取含有属性节点的属性

inline bool hasAttribute(const QString &qualifiedName); //

QStringRef value(const QString &qualifiedName) const;//获取属性的值

int StreamParseXml::readXml()
{
    if(fileName.isEmpty()) return -2;
    QFile *file = new QFile(fileName);
    if(!file->open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::information(NULL, QString("title"), QString("open error!"));
        return -1;
    }
    reader = new QXmlStreamReader(file);
     while(!reader->atEnd() && !reader->hasError()) {
         QXmlStreamReader::TokenType token = reader->readNext();
         if(token == QXmlStreamReader::StartDocument) {
             continue;
         }
          if (reader->isStartElement() && reader->name() == "OBJECT") {
              QString elementText = reader->readElementText();
              if (elementText == "USER") {
                  parseUserInformation();
                  break;
              }
          }
     }
    if (reader->hasError()) {
        qDebug() << reader->errorString();
        //QMessageBox::information(NULL, QString("parseXML"), reader->errorString());
    }
    reader->clear();
    delete reader;
    reader = NULL;
    return 0;
} 
void StreamParseXml::parseUserInformation()
{
    QString elementString = getValue("ACTION");
    if (elementString == "LOGIN") {
        while(!reader->atEnd()) {
            reader->readNext();
            if (reader->name() == "USER") {
                QXmlStreamAttributes attributes = reader->attributes();
                if(attributes.hasAttribute("NAME")) {
                    qDebug() << "USER=" << attributes.value("NAME").toString();
                }
                if(attributes.hasAttribute("PASSWORD")) {
                    qDebug() << "PASSWORD=" << attributes.value("PASSWORD").toString();
                }
            }
        }
    }
}
QString StreamParseXml::getValue(const QString &name)
{
    while(!reader->atEnd()) {
        reader->readNext();
        if (reader->isStartElement() && reader->name() == name) {
            return reader->readElementText();
        }
    }
    return "";
}

QDomDocument

引用头文件

#include <QDomDocument>

QDomDocument类代表整个的XML文件。概念上讲:它是文档树的根节点,并提供了文档数据的基本访问方法。由于元素、文本节点、注释、指令执行等等不可能脱离一个文档的上下文,所以文档类也包含了需要用来创建这些对象的工厂方法

DOM类中最常使用的是QDomNode、QDomDocument、QDomElement和QDomText。

 QDomDocument::setContent()完成XML文档的设置,他从QFile对象中读取XML数据并检测XML文档的编码

写操作

结合QFileQTextStream类一起使用。

常用的函数:

QDomProcessingInstruction createProcessingInstruction(const QStringtargetconst QStringdata);//创建版本和编码格式

QDomNode appendChild(const QDomNodenewChild);//添加数据到节点

QDomElement createElement(const QStringtagName);//创建节点

QDomText createTextNode(const QStringdata);//创建节点的文本

QDomAttr createAttribute(const QStringname);//创建属性

QDomAttr setAttributeNode(const QDomAttrnewAttr);//节点关联属性

 void save(QTextStream&, intEncodingPolicy=QDomNode::EncodingFromDocumentconst;//把整个QDomDocumentQTextStream形式保存到本地文件。

int DomDocument::writeXml()
{
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
        return -2;
    QTextStream out(&file);
    QDomDocument doc;
    QDomText text;
    QDomElement element;
    QDomAttr attr;
    QDomProcessingInstruction instruction;
    instruction = doc.createProcessingInstruction( "xml", "version = \'1.0\' encoding=\'UTF-8\'" );
    doc.appendChild( instruction );
 
    QDomElement root = doc.createElement( "COMMAND" );
    doc.appendChild(root);
    element = doc.createElement( "OBJECT" );
    text = doc.createTextNode( "USER" );
    element.appendChild(text);
    root.appendChild(element);
 
    element = doc.createElement( "ACTION" );
    text = doc.createTextNode( "LOGIN" );
    element.appendChild(text);
    root.appendChild(element);
 
    element = doc.createElement( "DATA" );
    root.appendChild(element);
 
    QDomElement userElement = doc.createElement( "USERINFO" );
    attr = doc.createAttribute( "NAME" );
    attr.setValue("root");
    userElement.setAttributeNode(attr);
    attr = doc.createAttribute( "PASSWORD" );
    attr.setValue("123456");
    userElement.setAttributeNode(attr);
    element.appendChild(userElement);
 
    doc.save(out, 4);       //each line space of file is 4
    return 0;
}

读操作

结合QFile类一起使用。使用setContent函数进行关联。

bool setContent(QIODevicedevbool namespaceProcessingQString *errorMsg=nullptrint *errorLine=nullptrint *errorColumn=nullptr );QFileQDomDocument关联,从QFile对象中读取XML数据

QDomElement documentElement() const; //获取dom树的根标签

QString tagName() const;  //获取根/子标签的标签名字,对应于createElement函数的参数

 QString text() const; //获取根/子标签的文本,对应于createTextNode函数的参数

QDomNode firstChild() const;//根/子标签下的子标签

 QDomNode nextSibling() const; //下一个标签

bool isNull() const; //判断标签是否为空,用于是否标签到最后面结束了。

QDomElement toElement() const;  //把QDomNode 转换成QDomElement ,即基类转换成子类

bool hasAttribute(const QStringnameconst; //判断标签节点是否有属性

对应于createAttribute函数操作

QDomAttr attributeNode(const QStringname);//获取标签节点的属性

QString name() const;//获取标签节点的属性名称

QString value() const;//获取标签节点的属性值

int DomDocument::readXml()
{
    QDomDocument doc;
    QFile file(fileName);
    QString error = "";
    int row = 0, column = 0;
    if (!file.open(QIODevice::ReadOnly)) return -2;
 
    if(!doc.setContent(&file, false, &error, &row, &column)){
        qDebug() << "parse file failed:" << row << "---" << column <<":" <<error;
        file.close();
        return -1;
    }
 
    file.close();
    QDomElement root = doc.documentElement();
    QDomNode node = root.firstChild();    //得到COMMAND标签
    while(!node.isNull()) {
       QDomElement element = node.toElement(); // try to convert the node to an element.
       if(!element.isNull()) {
          qDebug()<<element.tagName() << ":" << element.text();
          QDomNode nodeson = element.firstChild(); //得到OBJECT标签
          while(!nodeson.isNull()) {
              QDomElement elementson = nodeson.toElement();
              if(!elementson.isNull()) {
                  qDebug()<< "---" <<elementson.tagName();
                  if (elementson.hasAttribute("NAME")) {
                      qDebug()<< "---" << "NAME=" << elementson.attributeNode("NAME").value();
                  }
                  if (elementson.hasAttribute("PASSWORD")) {
                      qDebug()<< "---" << "PASSWORD=" << elementson.attributeNode("PASSWORD").value();
                  }
              }
              nodeson = nodeson.nextSibling();
          }
       }
       node = node.nextSibling();
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/676613.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端vue入门(纯代码)13

【13.Vue的消息订阅与发布】 备注&#xff1a;全局事件总线用的更多些&#xff0c;消息订阅与发布只需了解即可。【注意点1】&#xff1a;由于“消息订阅与发布”可依赖的第三方库太多了&#xff0c;这里使用pubsub-js 问题&#xff1a;“全局事件总线”和“消息订阅与发布”都…

看完这篇 教你玩转渗透测试靶机vulnhub—Emplre: Breakout

Vulnhub靶机Emplre: Breakout渗透测试详解 Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a;②&#xff1a;登入后台&#xff1a;③&#xff1a;GetShell&#xff1a;④…

oracle操作xml格式数据

新建一张用来测试的表 -- Create table create table XMLTEST (id NUMBER,content VARCHAR2(4000) );往表中插入数据 insert into XMLTEST (id, content) values (1, <root><app><id>1</id><name>张三</name><age>18</age…

《网络安全0-100》经典访问控制策略

1经典访问控制策略 1.1自主访问控制 允许用户自己对客体将已有的权限赋予给其他主体&#xff0c;也可以撤销自己赋予给其他主体的权限。 矩阵结构分为三个主要的表&#xff1a; 访问控制矩阵 访问控制列表 权能表 矩阵的局限性&#xff1a; 大小为主体数量客体数量&…

【FPGA】Verilog:时序电路设计 | 自循环移位寄存器 | 环形计数 | 扭环计数 | 约翰逊计数器

前言&#xff1a;本章内容主要是演示Vivado下利用Verilog语言进行电路设计、仿真、综合和下载 示例&#xff1a;计数器 ​​ 功能特性&#xff1a; 采用 Xilinx Artix-7 XC7A35T芯片 配置方式&#xff1a;USB-JTAG/SPI Flash 高达100MHz 的内部时钟速度 存储器&#xff1a;2Mb…

Bresenham直线算法

文章目录 1.Bresenham直线算法1.1 算法流程1.2 Bresenham算法实现1.3matlab中应用1.4 算法优势1.5 对比以往方法的改进和优化1.6 算法改进和缺陷 2.国内外研究现状3.个人感想及算法改进 1.Bresenham直线算法 Bresenham直线算法是一种用于将两点之间的线段绘制在屏幕上的算法。…

什么是MLOps?为什么要使用MLOps进行机器学习实践

随着数字化和计算能力的发展&#xff0c;机器学习&#xff08;Machine Learning&#xff09;技术在提高企业生产力方面所涌现的潜力越来越被大家所重视&#xff0c;然而很多机器学习的模型及应用在实际的生产环境并未达到预期&#xff0c;大量的ML项目被证明是失败的。从机器学…

【Red Hat7.9安装Oracle11g】---调用图形化界面的几种方式

【Red Hat7.9安装Oracle11g】---调用图形化界面的几种方式 &#x1f53b; 一、续上一篇[【Red Hat 7.9---详细安装Oracle 11g---图形化界面方式】](https://blog.csdn.net/qq_41840843/article/details/131198718?spm1001.2014.3001.5501)⛳ 1.1 前言⛳ 1.2 方式一、使用Xmana…

MIT 6.S081 Lab Five

MIT 6.S081 Lab Five 引言xv6 lazy page allocationEliminate allocation from sbrk() (easy)代码解析 Lazy allocation (moderate)代码解析 Lazytests and Usertests (moderate)代码解析 可选的挑战练习 引言 本文为 MIT 6.S081 2020 操作系统 实验五解析。 MIT 6.S081课程前…

从C语言到C++_21(模板进阶+array)+相关笔试题

目录 1. 非类型模板参数 1.1 array 1.2 非类型模板参数的使用场景 1.3 注意事项 2. 模板的特化 2.1 函数模板的特化 2.2 类模板的特化 2.3 全特化和偏特化(半特化) 3. 模板关于分离编译 4. 模板优缺点 5. 模板相关笔试题 本章完。 1. 非类型模板参数 对于函数模板…

dhtmlx Event Calendar JavaScript new Crack

DHTMLX Event Calendar可帮助您开发类似 Google 的 JavaScript 事件日历&#xff0c;以高效地组织约会。用户可以通过拖放来管理事件&#xff0c;并以六种不同的模式显示它们。 JavaScript 事件日历功能 轻的 简单的 JavaScript API 六个默认视图&#xff1a;日、周、月、年、议…

Java并发编程学习16-线程池的使用(中)

线程池的使用&#xff08;中&#xff09; 引言1. 配置 ThreadPoolExecutor1.1 线程的创建与销毁1.2 管理队列任务1.3 饱和策略1.4 线程工厂1.5 定制 ThreadPoolExecutor 2. 扩展 ThreadPoolExecutor总结 引言 上篇分析了在使用任务执行框架时需要注意的各种情况&#xff0c;并…

死锁的成因以及解决方案(简析)

目录 一.为什么会产生死锁? 二.死锁产生的几个场景 一个线程一把锁的情况 关于可重入和不可重入锁的简单举例 两个线程两把锁的情况 多线程多把锁 如何解决死锁 一.为什么会产生死锁? 简单来说,就是进程加锁之后,没有被解锁而处于一直等待的状态 二.死锁产生的几个场景…

深入理解深度学习——BERT(Bidirectional Encoder Representations from Transformers):BERT的结构

分类目录&#xff1a;《深入理解深度学习》总目录 相关文章&#xff1a; BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff1a;基础知识 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09…

软件架构模式—分层架构

这是软件架构模式博客系列第 2 章&#xff0c;我们将讨论分层架构模式。 分层架构模式是一种n层模式&#xff0c;其中组件按照水平层次进行组织。这是设计大多数软件的传统方法&#xff0c;旨在实现自我独立。这意味着所有组件之间相互连接&#xff0c;但彼此之间不相互依赖。…

测试体系与测试方案设计

如果我们想要测试一个系统&#xff0c;我们得先需要了解被测系统架构 业务架构:业务模型分析技术架构:技术组件、通讯协议分析数据架构:数据模型、数据存储引擎分析 电子商城 Mall 开源项目技术架构 经典技术架构 网关产品 Nginx Apache HttpdWeb 应用开发 Vue.js React移动应…

福州大学学报退稿率【爬虫+数据处理】

目录 一、爬虫 二、数据处理 2.1 历年投稿总数&#xff1a; 2.2 各稿件状态比例&#xff1a; 2.3 历年退稿率 三、总结&#xff08;福州大学学报退稿率&#xff09; 一、爬虫 从福州大学学报微信公众号可以发现稿件状态的查询接口&#xff0c; 根据测试可知稿件号由年份与当…

Linux共享内存

博客内容&#xff1a;共享内存 文章目录 一、认识共享内存结构二、如何创建共享内存&#xff1f;1.创建共享内存2.关联进程&#xff0c;取消进程3.释放共享内存 三、代码示例总结 一、认识共享内存结构 共享内存 共享内存指 (shared memory)在多处理器的计算机系统中&#xff…

新手速成!如何使用ChatGPT成为你的导师

1. 写在前面 最近我发现咱们的团队现在是人手ChatGPT&#xff0c;不光是我们团队&#xff0c;我整个行业的人都在用它解决生活跟工作中遇到的问题。可以看到的是大家也都是对它赞赏度很高 本文我将为大家介绍如何更加高效的使用ChatGPT提高工作效率&#xff0c;面向ChatGPT编程…

JavaScript高级学习总结

函数作用域 函数内部声明的变量&#xff0c;在函数外部无法被访问函数的参数也是函数内部的局部变量不同函数内部声明的变量无法互相访问函数执行完毕之后&#xff0c;函数内部的变量实际被清空了 块作用域 let声明的变量会产生块作用域&#xff0c;var不会产生块作用域cons…