最近,学习了Qt C++对XML的一系列操作。今天,把相关代码和注释贴在这里, 以备后续使用。
什么是 XML
可扩展标记语言(英语:Extensible Markup Language,简称:XML)是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。
——from Wikipedia
Qt 如何操作 XML
.pro 文件
增加 QT += xml模块。
.cpp 文件
头部 #include <QtXml>
写入 XML
源代码
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
<?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
源代码
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 内容
源代码
// 增加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 内容
源代码
// 删除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 内容
源代码
// 更新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学习记录~