五、Qt读写XML

人其实是很抗拒新的事物,因为新的事物会打破既有的积累,但是新的东西往往具有更优越的特点,当然今天说的XML不算是新的东西

XML是一种文本的组织格式,打个比方说,有一个人的个人资料信息,你要传输给我,按照传统的方式,你可以像我传输一个字符串,诸如"年龄:24,身高:175,姓名:xxx,地区:北京",那么我接收到这段字符串的时候,从人的角度,我可以直接读出,从计算机的角度,我可以按照某种约定或者固定的格式去分析字符串,再将字符串切割再提取有效信息,是可以的,但是假如发送的消息增加了,增加了其他的选项,那就得需要改代码,假如我这个软件需要在web端实现,web端用的JavaScript语言,之前用的C语言,就不能实现移植,这是其中之一,另外一个原因是,这种方式对于字符串解析会花费大量的时间,复杂,容易出错,不易维护,如果有更多数据的时候,对于数据的解析,会产生巨量的工作量。

但是用XML可以避免上述这些问题,XML是一种固定的格式,当大家都遵循这个规则的时候,就实现了跨平台,跨语言,通用性大大提高,其实我更想说的是,XML是一种树形的方式组织的,由唯一的根(root)节点和其他节点组成,节点下还可以挂节点,每个节点都可以携带一条或者多条消息,我们通过对每个节点进行遍历,就能访问到树上的任何节点,从而提取到我们所存的信息

可以这么理解,最形象的就是思维导图,XML就是以思维导图的方式存储信息,且在不同的主流编程语言中,提供了相当完善的库,对XML格式进行读和写,值得一提的是,与XML相对应的还有JSON,下一篇会分析JSON

我们设计一个场景,我们公司的项目有需要动态创建页面,什么是动态呢?在软件运行的情况下修改某些页面,实现软件的在线更新,而且是那种运行过程中不掉线的更新,然后设计了一种利用XML文件进行页面更新的方式,我们将软件结构设计为,软件启动后,每一个页面的信息都是从文件读出的,比如我单击某个按钮,跳转到某个界面这个功能,单击按钮时,会先去读取对应的XML文件进行解析,而这个XML文件就描述了这个页面的信息,比如页面大小,按钮等等,我们将整个界面的信息用树的形式组织起来,修改的时候只要修改XML文件,然后进行重新加载这个页面,就实现了这样的效果,这种思想其实是非常棒的,其实采用这种方式的还有很多,例如嵌入式中的设备树。

读XML

QFile file(fileName);
//打开文件流
if(!file.open(QFile::ReadOnly|QFile::Text))
{
    qDebug()<<"Cont open the file "<<fileName;
    return false;
}
QDomDocument dom;
//读取dom树
if(!dom.setContent(&file))
{
    qDebug()<<"Read DOMDocument failed "<<fileName;
    return false;
}
//保存根节点
QDomElement root=dom.documentElement();

QDomNode node=root.childNodes().at(5);//获取root下的第5个节点的节点对象

//这是一个XML的简单的文档
<?xml version="1.0" encoding="UTF-8"?>
<DeviceParameters>
	<settingZone>10</settingZone>
	<stationName>退出/投入</stationName>
	<litPTOnce>10</litPTOnce>
</DeviceParameters>


QString name = node.toElement().tagName()//获取这个节点的标签名字,比如上面的stationName或litePTOnce
QString name = node.toElement().text()//获取这个节点的数据10、退出投入
//值得一提的是,每一条像<litPTOnce>10</litPTOnce>的标签就是一个节点,在上述例子中,<DeviceParameters>这个标签下,是有3个节点的,每一个节点或者标签都是一个QDomNode

这段代码描述的是,有一个XML文件,我们用QFile进行加载并打开,然后用**QDomDocument**这个类去解析

QDomDocument:
//一个XML文档,其实可以理解为一棵树的根基,代表了一整个XML文档
dom.setContent(&file)
//将这个文档的数据解析到这个树上,这样你就可以面对对象的方式操作你的数据了

QDomElement:
//代表XML的元素,XML树上的每一个节点的信息都可以用这个来描述,虽然没有实际的验证,但是从用法上我推测他的作用就是描述一个节点的信息,比如这个节点是否有子节点,以及各个子节点的指针,通过at等方法可以获得QDomNode的具体节点对象

QDomNode
//代表一个具体的节点,对这个节点的数据访问就是使用这个对象
    
QDomNode node.childNodes().at(n)
//可以使用这个API来获取这个节点的子节点,可以使用size()方法获取子节点的个数,然后用at方法进行遍历,当对root开发,对每一个节点进行遍历,并且用上述提供的两个方法提取标签名字和信息的时候,就能对真个XML文档遍历,提取到我们存储的每一条信息

写XML

写XML其实是一个逆向的过程,大致过程就是构建一棵树,我们看一下几个常用的API

QDomDocument dom;
//创建一个XML文档

QDomElement rootElement=dom.createElement("continuousSelectLineParematers");
//创建一个节点

QDomElement element=dom.createElement(QString("continuousSelectLineParemater"));
//创建一个节点

rootElement.appendChild(element);
//将element挂到rootElement节点下

element.appendChild(GetTextElement("continuous",continuousSelectLineConfig.continuous));   element.appendChild(GetTextElement("interval",QString::number(continuousSelectLineConfig.interval)));
element.appendChild(GetTextElement("disEachResult",continuousSelectLineConfig.displayEachResult));
//在element节点下挂了3个节点,实际上就是3条标签,后面的GetTextElement这个函数我放在下面了,其实就是给定标签名字和数据创造一个节点

return WriteFile(QString(XMLFILEPATH)+"line.xml",rootElement);
//调用写入XML文件的接口,这个函数也在下面了,第一个参数是要保存的文件的名字,第二个参数是上面创建的根节点


QDomElement xmlHelper::GetTextElement(QString title, QString text)
{
    QDomDocument dom;
    QDomElement titel=dom.createElement(title);
    titel.appendChild(dom.createTextNode(text));
    return titel;
}//根据标签名和数据,创建并返回一个标签节点


bool xmlHelper::WriteFile(const QString &fileName,const QDomElement &root)
{
    QDomProcessingInstruction instruction;
    QDomDocument dom;
    instruction=dom.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    dom.appendChild(instruction);
    dom.appendChild(root);
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly|QFile::Truncate))
    {
        qDebug()<<"Cont open the file "<<fileName;
        return false;
    }
    QTextStream in(&file);
    in.setCodec("UTF-8");//规定写入格式
    dom.save(in,4);//写入文件
    file.close();
    return true;
}//写入XML文件,其实就是创建版本号,然后将参数传入的根节点挂到创建的文档中

最后想说的一点就是,树这种方式真的是一种非常非常优秀的一种思想,在很多地方都有这种思想的运用,包括设备树,包括思维导图等等等等,以后会更多,还是要好好的理解,本篇 的代码经过测试,可以直接复制使用,不要停止学习啊,共勉!手肝不易

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值