Qt XML的使用

Qt中对于XML文件的写入有两种方式,一个是使用QXmlStreamWriter,另一个则为使用Dom。stream流的形式相对来说更加灵活,而且适合处理大文件。Dom方式由于是将内容加载到了内存中进行操作,所以对于小内存设备则有一定得局限性。

根据《QtCreator快速入门》和网上的一些例子练习了Qt XML的使用,做一个记录,以下是采用Dom方式实现的

实现界面

编写的XML文件


 1 <?xml version="1.0" encoding="UTF-8"?>
2 <information>
3 <pin id="1">
4 <card id="1">
5 <port id="1" flag="0"/>
6 <port id="2" flag="0"/>
7 <port id="3" flag="0"/>
8 <port id="4" flag="0"/>
9 <port id="5" flag="0"/>
10 <port id="6" flag="0"/>
11 <port id="7" flag="0"/>
12 </card>
13 <card id="2">
14 <port id="1" flag="0"/>
15 <port id="2" flag="0"/>
16 <port id="3" flag="0"/>
17 <port id="4" flag="0"/>
18 <port id="5" flag="0"/>
19 <port id="6" flag="0"/>
20 </card>
21 <card id="3">
22 <port id="1" flag="0"/>
23 <port id="2" flag="0"/>
24 <port id="3" flag="0"/>
25 <port id="4" flag="0"/>
26 <port id="5" flag="0"/>
27 </card>
28 </pin>
29 <pin id="2">
30 <card id="1">
31 <port id="1" flag="0"/>
32 <port id="2" flag="0"/>
33 <port id="3" flag="0"/>
34 <port id="4" flag="0"/>
35 <port id="5" flag="0"/>
36 <port id="6" flag="0"/>
37 <port id="7" flag="0"/>
38 </card>
39 <card id="2">
40 <port id="1" flag="0"/>
41 <port id="2" flag="0"/>
42 <port id="3" flag="0"/>
43 <port id="4" flag="0"/>
44 <port id="5" flag="0"/>
45 <port id="6" flag="0"/>
46 </card>
47 </pin>
48 </information>

一共有三层,pin->card->port,最内层的port有id和flag两种属性

首先是编写XML文件

代码如下:


 1 void xml::writeXML()
2 {
3 QFile file("../project/ini/write.xml");
4 if(!file.open(QIODevice::WriteOnly|QIODevice::Truncate))
5 {
6 return;
7 }
8 QDomDocument doc;
9 QDomProcessingInstruction instruction;
10
11 instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
12 doc.appendChild(instruction);
13 QDomElement root=doc.createElement(tr("information"));
14 doc.appendChild(root);
15
16 QDomElement Pin;
17 QDomElement Card;
18 QDomElement Port;
19 QDomAttr ID = doc.createAttribute("id");
20 QDomAttr Flag = doc.createAttribute("flag");
21 //QDomText text;
22
23 for (int i = 1;i < 3;i++)
24 {
25 Pin = doc.createElement(tr("pin"));
26
27 ID = doc.createAttribute("id");
28 ID.setValue(tr("%1").arg(i));
29 Pin.setAttributeNode(ID);
30
31 //Pin.appendChild(Card);
32 //Card = doc.createElement(tr("card"));
33 for (int j = 1;j < 5 - i;j++)
34 {
35 Card = doc.createElement(tr("card"));
36
37 ID = doc.createAttribute("id");
38 ID.setValue(tr("%1").arg(j));
39 Card.setAttributeNode(ID);
40
41 for (int k = 1;k < 9 - j;k++)
42 {
43 Port = doc.createElement(tr("port"));
44
45 ID = doc.createAttribute("id");
46 ID.setValue(tr("%1").arg(k));
47 Port.setAttributeNode(ID);
48 Flag = doc.createAttribute("flag");
49 Flag.setValue("0");
50 Port.setAttributeNode(Flag);
51
52 Card.appendChild(Port);
53 }
54 Pin.appendChild(Card);
55 }
56 root.appendChild(Pin);
57 }
58
59 QTextStream out(&file);
60 doc.save(out,4);
61 file.close();
62 }

QDomProcessingInstruction instruction;

instruction =
doc.createProcessingInstruction("xml","version=/"1.0/" encoding=/"UTF-8/"");

用来写入XML文件的声明,这对于一个XML文件来说不可缺少。

writeXML()中采用三层for循环进行XML的存储。

好了,现在有我们需要操作的XML文件了,下一步就是就是进行读取,并在界面上显示
我是采用三个listWidget分别显示pin card port信息的
代码如下:


 1 /*
2 *函数名:_CreateListWidget
3 *功能:初始化探针、板卡、端口信息
4 *
5 */
6 void configure_win::_CreateListWidget()
7 {
8 ui->cardlistWidget->clear();
9 ui->portlistWidget->clear();
10 ui->pinlistWidget->clear();
11 int flag_card = 1;
12 int flag_port = 1;//判断标识,确定listWidget初始化显示一次
13 QDomDocument doc;
14 QFile file("../project/ini/write.xml");
15 if (!file.open(QIODevice::ReadOnly))
16 {
17 return;
18 }
19 if (!doc.setContent(&file))
20 {
21 file.close();
22 return;
23 }
24 file.close();
25 QDomElement docElem = doc.documentElement();
26 QDomNode n = docElem.firstChild();
27 while (!n.isNull())
28 {
29 if (n.isElement())
30 {
31 QDomElement e = n.toElement();
32 ui->pinlistWidget->addItem(e.toElement().tagName()+e.toElement().attribute("id"));
33 //ui->pinlistWidget->addItem("探针"+e.toElement().attribute("id"));
34 QDomNodeList listcard = e.childNodes();
35 if (flag_card)
36 {
37 for (int i = 0;i < listcard.count();i++)
38 {
39 QDomNode node = listcard.at(i);
40 if (node.isElement())
41 {
42 ui->cardlistWidget->addItem(node.toElement().tagName()+node.toElement().attribute("id"));
43 //ui->cardlistWidget->addItem("板卡"+node.toElement().attribute("id"));
44 QDomNodeList listport = node.childNodes();
45 if (flag_port)
46 { for (int j = 0;j < listport.count();j++)
47 {
48 QDomNode port = listport.at(j);
49 if (port.isElement())
50 {
51 QListWidgetItem *item = new QListWidgetItem;
52 item->setText(port.toElement().tagName() + port.toElement().attribute("id"));
53 item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
54 item->setCheckState(Qt::Unchecked);
55 ui->portlistWidget->addItem(item);
56 //ui->portlistWidget->addItem(port.toElement().tagName() + port.toElement().attribute("id"));
57 //ui->portlistWidget->addItem("端口" + port.toElement().attribute("id"));
58 }
59 }
60 }
61 flag_port = 0;
62 }
63 node = node.nextSibling();
64 }
65 }
66 flag_card = 0;
67 }
68 n = n.nextSibling();
69 }
70 ui->pinlistWidget->item(0)->setSelected(true);
71 ui->cardlistWidget->item(0)->setSelected(true);
72 g_pin = ui->pinlistWidget->item(0)->text();//初始化存储pin card port
73 g_card = ui->cardlistWidget->item(0)->text();
74 g_port = ui->portlistWidget->item(0)->text();
75 }

因为涉及到获取listWidget的item的信息,而界面上只能有一个焦点,所以我使用了三个全局变量保存当前被激活的item项

并且默认为第一项被选中,这样就完成了开始界面的呈现

现在只是完成了XML数据的静态呈现,还没有动态显示,所以下一步需要对listWidget添加一些信号槽函数


1 connect(ui->pinlistWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(xmlChanged(QListWidgetItem*)));//点击探针
2 connect(ui->cardlistWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(xmlChanged(QListWidgetItem*)));//点击板卡

代码如下:


 1 /*
2 *槽函数名:xmlChanged
3 *功能:根据选择读取xml信息
4 *
5 */
6 void configure_win::xmlChanged(QListWidgetItem *item)
7 {
8 QString str = item->text();
9 QString str2 = str.right(1);//取最后一位1
10 QString str1 = str.left(str.length() - 1);//去掉最后一位 card
11 if (str1 == "pin")//点击pin
12 {
13 g_pin = str;//选中的pin改变
14 g_card = "card1";//默认card1
15 g_port = "port1";
16 _SelectChanged(str,"card1");
17 ui->cardlistWidget->item(0)->setSelected(true);
18 }
19 else if (str1 == "card")//点击card
20 {
21 g_card = str;//选中的card改变
22 g_port = "port1";
23 QString strpin;
24 if (ui->pinlistWidget->currentRow() == -1)//获得选中card对应探针????初始化pin第一项pin为选中,为什么返回-1而不是0
25 {
26 strpin = ui->pinlistWidget->item(0)->text();
27 }
28 else
29 {
30 strpin = ui->pinlistWidget->currentItem()->text();
31 }
32 int i = ui->cardlistWidget->currentRow();//获取选中card项
33 _SelectChanged(strpin,str);//更新listWidget
34 ui->cardlistWidget->item(i)->setSelected(true);//重新设置card为选中
35 }
36 }


 1 /*
2 *函数名:_SelectChanged
3 *功能:更新探针、板卡、端口信息
4 *
5 */
6 void configure_win::_SelectChanged(QString str1, QString str2)
7 {
8
9 QDomDocument doc;
10 QFile file("../project/ini/write.xml");
11 if (!file.open(QIODevice::ReadOnly))
12 {
13 return;
14 }
15 if (!doc.setContent(&file))
16 {
17 file.close();
18 return;
19 }
20 file.close();
21
22 //QString str = item->text();
23 //qDebug()<<str1;
24 QString strNumberPin = str1.right(1);
25 QString strTypePin = str1.left(str1.length() - 1);//去掉最后一位
26 QString strNumberCard = str2.right(1);
27 QString strTypeCard = str2.left(str1.length() - 1);//去掉最后一位
28 //qDebug()<<strNumberPin<<strTypePin<<strNumberCard<<"\n"<<strTypeCard;
29 //if (i)//点击板卡
30 {
31 QDomNodeList list = doc.elementsByTagName(strTypePin);//查找探针项
32 for (int i = 0;i < list.count();i++)
33 {
34 QDomElement e = list.at(i).toElement();
35 if (e.attribute("id") == strNumberPin)//找到对应的探针
36 {
37 ui->cardlistWidget->clear();//清空板卡
38 QDomNodeList childCard = e.childNodes();
39 for (int j = 0;j < childCard.count();j++)//遍历板卡
40 {
41 QDomElement card = childCard.at(j).toElement();
42 //QDomNode port = childCard.at(j);
43 //qDebug()<<" "<<qPrintable(card.tagName())<<qPrintable(card.attribute("id"));
44 QListWidgetItem *item = new QListWidgetItem;
45 item->setText(card.tagName() + card.attribute("id"));
46
47 //item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
48 //item->setCheckState(Qt::Unchecked);
49 ui->cardlistWidget->addItem(item);
50 if (card.attribute("id") == strNumberCard)
51 {
52 ui->portlistWidget->clear();//清空端口
53 QDomNodeList childPort = card.childNodes();
54
55 for (int k = 0;k < childPort.count();k++)
56 {
57 QDomNode port = childPort.at(k);
58 //qDebug()<<" "<<qPrintable(port.toElement().tagName())<<qPrintable(port.toElement().attribute("id"));
59 QListWidgetItem *item = new QListWidgetItem;
60 item->setText(port.toElement().tagName() + port.toElement().attribute("id"));
61 item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
62 if (port.toElement().attribute("flag") == "0")
63 {
64 item->setCheckState(Qt::Unchecked);
65 }
66 else
67 {
68 item->setCheckState(Qt::Checked);
69 }
70 ui->portlistWidget->addItem(item);
71 }
72 }
73 }
74 return;//完成部分显示后跳出遍历
75 }
76 }
77 }
78 }

xmlChanged()函数响应信号,获取item信息
_SelectChanged()函数根据pin,card读取XML进行界面的动态呈现,还是默认card、port的第一项为选中

到现在为止,我只进行了XML的读取(全部和选择部分),下面是进行XML的修改,这里我选择更改port的flag属性,默认为0,选中为1


 1 <?xml version=‘1.0‘ encoding=‘UTF-8‘?>
2 <information>
3 <pin id="1">
4 <card id="1">
5 <port id="1" flag="0"/>
6 <port id="2" flag="0"/>
7 <port id="3" flag="0"/>
8 <port id="4" flag="0"/>
9 <port id="5" flag="0"/>
10 <port id="6" flag="0"/>
11 <port id="7" flag="0"/>
12 </card>
13 <card id="2">
14 <port id="1" flag="0"/>
15 <port id="2" flag="0"/>
16 <port id="3" flag="0"/>
17 <port id="4" flag="0"/>
18 <port id="5" flag="0"/>
19 <port id="6" flag="0"/>
20 </card>
21 <card id="3">
22 <port id="1" flag="0"/>
23 <port id="2" flag="0"/>
24 <port id="3" flag="0"/>
25 <port id="4" flag="0"/>
26 <port id="5" flag="0"/>
27 </card>
28 </pin>
29 <pin id="2">
30 <card id="1">
31 <port id="1" flag="1"/>
32 <port id="2" flag="0"/>
33 <port id="3" flag="1"/>
34 <port id="4" flag="0"/>
35 <port id="5" flag="1"/>
36 <port id="6" flag="0"/>
37 <port id="7" flag="0"/>
38 </card>
39 <card id="2">
40 <port id="1" flag="0"/>
41 <port id="2" flag="0"/>
42 <port id="3" flag="0"/>
43 <port id="4" flag="0"/>
44 <port id="5" flag="0"/>
45 <port id="6" flag="0"/>
46 </card>
47 </pin>
48 </information>

pin2的card1中的一些端口flag状态已经改变

代码如下:


1 connect(ui->portlistWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(portSelected(QListWidgetItem*)));//点击端口


 1 void configure_win::portSelected(QListWidgetItem *item)
2 {
3 //qDebug()<<"&&&&&&&&&&&&&&&&&&&";
4 g_port = item->text();
5 if (item->checkState() == Qt::Checked)//添加
6 {
7 _linkUpdate(g_pin,g_card,g_port,1);//链路
8 _xmlUpdate(g_pin,g_card,g_port,1);//XML文件
9 }
10 else//删除
11 {
12 _linkUpdate(g_pin,g_card,g_port,0);;//链路
13 _xmlUpdate(g_pin,g_card,g_port,0);//XML文件
14 }
15 }


 1 /*
2 *函数名:_xmlUpdate
3 *功能:更新xml文件信息
4 *
5 */
6 void configure_win::_xmlUpdate(QString pin, QString card, QString port, int number)
7 {
8 //qDebug()<<i;
9 QDomDocument doc;
10 QDomAttr Flag = doc.createAttribute("flag");
11 QFile file("../project/ini/write.xml");
12 if (!file.open(QIODevice::ReadWrite))
13 {
14 return;
15 }
16 if (!doc.setContent(&file))
17 {
18 file.close();
19 return;
20 }
21 file.close();
22
23 QString strNumberPin = pin.right(1);
24 QString strTypePin = pin.left(pin.length() - 1);//去掉最后一位
25 QString strNumberCard = card.right(1);
26 QString strTypeCard = card.left(card.length() - 1);//去掉最后一位
27 QString strNumberPort = port.right(1);
28 QString strTypePort = port.left(port.length() - 1);//去掉最后一位port
29
30 QDomNodeList list = doc.elementsByTagName(strTypePin);//查找探针项
31 for (int i = 0;i < list.count();i++)
32 {
33 QDomElement e = list.at(i).toElement();
34 if (e.attribute("id") == strNumberPin)//找到对应的探针
35 {
36 //ui->cardlistWidget->clear();//清空板卡
37 QDomNodeList childCard = e.childNodes();
38 for (int j = 0;j < childCard.count();j++)//遍历板卡
39 {
40 QDomElement card = childCard.at(j).toElement();
41 //qDebug()<<" "<<qPrintable(card.tagName())<<qPrintable(card.attribute("id"));
42 if (card.attribute("id") == strNumberCard)
43 {
44 QDomNodeList childPort = card.childNodes();
45
46 for (int k = 0;k < childPort.count();k++)
47 {
48 QDomNode port = childPort.at(k);
49
50 if (port.toElement().attribute("id") == strNumberPort)
51 {
52 QString num = QString::number(number);
53 //qDebug()<<num;
54 port.toElement().setAttribute("flag",num); //把属性写入xml文件
55 goto _NEXT;
56 }
57 }
58 }
59 }
60 }
61 }
62 _NEXT:
63 QFile f("../project/ini/write.xml");
64 //if(!f.open(QIODevice::WriteOnly|QIODevice::Truncate))
65 if(!f.open(QIODevice::WriteOnly|QIODevice::Truncate))
66 {
67 return;
68 }
69 QTextStream out(&f);
70 doc.save(out,4);
71 f.close();
72 }

好了,我的XML操作到这里都实现了,最后我根据需要,添加了移除按钮的信息,也对XML中的port属性进行修改


1 connect(ui->linkWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(mylinkWidgetSelect(QListWidgetItem*)));//移除,禁用按钮可用


 1 /*
2 *槽函数名:on_removeBtn_clicked
3 *功能:单击移除按钮,移除选中端口
4 *
5 */
6 void configure_win::on_removeBtn_clicked()
7 {
8 QMessageBox msgBox;
9 msgBox.setWindowTitle(tr("提示"));
10 msgBox.setText(tr("确定要删除端口?"));
11 msgBox.setIcon(QMessageBox::Information);
12 msgBox.addButton(tr("确定(&Y)"),QMessageBox::YesRole);
13 msgBox.addButton(tr("取消(&N)"),QMessageBox::NoRole);
14 msgBox.setStyleSheet("background-color:grey");
15 int ret = msgBox.exec();
16 if (ret == 0)//删除端口
17 {
18 int row = ui->linkWidget->currentRow();
19 QString strlink = ui->linkWidget->item(row)->text();
20 QStringList listlink = strlink.split("->");
21 QString pin = listlink.at(0);
22 QString card = listlink.at(1);
23 QString port = listlink.at(2);
24 _xmlUpdate(pin,card,port,0);//更新xml文件
25 if (pin == g_pin && card == g_card)
26 {
27 for (int j =0;j < ui->portlistWidget->count();j++)
28 {
29 //qDebug()<<ui->portlistWidget->item(j)->text();
30 if (ui->portlistWidget->item(j)->text() == port)
31 {
32
33 ui->portlistWidget->item(j)->setCheckState(Qt::Unchecked);
34 break;
35 }
36 }
37 }
38 ui->linkWidget->takeItem(row);
39 }
40 }

忘了加一句,需要在.pro文件中添加QT += xml

这样才能使用XML的一些类

花了两天半的时间,终于把项目需要的一些对XML的操作搞定了



Qt XML的使用

时间: 2025-02-01 16:57:06

Qt XML的使用的相关文章

Qt XML读取写入操作

XML(eXtensible Markup Language,可扩展标记语言)是普通用于数据交换和数据存储的一种多用途文本文件格式: SVG(可标量矢量图形)XML格式,QtSvg模块提供了可用于载入并呈现SVG图像的类: MathML(数学标记语言)XML格式的绘制文档,可以使用Qt Solution中的QtMmlWidget操作: 对于一般的XML数据处理,Qt提供了QtXml模块,QtXml提供了三种不同的应用程序接口来读取XML文档: 1.QXmlStreamReader 用于读取格式良

QT xml 读写

最近用QT在做一个项目,需要存储设备信息. deviceInfo.h文件: #include <QWidget>#include <QtCore> #include <QString> #include <QFile> #include <QVector> #include <QtXml/QDomDocument> #include <QtXml/QDomNodeList> #include <QtXml/QDomE

Qt中对XML的处理方式

XML(eXtensible Markup Language,可扩展标记语言)是普通用于数据交换和数据存储的一种多用途文本文件格式: SVG(可标量矢量图形)XML格式,QtSvg模块提供了可用于载入并呈现SVG图像的类: MathML(数学标记语言)XML格式的绘制文档,可以使用Qt Solution中的QtMmlWidget操作: 对于一般的XML数据处理,Qt提供了QtXml模块,QtXml提供了三种不同的应用程序接口来读取XML文档: 1.QXmlStreamReader 用于读取格式良

QT开发(四十一)——XML文件解析基础

QT开发(四十一)--XML文件解析基础 一.XML文档简介 XML(Extensible Markup Language,可扩展标记语言),是一种通用的文本格式,被广泛运用于数据交换和数据存储,而不是显示数据.XML的标签没有被预定义,用户需要在使用时自行进行定义.XML是W3C(万维网联盟)的推荐标准.相对于数据库表格的二维表示,XML使用的树形结构更能表现出数据的包含关系,作为一种文本文件格式,XML简单明了的特性使得它在信息存储和描述领域非常流行. <?xml version="1

QXmlStreamReader/QXmlStreamWriter实现Qt下xml文件读写

版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QXmlStreamReader/QXmlStreamWriter实现Qt下xml文件读写     本文地址:http://techieliang.com/2017/12/714/ 文章目录 1. 介绍  1.1. QXml-Token标记类型  1.2. 范例xml文件 2. 写xml 3. 读xml  3.1. 其他 1. 介绍 帮助文档:QXmlStreamReader.QXmlStr

Qt中三种解析xml的方式

在下面的随笔中,我会根据xml的结构,给出Qt中解析这个xml的三种方式的代码.虽然,这个代码时通过调用Qt的函数实现的,但是,很多开源的C++解析xml的库,甚至很多其他语言解析xml的库,都和下面三种解析xml采用相同的原理,所以就算你不是学习qt,也可以大致参看一下代码,对三种解析方式有一种大致的感觉. 先给出xml如下: <?xml version="1.0" encoding="utf-8"?> <school> <teach

Qt的Xml操作QDomDocument

Qt对于Xml的支持是很好的,一些我们需要的操作应有尽有,下面简单介绍一下怎样使用.主要有以下几点使用: 写xml到文件 读xml 添加节点到xml 删除xml中某节点信息 修改xml中某节点信息 准备工作 .pro加入QT += xml 需要include QDomDocument QTextStream QFile三个头文件 直接上代码 WriteXml 1 void writeXml() 2 { 3 QDomDocument doc; 4 QDomProcessingInstruction

Qt项目管理(33个规则)

2016-06-20 花莫弦 小小杂货铺LY 一.qmake的介绍 qmake是Trolltech公司创建的用来为不同的平台和编译器书写Makefile的工具. 手写Makefile是比较困难并且容易出错的,尤其是需要给不同的平台和编译器组合写几个Makefile.使用qmake,开发者创建一个简单的“项目”文件并且运行qmake生成适当的Makefile.qmake会注意所有的编译器和平台的依赖性,可以把开发者解放出来只关心他们的代码.Trolltech公司使用qmake作为Qt库和Qt所提供

DOM解析xml实现读、写、增、删、改

qt提供了三种方式解析xml,不过如果想实现对xml文件进行增.删.改等操作,还是DOM方式最方便. 项目配置 pro文件里面添加QT+=xml include <QtXml>,也可以include <QDomDocument> pro文件: [plain] view plain copy print? QT       += core xml QT       -= gui TARGET = xmltest CONFIG   += console CONFIG   -= app_