QDomDocument是QT所封装的类,用来操作XML文件。而xml在项目中的角色常常是用来存储一些配置数据,因此在大部分的项目中会用到两个功能:写XML文件和读取XML文件。具体情况见代码:
#include <QtCore/QCoreApplication>
#include <QDomDocument>
#include <QMap>
#include <QTextStream>
#include <QFile>
#include <iostream>
class CXMLTestData
{
public:
CXMLTestData();
CXMLTestData(int num);
~CXMLTestData();
void OutTheData();
bool m_bXMLTestData;
int m_iTestNum;
double m_dChooseNum;
QString m_qsXMLDescripe;
QMap<double , QString> m_mapXMLData;
bool m_bFirstChild;
double m_dFirstChildChoose;
QString m_qsTextNode;
};
CXMLTestData::CXMLTestData()
{
m_bXMLTestData = true;
m_iTestNum = 2226;
m_dChooseNum = 7920;
m_qsXMLDescripe = "XML Write Or Read Test!";
m_mapXMLData[0] = "This is first data.";
m_mapXMLData[1] = "This is second data.";
m_mapXMLData[2] = "This is third data";
m_bFirstChild = true;
m_dFirstChildChoose = 9898;
m_qsTextNode = "This is TestNode!";
}
CXMLTestData::CXMLTestData(int num)
{
m_bXMLTestData = false;
m_iTestNum = 0;
m_dChooseNum = 0;
m_bFirstChild = true;
m_dFirstChildChoose = 0;
}
CXMLTestData::~CXMLTestData()
{
}
void CXMLTestData::OutTheData()
{
std::cout<< "bXML_TestData = " << m_bXMLTestData << "\n"
<< "iTest_Num = " << m_iTestNum << "\n"
<< "dChoose_Num = " << m_dChooseNum << "\n"
<< "qsXML_Descripe = " << m_qsXMLDescripe.toStdString() << "\n"
<< "mapXMLData_index_0 = " << m_mapXMLData[0].toStdString() << "\n"
<< "mapXMLData_index_1 = " << m_mapXMLData[1].toStdString() << "\n"
<< "mapXMLData_index_2 = " << m_mapXMLData[2].toStdString() << "\n"
<< "bFirstChild = " << m_bFirstChild << "\n"
<< "dFirstChild_Choose = " << m_dFirstChildChoose << "\n"
<< "LastChild = " << m_qsTextNode.toStdString() <<"\n"
<< endl;
}
CXMLTestData myData;
CXMLTestData myReadData(0);
void writeXML()
{
//保存或者创建一个XML文件,其顺序大部分为:
//1.对一个QDomDocument对象进行加工,得到需要存储的QDomDocument
//2.将其保存到一个.xml文件中
//1.创建加工一个QDomDocument对象
//(1)创建XML文档得到声明和处理指令,当然也可以添加注释等
QDomDocument doc;
//声明和处理指令
//声明:https://www.cnblogs.com/linyisme/p/5865129.html
//处理指令:https://www.cnblogs.com/planetwithpig/p/11517923.html
QDomProcessingInstruction stateInstruct = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
QDomProcessingInstruction dealInstruct = doc.createProcessingInstruction("xml-stylesheet", "type=\"text/css\" href=\"style.css\"");
doc.appendChild(stateInstruct);
doc.appendChild(dealInstruct);
//也可以补充一些改xml表示的注释
QDomComment comment = doc.createComment(QString::fromLocal8Bit("这是关于读写XML文件的测试而已"));
doc.appendChild(comment);
//(2)创建根节点
//关于QDomText、QDomElement、QDomComment、QDomProcessingInstruction等都是通过QDomDocument进行创建
//之后将其appendChild到某个节点中去
//将根节点创建后,后续的数据填充到根节点中即可
//===================================================
//此处数据的填充可以类似到树的添加即可
//elementRoot.appendChild(LastChild)相当于添加子节点的兄弟节点
//而如果elementRoot.appendChild(QDomElement::firstChild),再用firstChild.appendChild(ChildChild)相当于根的子节点添加了子节点
//
// QDomElement
// / \
// firstChild LastChild
// /
// ChildChild
QDomElement elementRoot = doc.createElement("XML-TestData");
doc.appendChild(elementRoot);
QDomElement elementFirstChild = doc.createElement("XML-FirstChild");
elementRoot.appendChild(elementFirstChild);
QDomElement elementLastChild = doc.createElement("XML-LastChild");
elementRoot.appendChild(elementLastChild);
//(3)填充保存数据-元素
//对于单个节点来说,常用setAttribute,来填充数据
//数据的存储一般是为<key,value>的对应关系进行存储
//因此在读取的时候,也会用key进行读取
//大概顺序:
//在某个节点setAttribute填充数据,相当于一个节点内的数据
//之后用appendChild将这个节点放在某个父节点之下
//===================================
//当然你也可以使用doc.createTextNode创建相应的节点去存储数据,之后放在root节点下
//在创建的时候,推荐对需要存储的元素都设定为<key,value>的形态,这样方便后续的取值
elementRoot.setAttribute("bXML_TestData", myData.m_bXMLTestData ? 1 : 0);
elementRoot.setAttribute("iTest_Num",myData.m_iTestNum);
elementRoot.setAttribute("dChoose_Num",myData.m_dChooseNum);
elementRoot.setAttribute("qsXML_Descripe", myData.m_qsXMLDescripe);
for (
QMap<double, QString>::const_iterator cIter = myData.m_mapXMLData.constBegin();
cIter != myData.m_mapXMLData.constEnd(); cIter++
)
{
QDomElement element = doc.createElement("mapXMLData");
element.setAttribute("mapXMLData_index", *cIter);
elementRoot.appendChild(element);
}
elementFirstChild.setAttribute("bFirstChild", myData.m_bFirstChild ? 1 : 0);
elementFirstChild.setAttribute("dFirstChild_Choose", myData.m_dFirstChildChoose);
QDomText textNode = doc.createTextNode(myData.m_qsTextNode);
elementLastChild.appendChild(textNode);
//(4)保存xml文件
QFile xmlFile("xmlTest.xml");
if (xmlFile.open(QFile::WriteOnly | QFile::Text))
{
QTextStream outFile(&xmlFile);
outFile.setCodec("UTF-8");
doc.save(outFile, QDomNode::EncodingFromDocument);
xmlFile.close();
}
}
void readXML()
{
// 保存或者创建一个XML文件,其顺序大部分为:
//1.将文件数据从文件中读取到QDomDocument中
//2.运用QDomDocument :: elementsByTagName(rootName)获取到根节点
//3.获取数据,存储到对应地方
//1.打开文件,并存储到QDomDocument
QFile xmlFile("xmlTest.xml");
if (!xmlFile.open(QFile::ReadOnly))
return;
QDomDocument doc;
if (!doc.setContent(&xmlFile))
{
xmlFile.close();
return;
}
xmlFile.close();
//2.找到根节点,将所有名称为"XML-TestData"的节点存入list
//QDomNodeList QDomDocument::elementsByTagName(const QString& tagname)const
//返回QDomNodeList,其中包含名称为tagname的文档中的所有元素。节点列表的顺序是在元素树的预遍历中遇到它们的顺序
//https://doc-snapshots.qt.io/4.8/qdomdocument.html#createProcessingInstruction QT网页资料库
//此时获取到的QDomNodeList是“live”的,简单来说就是现在该部QDomDocument节点的值,QDomNodeList里面的值也会变化
//QDomNode QDomNodeList :: at( int index)const
//提供此功能是为了确保Qt API的一致性。它相当于项目()。
//QDomElement QDomNode::toElement()const
//将QDomNode转换为QDomElement。如果节点不是元素,则返回的对象为null。
//QDomNode存在许多的类似toElement()的接口,可以转换成为对应的类型
QDomNodeList nodeList = doc.elementsByTagName("XML-TestData");
if (nodeList.isEmpty())
return;
QDomElement rootElement = nodeList.at(0).toElement();
//3.获取数据
if (rootElement.hasAttribute("bXML_TestData"))
myReadData.m_bXMLTestData = rootElement.attribute("bXML_TestData").toInt();
myReadData.m_iTestNum = rootElement.attribute("iTest_Num").toInt();
myReadData.m_dChooseNum = rootElement.attribute("dChoose_Num").toInt();
myReadData.m_qsXMLDescripe = rootElement.attribute("qsXML_Descripe");
myReadData.m_mapXMLData.clear();
QDomNodeList locp = rootElement.elementsByTagName("mapXMLData");
for (int i = 0; i < locp.size(); ++i)
{
QDomElement element = locp.at(i).toElement();
myReadData.m_mapXMLData[i] = element.attribute("mapXMLData_index");
}
//关于子节点这一点,在文件中的存储方式为:
//<XML-TestData iTest_Num="2226" dChoose_Num="7920" qsXML_Descripe="XML Write Or Read Test!" bXML_TestData="1">
//<XML - FirstChild bFirstChild = "1" dFirstChild_Choose = "9898" / >
//<XML - LastChild>This is TestNode!< / XML - LastChild>
//<mapXMLData mapXMLData_index = "This is first data." / >
//< / XML - TestData>
//当你想要访问FirstChild节点中的时候,需要获取到FirstChild节点对象进行访问,
//我测试过使用rootElement
//获取firstChild.attribute("bFirstChild").toInt();,使用根节点进行访问的时候,其值是获取不到的
QDomNodeList locpFirst = rootElement.elementsByTagName("XML-FirstChild");
if(0 < locpFirst.size())
{
QDomElement firstElement = locpFirst.at(0).toElement();
myReadData.m_bFirstChild = firstElement.attribute("bFirstChild").toInt();
myReadData.m_dFirstChildChoose = firstElement.attribute("dFirstChild_Choose").toInt();
}
//获取LastChild
QDomNodeList locpLast = rootElement.elementsByTagName("XML-LastChild");
if(0 < locpLast.size())
{
QDomElement lastElement = locpLast.at(0).toElement();
myReadData.m_qsTextNode = lastElement.text();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
writeXML();
readXML();
myReadData.OutTheData();
return a.exec();
}
运行结果为:
可拓展知识:
在qdom.h代码文件中,列举了许多的节点类型,未进行全面了解可在QT网上教程中查看: