抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

最近,学习了Qt C++对XML的一系列操作。今天,把相关代码和注释贴在这里, 以备后续使用。

什么是 XML

可扩展标记语言(英语:Extensible Markup Language,简称:XML)是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。

——from Wikipedia

Qt 如何操作 XML

.pro 文件

增加 QT += xml模块。

.cpp 文件

头部 #include <QtXml>

写入 XML

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
void Widget::write_xml()
{
// 打开或创建文件
QFile file("test.xml"); //相对路径、绝对路径、资源路径都可以
if(!file.open(QFile::WriteOnly | QFile::Truncate))
return;
QDomDocument doc;

// 写入XML头部
QDomProcessingInstruction instruction;//添加处理命令
instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);

// 添加根节点
QDomElement root = doc.createElement("library");
doc.appendChild(root);

// 添加第一个子节点及其元素
QDomElement book = doc.createElement("book");
book.setAttribute("id", 1); // 方式一:创建属性 其中键值对的值可以是各种类型
QDomAttr time = doc.createAttribute("time");
time.setValue("2020/08/11"); // 方式二:创建属性 值必须是字符串
book.setAttributeNode(time);

QDomElement title = doc.createElement("title"); // 创建子元素
QDomText text; // 设置括号标签中间的值
text = doc.createTextNode("C++ primer");
book.appendChild(title);
title.appendChild(text);

QDomElement author = doc.createElement("author"); // 创建子元素
text = doc.createTextNode("Stanley Lippman");
author.appendChild(text);
book.appendChild(author);
root.appendChild(book);

QDomElement price = doc.createElement("price");
text = doc.createTextNode("$29.9");
price.appendChild(text);
book.appendChild(price);
root.appendChild(book);


// 添加第二个子节点及其子元素,部分变量只需重新赋值
book = doc.createElement("book");
book.setAttribute("id", 2);
time = doc.createAttribute("time");
time.setValue("2020/08/10");
book.setAttributeNode(time);
title = doc.createElement("title");
text = doc.createTextNode("Thinking in Java");
book.appendChild(title);
title.appendChild(text);
author = doc.createElement("author");
text = doc.createTextNode("Bruce Eckel");
author.appendChild(text);
book.appendChild(author);
root.appendChild(book);

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

调试结果 test.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book time="2020/08/11" id="1">
<title>C++ primer</title>
<author>Stanley Lippman</author>
<price>$29.9</price>
</book>
<book time="2020/08/10" id="2">
<title>Thinking in Java</title>
<author>Bruce Eckel</author>
</book>
</library>
读取 XML

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void Widget::read_xml()
{
// 打开或创建文件
QFile file("test.xml"); // 相对路径、绝对路径、资源路径
if(!file.open(QFile::ReadOnly))
{
return;
}

QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();

QDomElement root = doc.documentElement(); // 返回根节点
qDebug() << root.nodeName();
QDomNode node = root.firstChild();
while(!node.isNull()) // 如果节点不空
{
if(node.isElement())
{
// 转换为元素,注意元素和节点是两个数据结构
QDomElement e = node.toElement();
// 打印键值对,tagName和nodeName是一个东西
qDebug() << e.tagName() << " " << e.attribute("id") << " " << e.attribute("time");
QDomNodeList list = e.childNodes();
// 遍历子元素,count和size都可以使用,可用于标签数计数
for (int i = 0; i < list.count(); i++)
{
QDomNode n = list.at(i);
if(node.isElement())
{
qDebug() << n.nodeName() << ":" << n.toElement().text();
}
}
}
node = node.nextSibling();
}
}
增加 XML 内容

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 增加XML内容
void Widget::add_xml()
{
// 打开文件
QFile file("test.xml"); // 相对路径、绝对路径、资源路径都可以
if(!file.open(QFile::ReadOnly))
{
return;
}

// 增加一个以及子节点以及元素
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();

QDomElement root = doc.documentElement();
QDomElement book = doc.createElement("book");
book.setAttribute("id", 3);
book.setAttribute("time", "1999/09/09");
QDomElement title = doc.createElement("title");
QDomText text;
text = doc.createTextNode("Pride and Prejudice");
title.appendChild(text);
book.appendChild(title);
QDomElement author = doc.createElement("author");
text = doc.createTextNode("Jane Austen");
author.appendChild(text);
book.appendChild(author);
QDomElement price = doc.createElement("price");
text = doc.createTextNode("$69.9");
price.appendChild(text);
book.appendChild(price);
root.appendChild(book);

if(!file.open(QFile::WriteOnly | QFile::Truncate))
{
// 先读进来,再重写 ,如果不用truncate就是在后面追加内容
return;
}

// 输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4); // 缩进4格
file.close();
}
删除 XML 内容

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 删除XML内容
void Widget::remove_xml()
{
// 打开文件
QFile file("test.xml"); // 相对路径、绝对路径、资源路径都可以
if(!file.open(QFile::ReadOnly))
{
return;
}

// 删除一个一级子节点及其元素,外层节点删除内层节点与此相同
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close(); // 一定要记得关闭,不然无法完成操作

QDomElement root = doc.documentElement();
QDomNodeList list = doc.elementsByTagName("book"); // 由标签名定位
for(int i = 0; i < list.count(); i++)
{
QDomElement e = list.at(i).toElement();
if(e.attribute("time") == "2020/08/09") // 以属性名定位,类似于hash方式
{
root.removeChild(list.at(i)); // 这里仅删除一个节点,可以加入break
break;
}
}

if(!file.open(QFile::WriteOnly | QFile::Truncate))
{
return;
}

// 输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4);
file.close();
}
更新 XML 内容

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 更新XML内容
void Widget::update_xml()
{
// 打开文件
QFile file("test.xml");
if(!file.open(QFile::ReadOnly))
{
return;
}

//更新一个标签项,如果知道XML的结构,直接定位到那个标签定点更新
//或者用遍历的方法去匹配tagname或者attribute,value来更新
QDomDocument doc;
if(!doc.setContent(&file))
{
file.close();
return;
}
file.close();

QDomElement root = doc.documentElement();
QDomNodeList list = root.elementsByTagName("book");
QDomNode node = list.at(list.size() - 1).firstChild(); // 定位到第三格以及子节点的子元素
QDomNode oldnode = node.firstChild(); // 标签之间的内容作为节点的子节点出现,当前是 How to learn Python
node.firstChild().setNodeValue("Update_success");
QDomNode newnode = node.firstChild();
node.replaceChild(newnode, oldnode);

if(!file.open(QFile::WriteOnly | QFile::Truncate))
{
return;
}
// 输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4); // 缩进4格
file.close();
}

今天的分享就到这里,后续我会继续更新我的Qt学习记录~

评论