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

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

实现界面

编写的XML文件

 <?xml version="1.0" encoding="UTF-8"?>
<information>
<pin id="">
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
</pin>
<pin id="">
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
</pin>
</information>

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

首先是编写XML文件

代码如下:

 void xml::writeXML()
{
QFile file("../project/ini/write.xml");
if(!file.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
return;
}
QDomDocument doc;
QDomProcessingInstruction instruction; instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
QDomElement root=doc.createElement(tr("information"));
doc.appendChild(root); QDomElement Pin;
QDomElement Card;
QDomElement Port;
QDomAttr ID = doc.createAttribute("id");
QDomAttr Flag = doc.createAttribute("flag");
//QDomText text; for (int i = ;i < ;i++)
{
Pin = doc.createElement(tr("pin")); ID = doc.createAttribute("id");
ID.setValue(tr("%1").arg(i));
Pin.setAttributeNode(ID); //Pin.appendChild(Card);
//Card = doc.createElement(tr("card"));
for (int j = ;j < - i;j++)
{
Card = doc.createElement(tr("card")); ID = doc.createAttribute("id");
ID.setValue(tr("%1").arg(j));
Card.setAttributeNode(ID); for (int k = ;k < - j;k++)
{
Port = doc.createElement(tr("port")); ID = doc.createAttribute("id");
ID.setValue(tr("%1").arg(k));
Port.setAttributeNode(ID);
Flag = doc.createAttribute("flag");
Flag.setValue("");
Port.setAttributeNode(Flag); Card.appendChild(Port);
}
Pin.appendChild(Card);
}
root.appendChild(Pin);
} QTextStream out(&file);
doc.save(out,);
file.close();
}

QDomProcessingInstruction instruction;

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

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

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

好了,现在有我们需要操作的XML文件了,下一步就是就是进行读取,并在界面上显示
我是采用三个listWidget分别显示pin card port信息的
代码如下:
 /*
*函数名:_CreateListWidget
*功能:初始化探针、板卡、端口信息
*
*/
void configure_win::_CreateListWidget()
{
ui->cardlistWidget->clear();
ui->portlistWidget->clear();
ui->pinlistWidget->clear();
int flag_card = ;
int flag_port = ;//判断标识,确定listWidget初始化显示一次
QDomDocument doc;
QFile file("../project/ini/write.xml");
if (!file.open(QIODevice::ReadOnly))
{
return;
}
if (!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement docElem = doc.documentElement();
QDomNode n = docElem.firstChild();
while (!n.isNull())
{
if (n.isElement())
{
QDomElement e = n.toElement();
ui->pinlistWidget->addItem(e.toElement().tagName()+e.toElement().attribute("id"));
//ui->pinlistWidget->addItem("探针"+e.toElement().attribute("id"));
QDomNodeList listcard = e.childNodes();
if (flag_card)
{
for (int i = ;i < listcard.count();i++)
{
QDomNode node = listcard.at(i);
if (node.isElement())
{
ui->cardlistWidget->addItem(node.toElement().tagName()+node.toElement().attribute("id"));
//ui->cardlistWidget->addItem("板卡"+node.toElement().attribute("id"));
QDomNodeList listport = node.childNodes();
if (flag_port)
{ for (int j = ;j < listport.count();j++)
{
QDomNode port = listport.at(j);
if (port.isElement())
{
QListWidgetItem *item = new QListWidgetItem;
item->setText(port.toElement().tagName() + port.toElement().attribute("id"));
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
ui->portlistWidget->addItem(item);
//ui->portlistWidget->addItem(port.toElement().tagName() + port.toElement().attribute("id"));
//ui->portlistWidget->addItem("端口" + port.toElement().attribute("id"));
}
}
}
flag_port = ;
}
node = node.nextSibling();
}
}
flag_card = ;
}
n = n.nextSibling();
}
ui->pinlistWidget->item()->setSelected(true);
ui->cardlistWidget->item()->setSelected(true);
g_pin = ui->pinlistWidget->item()->text();//初始化存储pin card port
g_card = ui->cardlistWidget->item()->text();
g_port = ui->portlistWidget->item()->text();
}

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

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

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

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

代码如下:

 /*
*槽函数名:xmlChanged
*功能:根据选择读取xml信息
*
*/
void configure_win::xmlChanged(QListWidgetItem *item)
{
QString str = item->text();
QString str2 = str.right();//取最后一位1
QString str1 = str.left(str.length() - );//去掉最后一位 card
if (str1 == "pin")//点击pin
{
g_pin = str;//选中的pin改变
g_card = "card1";//默认card1
g_port = "port1";
_SelectChanged(str,"card1");
ui->cardlistWidget->item()->setSelected(true);
}
else if (str1 == "card")//点击card
{
g_card = str;//选中的card改变
g_port = "port1";
QString strpin;
if (ui->pinlistWidget->currentRow() == -)//获得选中card对应探针????初始化pin第一项pin为选中,为什么返回-1而不是0
{
strpin = ui->pinlistWidget->item()->text();
}
else
{
strpin = ui->pinlistWidget->currentItem()->text();
}
int i = ui->cardlistWidget->currentRow();//获取选中card项
_SelectChanged(strpin,str);//更新listWidget
ui->cardlistWidget->item(i)->setSelected(true);//重新设置card为选中
}
}
 /*
*函数名:_SelectChanged
*功能:更新探针、板卡、端口信息
*
*/
void configure_win::_SelectChanged(QString str1, QString str2)
{ QDomDocument doc;
QFile file("../project/ini/write.xml");
if (!file.open(QIODevice::ReadOnly))
{
return;
}
if (!doc.setContent(&file))
{
file.close();
return;
}
file.close(); //QString str = item->text();
//qDebug()<<str1;
QString strNumberPin = str1.right();
QString strTypePin = str1.left(str1.length() - );//去掉最后一位
QString strNumberCard = str2.right();
QString strTypeCard = str2.left(str1.length() - );//去掉最后一位
//qDebug()<<strNumberPin<<strTypePin<<strNumberCard<<"\n"<<strTypeCard;
//if (i)//点击板卡
{
QDomNodeList list = doc.elementsByTagName(strTypePin);//查找探针项
for (int i = ;i < list.count();i++)
{
QDomElement e = list.at(i).toElement();
if (e.attribute("id") == strNumberPin)//找到对应的探针
{
ui->cardlistWidget->clear();//清空板卡
QDomNodeList childCard = e.childNodes();
for (int j = ;j < childCard.count();j++)//遍历板卡
{
QDomElement card = childCard.at(j).toElement();
//QDomNode port = childCard.at(j);
//qDebug()<<" "<<qPrintable(card.tagName())<<qPrintable(card.attribute("id"));
QListWidgetItem *item = new QListWidgetItem;
item->setText(card.tagName() + card.attribute("id")); //item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
//item->setCheckState(Qt::Unchecked);
ui->cardlistWidget->addItem(item);
if (card.attribute("id") == strNumberCard)
{
ui->portlistWidget->clear();//清空端口
QDomNodeList childPort = card.childNodes(); for (int k = ;k < childPort.count();k++)
{
QDomNode port = childPort.at(k);
//qDebug()<<" "<<qPrintable(port.toElement().tagName())<<qPrintable(port.toElement().attribute("id"));
QListWidgetItem *item = new QListWidgetItem;
item->setText(port.toElement().tagName() + port.toElement().attribute("id"));
item->setFlags(Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsUserCheckable);
if (port.toElement().attribute("flag") == "")
{
item->setCheckState(Qt::Unchecked);
}
else
{
item->setCheckState(Qt::Checked);
}
ui->portlistWidget->addItem(item);
}
}
}
return;//完成部分显示后跳出遍历
}
}
}
}
xmlChanged()函数响应信号,获取item信息
_SelectChanged()函数根据pin,card读取XML进行界面的动态呈现,还是默认card、port的第一项为选中

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

 <?xml version='1.0' encoding='UTF-8'?>
<information>
<pin id="">
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
</pin>
<pin id="">
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
<card id="">
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
<port id="" flag=""/>
</card>
</pin>
</information>

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

代码如下:
 connect(ui->portlistWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(portSelected(QListWidgetItem*)));//点击端口
 void configure_win::portSelected(QListWidgetItem *item)
{
//qDebug()<<"&&&&&&&&&&&&&&&&&&&";
g_port = item->text();
if (item->checkState() == Qt::Checked)//添加
{
_linkUpdate(g_pin,g_card,g_port,);//链路
_xmlUpdate(g_pin,g_card,g_port,);//XML文件
}
else//删除
{
_linkUpdate(g_pin,g_card,g_port,);;//链路
_xmlUpdate(g_pin,g_card,g_port,);//XML文件
}
}
 /*
*函数名:_xmlUpdate
*功能:更新xml文件信息
*
*/
void configure_win::_xmlUpdate(QString pin, QString card, QString port, int number)
{
//qDebug()<<i;
QDomDocument doc;
QDomAttr Flag = doc.createAttribute("flag");
QFile file("../project/ini/write.xml");
if (!file.open(QIODevice::ReadWrite))
{
return;
}
if (!doc.setContent(&file))
{
file.close();
return;
}
file.close(); QString strNumberPin = pin.right();
QString strTypePin = pin.left(pin.length() - );//去掉最后一位
QString strNumberCard = card.right();
QString strTypeCard = card.left(card.length() - );//去掉最后一位
QString strNumberPort = port.right();
QString strTypePort = port.left(port.length() - );//去掉最后一位port QDomNodeList list = doc.elementsByTagName(strTypePin);//查找探针项
for (int i = ;i < list.count();i++)
{
QDomElement e = list.at(i).toElement();
if (e.attribute("id") == strNumberPin)//找到对应的探针
{
//ui->cardlistWidget->clear();//清空板卡
QDomNodeList childCard = e.childNodes();
for (int j = ;j < childCard.count();j++)//遍历板卡
{
QDomElement card = childCard.at(j).toElement();
//qDebug()<<" "<<qPrintable(card.tagName())<<qPrintable(card.attribute("id"));
if (card.attribute("id") == strNumberCard)
{
QDomNodeList childPort = card.childNodes(); for (int k = ;k < childPort.count();k++)
{
QDomNode port = childPort.at(k); if (port.toElement().attribute("id") == strNumberPort)
{
QString num = QString::number(number);
//qDebug()<<num;
port.toElement().setAttribute("flag",num); //把属性写入xml文件
goto _NEXT;
}
}
}
}
}
}
_NEXT:
QFile f("../project/ini/write.xml");
//if(!f.open(QIODevice::WriteOnly|QIODevice::Truncate))
if(!f.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
return;
}
QTextStream out(&f);
doc.save(out,);
f.close();
}

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

 connect(ui->linkWidget,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(mylinkWidgetSelect(QListWidgetItem*)));//移除,禁用按钮可用
 /*
*槽函数名:on_removeBtn_clicked
*功能:单击移除按钮,移除选中端口
*
*/
void configure_win::on_removeBtn_clicked()
{
QMessageBox msgBox;
msgBox.setWindowTitle(tr("提示"));
msgBox.setText(tr("确定要删除端口?"));
msgBox.setIcon(QMessageBox::Information);
msgBox.addButton(tr("确定(&Y)"),QMessageBox::YesRole);
msgBox.addButton(tr("取消(&N)"),QMessageBox::NoRole);
msgBox.setStyleSheet("background-color:grey");
int ret = msgBox.exec();
if (ret == )//删除端口
{
int row = ui->linkWidget->currentRow();
QString strlink = ui->linkWidget->item(row)->text();
QStringList listlink = strlink.split("->");
QString pin = listlink.at();
QString card = listlink.at();
QString port = listlink.at();
_xmlUpdate(pin,card,port,);//更新xml文件
if (pin == g_pin && card == g_card)
{
for (int j =;j < ui->portlistWidget->count();j++)
{
//qDebug()<<ui->portlistWidget->item(j)->text();
if (ui->portlistWidget->item(j)->text() == port)
{ ui->portlistWidget->item(j)->setCheckState(Qt::Unchecked);
break;
}
}
}
ui->linkWidget->takeItem(row);
}
}

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

这样才能使用XML的一些类

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


Qt XML的使用的更多相关文章

  1. Qt XML读取写入操作

    XML(eXtensible Markup Language,可扩展标记语言)是普通用于数据交换和数据存储的一种多用途文本文件格式: SVG(可标量矢量图形)XML格式,QtSvg模块提供了可用于载入 ...

  2. QT XML文档的解析 QXmlStreamReader, DOM,SAX 三种解析方法 简单示例

    0. xml文档如下 <?xml version="1.0"?> <bookindex> <entry term="sidebearings ...

  3. Qt Xml Dom

    //Dom方式更改节点信息 bool XmlTools::SetValue(QString name,float exposure,float gain,float gamma,int brightn ...

  4. 39.Qt XML

    1.使用QXmlStreamReader读取XML,可以读取内存中容纳不了的特大文件,或者读取在XML文档中定制的文档的内容. xml文件(in1.xml) <?xml version=&quo ...

  5. Qt中三种解析xml的方式

    在下面的随笔中,我会根据xml的结构,给出Qt中解析这个xml的三种方式的代码.虽然,这个代码时通过调用Qt的函数实现的,但是,很多开源的C++解析xml的库,甚至很多其他语言解析xml的库,都和下面 ...

  6. Qt中使用DOM解析XML文件或者字符串二(实例)

    介绍 在Qt中提供了QtXml模块实现了对XML数据的处理,我们在Qt帮助中输入关键字QtXml Module,可以看到该模块的类表.在这里我们可以看到所有相关的类,它们主要是服务于两种操作XML文档 ...

  7. Qt中使用DOM解析XML文件或者字符串(实例)

    因为需要读取配置文件,我的配置文件采用xml:因此编写了使用qt读取xml文件内容的代码,xml文件如下: <?xml version="1.0" encoding=&quo ...

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

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QXmlStreamReader/QXmlStreamWriter实现Qt下xml文件读写   ...

  9. Qt 学习之路 2(60):使用 DOM 处理 XML

    Qt 学习之路 2(60):使用 DOM 处理 XML  豆子  2013年8月3日  Qt 学习之路 2  9条评论 DOM 是由 W3C 提出的一种处理 XML 文档的标准接口.Qt 实现了 DO ...

随机推荐

  1. Linux IIO子系统分析

    最近稍微看了下LKML,发现里面有一个子系统叫做“IIO”.以前没有接触过,所以Google了下.     IIO子系统全称是 Industrial I/O subsystem(工业 I/O 子系统) ...

  2. HTC仅限拨打紧急电话

    问题描述: 我手上有台 HTC One V 没碰没撞,突然打不出电话,信号上显示一个叉,屏幕上显示“仅限拨打紧急电话” 解决办法:经百度,原来很多HTC机子都有这种情况,幸好不是硬件坏了,只需按以下步 ...

  3. Ubuntu 如何使用apt命令安装、升级、卸载软件

    apt-get是一条linux命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索.安装.升级.卸载软件或操作系统. apt-get命令一般需要root权限执行,所以一般跟着su ...

  4. Eclipse编译ijkplayer

    参考链接:http://blog.csdn.net/fatiao101/article/details/49586379

  5. Java-String之寻根问底

    Java-String之寻根问底 引言 在java编程中,几乎每天都会跟String打交道,因此,深入理解String及其用法十分有必要.下面分三方面来详细说明下String相关的特点及用法 •Imm ...

  6. 【转】谁说Vim不是IDE?(一)

    谁说Vim不是IDE?(一)   话说操作系统.编程语言和编辑器似乎是程序员永恒的吐槽话题,技术发展了几十年,大家讨论起这几个“之争”还是充满愤怒.津津乐道.有人描述过Emacs和VI程序员,大家沿着 ...

  7. linux内核--内核内存管理

    如题目所示,为什么要称作“内核内存管理”,因为内核所需要的内存和用户态所需要的内存,这两者在管理上是不一样的. 这篇文章描述内核的内存管理,用户态的内存管理在以后的文章中讲述. 首先简单的说明一下下面 ...

  8. myeclipse输入“.”后没有自动提示功能

    今天和室友安装了一样的myeclipse版本,结果室友的自动提示功能有,我的输入"."后却不能提示,这对我们敲代码简直来说是一个折磨,不能自动提示,本来还以为是系统问题,一个是wi ...

  9. Android开发艺术探索(一)——Activity的生命周期和启动模式

    Activity的生命周期和启动模式 生命周期有? 1.典型情况下的生命周期—>指有用户参与的情况下,Activity所经过的生命周期改变 2.异常情况下的生命周期—>指Activity被 ...

  10. docker学习资料整理(持续更新中..)

    docker最近可以说火得一踏糊涂,跟 51大神在交流技术的时候这个东西会多次被提到,当我们还玩vm+linux/freebsd的时候,人家已经上升到更高层次了,这就是差距,感觉好高大上的样子,技术之 ...