QT中关于XML的增删改查

学习记录

使用QDomDocument读取xml   
QtWidgets 是系统弹窗需要头文件         

包含的头文件:

#include <QtXml>
#include <QDomDocument>
#include <QtWidgets>

1.创建:

void XmlStudy::Creat()
{
	//相对路径
	QFile file(qApp->applicationDirPath() + "/xml/" + "999.xml");
	// 文件存在则创建,否则创建一个文件
	if (!file.open(QFileDevice::ReadWrite | QFileDevice::Truncate)) {
		QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("文件打开或创建失败!"));
		return;
	}

	QDomDocument doc;
	QDomProcessingInstruction instruction;

	// 创建XML头部格式
	instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");

	// 添加到XML文件中
	doc.appendChild(instruction);

	//创建根节点  
	QDomElement Node_Root = doc.createElement(QStringLiteral("中国"));
	doc.appendChild(Node_Root);//   appendChild()  绑定关系:doc的下一层为root

	// 给根节点创建属性 可选择是否添加
	Node_Root.setAttribute(QStringLiteral("标签"), QStringLiteral("Number One"));

	{//创建一级节点1
		QDomElement Node_FirstLevel_1 = doc.createElement(QStringLiteral("河南省"));
		Node_Root.appendChild(Node_FirstLevel_1);

		// 给一级节点创建属性 可选择是否添加
		Node_FirstLevel_1.setAttribute(QStringLiteral("人口"), QStringLiteral("1000万人"));// 参数一是字符串,参数二可以是任何类型
		Node_FirstLevel_1.setAttribute(QStringLiteral("GTP"), QStringLiteral("100000亿元"));
		Node_FirstLevel_1.setAttribute(QStringLiteral("ID"), 1);

		// 给一级节点添加子元素1
		QDomElement Element_1 = doc.createElement(QStringLiteral("郑州"));
		Node_FirstLevel_1.appendChild(Element_1);
		// 设置子元素1的值
		QDomText text = doc.createTextNode("1");
		Element_1.appendChild(text);

		// 添加子元素2
		QDomElement Element_2 = doc.createElement(QStringLiteral("周口"));
		Node_FirstLevel_1.appendChild(Element_2);
		QDomText text2 = doc.createTextNode("2");
		Element_2.appendChild(text2);
	}
    
	{
		//创建一级节点2
		QDomElement Node_FirstLevel_2 = doc.createElement(QStringLiteral("河北省"));
		Node_Root.appendChild(Node_FirstLevel_2);

		// 给一级节点创建属性 可选择是否添加
		Node_FirstLevel_2.setAttribute(QStringLiteral("人口"), QStringLiteral("1000万人"));
		Node_FirstLevel_2.setAttribute(QStringLiteral("GTP"), QStringLiteral("100000亿元"));
		Node_FirstLevel_2.setAttribute(QStringLiteral("ID"), 2);

		// 给一级节点添加子元素1
		QDomElement Element_1 = doc.createElement(QStringLiteral("石家庄"));
		Node_FirstLevel_2.appendChild(Element_1);
		// 设置子元素1的值
		QDomText text = doc.createTextNode("1");
		Element_1.appendChild(text);

		// 添加子元素2
		QDomElement Element_2 = doc.createElement(QStringLiteral("邯郸"));
		Node_FirstLevel_2.appendChild(Element_2);
		QDomText text2 = doc.createTextNode("2");
		Element_2.appendChild(text2);
	}

	//保存
	QTextStream stream(&file);
	doc.save(stream, 4);

	file.close();
}

生成的xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<中国 标签="Number One">
    <河南省 GTP="100000亿元" ID="1" 人口="1000万人">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 GTP="100000亿元" ID="2" 人口="1000万人">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
</中国>

2.增加

void XmlStudy::Add()
{
	QFile file(qApp->applicationDirPath() + "/xml/" + "999.xml");
	if (!file.open(QFileDevice::ReadOnly)) {
		QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("文件打开失败!"));
		return;
	}

	QDomDocument doc;

	//读取XML文档
	if (!doc.setContent(&file)) {
		QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("操作的文件不是XML文件!"));
		file.close();
		return;
	}
	file.close();

	// 获取根节点
	QDomElement Node_Root = doc.documentElement();

	// 在原基础上添加一级节点3
	QDomElement Node_FirstLevel_3 = doc.createElement(QStringLiteral("四川省"));
	Node_Root.appendChild(Node_FirstLevel_3);

	Node_FirstLevel_3.setAttribute(QStringLiteral("人口"), QStringLiteral("1000万人"));
	Node_FirstLevel_3.setAttribute(QStringLiteral("GTP"), QStringLiteral("100000亿元"));
	Node_FirstLevel_3.setAttribute(QStringLiteral("ID"), 3);

	// 创建二级节点1
	QDomElement Element_1 = doc.createElement(QStringLiteral("成都"));
	QDomText text = doc.createTextNode("1");
	Element_1.appendChild(text);
	Node_FirstLevel_3.appendChild(Element_1);
	QDomElement Element_2 = doc.createElement(QStringLiteral("绵阳"));
	text = doc.createTextNode("2");
	Element_2.appendChild(text);
	Node_FirstLevel_3.appendChild(Element_2);
	
	if (!file.open(QFileDevice::WriteOnly | QFileDevice::Truncate)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	// 输出到文件
	QTextStream stream(&file);
	doc.save(stream, 4);	// 缩进4格
	file.close();
}

增加四川省节点后的xml如下:

<?xml version='1.0' encoding='UTF-8'?>
<中国 标签="Number One">
    <河南省 ID="1" GTP="100000亿元" 人口="1000万人">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 ID="2" GTP="100000亿元" 人口="1000万人">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
    <四川省 ID="3" GTP="100000亿元" 人口="1000万人">
        <成都>1</成都>
        <绵阳>2</绵阳>
    </四川省>
</中国>

3.删除

void XmlStudy::Delete()
{
	QFile file(qApp->applicationDirPath() + "/xml/" + "999.xml");
	if (!file.open(QFileDevice::ReadOnly)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	QDomDocument doc;
	if (!doc.setContent(&file)) {
		QMessageBox::information(NULL, "提示", "操作的文件不是XML文件!");
		file.close();
		return;
	}
	file.close();


	// 获得根节点
	QDomElement Node_Root = doc.documentElement();

	{
		// 获取一级节点名字为 一级节点3 的所有节点
		QDomNodeList list = doc.elementsByTagName(QStringLiteral("四川省"));
		int size = list.count();
		for (int i = 0; i < list.count(); i++) {
			// 获取节点
			QDomElement element = list.at(i).toElement();

			if (element.attribute(QStringLiteral("ID")) == "3") {    //这里判断一下ID的目的是   为了防止有多个名字为 四川省 的一级节点    做区分 删除对应id的四川省
				{
					//删除节点的子元素
					QDomNode node = element.namedItem(QStringLiteral("成都"));
					element.removeChild(node);
				}
				//{
					//删除此节点的全部信息
					//Node_Root.removeChild(list.at(i));
				//}

				//{
					//删除节点的属性
					//element.removeAttribute(QStringLiteral("人口"));
				//}
			}
		}
	}

	if (!file.open(QFileDevice::WriteOnly | QFileDevice::Truncate)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	// 输出到文件
	QTextStream stream(&file);
	doc.save(stream, 4);
	file.close();
}

删除四川省下的成都值      (删除节点属性 见代码里的注释)

删除前xml:

<?xml version='1.0' encoding='UTF-8'?>
<中国 标签="Number One">
    <河南省 ID="1" GTP="100000亿元" 人口="1000万人">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 ID="2" GTP="100000亿元" 人口="1000万人">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
    <四川省 ID="3" GTP="100000亿元" 人口="1000万人">
        <成都>1</成都>
        <绵阳>2</绵阳>
    </四川省>
</中国>

删除后:

<?xml version='1.0' encoding='UTF-8'?>
<中国 标签="Number One">
    <河南省 GTP="100000亿元" 人口="1000万人" ID="1">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 GTP="100000亿元" 人口="1000万人" ID="2">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
    <四川省 GTP="100000亿元" 人口="1000万人" ID="3">
        <绵阳>2</绵阳>
    </四川省>
</中国>

4.修改

void XmlStudy::Ament()
{
	QFile file(qApp->applicationDirPath() + "/xml/" + "999.xml");
	if (!file.open(QFileDevice::ReadOnly)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	QDomDocument doc;
	if (!doc.setContent(&file)) {
		QMessageBox::information(NULL, "提示", "操作的文件不是XML文件!");
		file.close();
		return;
	}
	file.close();

	// 获得根节点
	QDomElement Node_Root = doc.documentElement();

	// 获取所有Book1节点
	QDomNodeList list = Node_Root.elementsByTagName(QStringLiteral("四川省"));

	{
		/* 修改属性的值 */
		for (int i = 0; i < list.size(); i++) {
			QDomElement element = list.at(i).toElement();

			// 找到ID等于2的节点
			if (element.attribute("ID") == "3") {
				// 修改属性值
				element.setAttribute("GTP", 200000);
				break;
			}
		}
	}

	{
		/* 修改尖括号之间的值 */
		for (int i = 0; i < list.size(); i++) {
			QDomElement element = list.at(i).toElement();
			if (element.attribute("ID") == "3") {
				// 获得子节点
				QDomNode node = element.namedItem(QStringLiteral("成都"));
				node.firstChild().setNodeValue("999");
				break;
			}
		}
	}

	if (!file.open(QFileDevice::WriteOnly | QFileDevice::Truncate)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	// 输出到文件
	QTextStream stream(&file);
	doc.save(stream, 4);
	file.close();
}

将四川省 GTP修改为200000亿元   将成都值修改为999

修改前:

<?xml version='1.0' encoding='UTF-8'?>
<中国 标签="Number One">
    <河南省 ID="1" GTP="100000亿元" 人口="1000万人">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 ID="2" GTP="100000亿元" 人口="1000万人">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
    <四川省 ID="3" GTP="100000亿元" 人口="1000万人">
        <成都>1</成都>
        <绵阳>2</绵阳>
    </四川省>
</中国>

修改后:

<?xml version='1.0' encoding='UTF-8'?>
<中国 标签="Number One">
    <河南省 ID="1" GTP="100000亿元" 人口="1000万人">
        <郑州>1</郑州>
        <周口>2</周口>
    </河南省>
    <河北省 ID="2" GTP="100000亿元" 人口="1000万人">
        <石家庄>1</石家庄>
        <邯郸>2</邯郸>
    </河北省>
    <四川省 ID="3" GTP="200000" 人口="1000万人">
        <成都>999</成都>
        <绵阳>2</绵阳>
    </四川省>
</中国>

5.查找

void XmlStudy::Find()
{
	QFile file(qApp->applicationDirPath() + "/xml/" + "999.xml");
	if (!file.open(QFileDevice::ReadOnly)) {
		QMessageBox::information(NULL, "提示", "文件打开失败!");
		return;
	}

	QDomDocument doc;
	if (!doc.setContent(&file)) {
		QMessageBox::information(NULL, "提示", "操作的文件不是XML文件!");
		file.close();
		return;
	}

	// 获得根节点
	QDomElement Node_Root = doc.documentElement();
	qDebug() << QStringLiteral("根节点:") << Node_Root.nodeName();

	// 获取所有Book1节点
	QDomNodeList list = Node_Root.elementsByTagName(QStringLiteral("四川省"));


	/* 获取属性中的值 */
	for (int i = 0; i < list.count(); i++) {
		QDomElement element = list.at(i).toElement();
		qDebug() << QStringLiteral("子节点:") << element.nodeName();
		qDebug() << QStringLiteral("ID:") << element.attribute("ID");
		qDebug() << QStringLiteral("人口") << element.attribute(QStringLiteral("人口"));
		qDebug() << QStringLiteral("GTP") << element.attribute(QStringLiteral("GTP"));

	}

	// 获取节点子元素的值 
	for (int i = 0; i < list.count(); i++) {
		QDomElement element = list.at(i).toElement();

		// 找到需要读取的节点
		QDomNode note1 = element.namedItem(QStringLiteral("成都"));
		QDomNode note2 = element.namedItem(QStringLiteral("绵阳"));
		qDebug() << QStringLiteral("成都 的值为:") << note1.firstChild().nodeValue();
		qDebug() << QStringLiteral("绵阳 的值为:") << note2.firstChild().nodeValue();

		// 使用childNodes方法获取所有子节点
		//QDomNodeList nodeList = element.childNodes();
		//qDebug() << nodeList.at(0).firstChild().nodeValue();
		//qDebug() << nodeList.at(1).firstChild().nodeValue();

	}


	file.close();

}

qDebug()输出为:

"根节点:" "中国"
"子节点:" "四川省"
"ID:" "3"
"人口" "1000万人"
"GTP" "200000"
"成都 的值为:" "999"
"绵阳 的值为:" "2"

6.生成的XML  节点中属性会随机乱序问题

xml的Attribute属性是无关排序的,怎么排都一样,对于解析没有影响。

不过可以通过锁定哈希,设定固定的随机数种子来确保在特定机器上保存的属性顺序一致。

但是,由于不同机器的随机数种子不同,这种方法在不同设备间无法保证属性顺序的一致性

方法:

extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed;//这句放在头文件后面

qt_qhash_seed.store(0);//这句放在对于xml文件操作之前

亲测有效

另外,QXmlStreamWriter可以按照开发者的意愿任意排序元素属性的顺序。若生成的xml文件主要给人阅读,那么推荐使用QXmlStreamWriter方式。

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值