Qt XML 读写
XML 简介
XML(Extensible Markup Language)是一种类似于 HTML,但是没有使用预定义标记的语言。
有许多基于 XML 的语言,包括 XHTML、MathML、SVG、RSS 和 RDF (en-US)。
XML 声明
<?xml version="1.0" encoding="UTF-8"?>
注释
<!-- Comment -->
实体
像 HTML 一样,XML 为一些特别预留的符号定义了一些方法,称为实体(entities),例如用于标记的大于号。下面是五个你必须知道的符号:
实体 | 符号 | 描述 |
---|---|---|
& lt; | < | 小于符号 |
& gt; | > | 大于符号 |
& amp; | & | 和 |
& quot; | " | 一个双引号 |
& apos; | ' | 一个单引号 |
Qt QDomDocument
示例
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag id="1" time="2013/6/13">
<name>test1</name>
<value>100</value>
</tag>
<tag id="2" time="1813/1/27">
<name>test2</name>
<value>100</value>
</tag>
</root>
Code
void QtDemo::on_writeXmlBtn_Clicked()
{
//The trick of setting the QT_HASH_SEED environment variable
qSetGlobalQHashSeed(0); // set a fixed hash value
//打开或创建文件
QFile file("test.xml"); //相对路径、绝对路径、资源路径都可以
if (!file.open(QFile::WriteOnly | QFile::Truncate)) //可以用QIODevice,Truncate表示清空原来的内容
return;
QDomDocument doc;
//写入xml头部
QDomProcessingInstruction instruction; //添加处理命令
instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
//添加根节点
QDomElement root = doc.createElement("root");
doc.appendChild(root);
//添加第一个子节点及其子元素
QDomElement tag = doc.createElement("tag");
tag.setAttribute("id", 1); //方式一:创建属性 其中键值对的值可以是各种类型
QDomAttr time = doc.createAttribute("time"); //方式二:创建属性 值必须是字符串
time.setValue("2011/1/11");
tag.setAttributeNode(time);
QDomElement name = doc.createElement("name"); //创建子元素
QDomText text; //设置括号标签中间的值
text = doc.createTextNode("test1");
tag.appendChild(name);
name.appendChild(text);
QDomElement value = doc.createElement("value"); //创建子元素
text = doc.createTextNode("100");
value.appendChild(text);
tag.appendChild(value);
root.appendChild(tag);
//添加第二个子节点及其子元素,部分变量只需重新赋值
tag = doc.createElement("tag");
tag.setAttribute("id", 2);
time = doc.createAttribute("time");
time.setValue("2002/2/2");
tag.setAttributeNode(time);
name = doc.createElement("name");
text = doc.createTextNode("test2");
tag.appendChild(name);
name.appendChild(text);
value = doc.createElement("value");
text = doc.createTextNode("200");
value.appendChild(text);
tag.appendChild(value);
root.appendChild(tag);
//输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4); //缩进4格
file.close();
// reset hash seed with new random value.
qSetGlobalQHashSeed(-1);
}
void QtDemo::onreadxmlclicked()
{
//打开或创建文件
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(); //转换为元素,注意元素和节点是两个数据结构,其实差不多
qDebug() << e.tagName() << " " << e.attribute("id") << " " << e.attribute("time"); //打印键值对,tagName和nodeName是一个东西
QDomNodeList list = e.childNodes();
for (int i = 0; i < list.count(); i++) //遍历子元素,count和size都可以用,可用于标签数计数
{
QDomNode n = list.at(i);
if (node.isElement())
qDebug() << n.nodeName() << ":" << n.toElement().text();
}
}
node = node.nextSibling(); //下一个兄弟节点,nextSiblingElement()是下一个兄弟元素,都差不多
}
}
void QtDemo::on_addXmlBtn_Clicked()
{
//打开文件
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("tag");
book.setAttribute("id", 3);
book.setAttribute("time", "2019/1/1");
QDomElement title = doc.createElement("name");
QDomText text;
text = doc.createTextNode("test3");
title.appendChild(text);
book.appendChild(title);
QDomElement author = doc.createElement("value");
text = doc.createTextNode("300");
author.appendChild(text);
book.appendChild(author);
root.appendChild(book);
if (!file.open(QFile::WriteOnly | QFile::Truncate)) //先读进来,再重写,如果不用truncate就是在后面追加内容,就无效了
return;
//输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4); //缩进4格
file.close();
}
void QtDemo::on_removeXmlBtn_Clicked()
{
//打开文件
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("tag"); //由标签名定位
for (int i = 0; i < list.count(); i++)
{
QDomElement e = list.at(i).toElement();
if (e.attribute("id") == "1") //以属性名定位,类似于hash的方式,warning:这里仅仅删除一个节点,其实可以加个break
root.removeChild(list.at(i));
}
if (!file.open(QFile::WriteOnly | QFile::Truncate))
return;
//输出到文件
QTextStream out_stream(&file);
doc.save(out_stream, 4); //缩进4格
file.close();
}
void QtDemo::on_updateXmlBtn_Clicked()
{
//打开文件
QFile file("test.xml"); //相对路径、绝对路径、资源路径都可以
if (!file.open(QFile::ReadOnly))
return;
//更新一个标签项,如果知道xml的结构,直接定位到那个标签上定点更新
//或者用遍历的方法去匹配tagname或者attribut,value来更新
QDomDocument doc;
if (!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement root = doc.documentElement();
QDomNodeList list = root.elementsByTagName("tag");
QDomNode node = list.at(list.size() - 1).firstChild(); //定位到第三个一级子节点的子元素
QDomNode oldnode = node.firstChild(); //标签之间的内容作为节点的子节点出现,当前是
node.firstChild().setNodeValue("test333");
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();
}