本机系统配置:ThinkPadT570、Windows10、QT5.12.2(QtCreater4.8.2)
通过QDomDocument实现xml文件的写入主要有以下几个步骤:
1.定义QDomDocument变量
QDomDocument m_domDocSaveConfig;
2.创建根节点:
QDomElement root = m_domDocSaveConfig.documentElement();
if(root.isNull())
{
root = m_domDocSaveConfig.createElement("configuration");
}
//TODO:创建子节点并附加到root上······
3.将根节点添加到m_domDocSaveConfig
m_domDocSaveConfig.appendChild(root);
4.将dom变量保存到指定文件
QString sFilePath = qApp->applicationDirPath() + "/../../EditPic/test2.config";
QFile file(sFilePath);
if (!file.open(QFile::WriteOnly|QFile::Truncate | QFile::Text))//1.QFile::WriteOnly如果文件不存在,则创建;2.QFile::Truncate打开的同时清空
{
return false;
}
QTextStream stream( &file );
stream.setCodec("utf-8");
m_domDocSaveConfig.save(stream,4,QDomNode::EncodingFromTextStream);
file.close();
具体代码如下:
我建立的qt工程名为EditPic
需要解析的配置文件名为test.config,放在工程目录下
配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<ROOT time="20190417" version="1.0alpha">
<BRANCH_LEVEL1 AlgorithmID="1" invokeOrder="1,2,3" index="1" name="BranchLV1_1" nickname="一级分支1" visible="on">
<BRANCH_LEVEL2 index="1" name="BranchLV2_1" nickname="二级分支1" SubAlgoID="1" visible="off">
<param index="1" valuetype="int" valueRange="0,10" value="1" name="param1" nickname="参数1" visible="off"/>
</BRANCH_LEVEL2>
<BRANCH_LEVEL2 index="2" name="BranchLV2_2" nickname="二级分支2" SubAlgoID="2" visible="off">
<param index="1" valuetype="int" valueRange="0,10" value="1" name="param2" nickname="参数2" visible="off"/>
</BRANCH_LEVEL2>
</BRANCH_LEVEL1>
<BRANCH_LEVEL1 AlgorithmID="0" invokeOrder="" index="0" name="" nickname="" visible="off"/>
<BRANCH_LEVEL1 AlgorithmID="3" invokeOrder="1,2,3,4" index="3" name="BranchLV1_2" nickname="一级分支2" visible="on">
<BRANCH_LEVEL2 index="1" name="BranchLV2_1" nickname="二级分支1" SubAlgoID="1" visible="on">
<param index="1" valuetype="int" valueRange="0,10" value="1" name="param1" nickname="参数1" visible="on"/>
</BRANCH_LEVEL2>
<BRANCH_LEVEL2 index="2" name="BranchLV2_2" nickname="二级分支2" SubAlgoID="2" visible="on">
<param index="1" valuetype="int" valueRange="0,10" value="1" name="param2" nickname="参数2" visible="on"/>
</BRANCH_LEVEL2>
</BRANCH_LEVEL1>
</ROOT>
</configuration>
我写了一个ConfigFileManager类用来读写xml文件的,头文件如下:
#ifndef CONFIGFILEMANAGER_H
#define CONFIGFILEMANAGER_H
#include <QObject>
#include <QString>
#include <QFileInfo>
#include <QtXml/QDomDocument>
#include <QDebug>
#include <QMap>
#include <QCoreApplication>
#include <QDir>
#include <QSettings>
#include <QVector>
struct PARAM//参数节点
{
int m_nIndex;//参数ID
QString m_sName;//参数名
QString m_sNickname;//参数中文名
QString m_sValueType;//参数类型
int m_nValueRange[2];//int类型的参数范围
float m_fValueRange[2];//float类型的参数范围
QVector<int> m_vIntValue;//int类型的参数容器
QVector<float> m_vFloatValue;//float类型的参数容器
QString m_sStringValue;//string类型的参数、或者enum类型的参数、或bool类型的参数
QStringList m_slistEnumValues;//enum类型的参数值列表
bool m_bVisible;//参数是否显示
PARAM():m_nIndex(0),
m_sName(""),
m_sNickname(""),
m_sValueType(""),
m_bVisible(true)
{
m_nValueRange[0] = 0;
m_nValueRange[1] = 0;
m_fValueRange[0] = 0;
m_fValueRange[1] = 0;
m_sStringValue = "";
if(!m_slistEnumValues.empty())
{
m_slistEnumValues.clear();
}
}
};
struct BRANCH_LEVEL2//二级分支节点
{
int m_nIndex;
QString m_sName;
QString m_sNickname;
int m_nAlgoId;
bool m_bVisible;
QMap<int,PARAM> m_mapParams;
};
struct BRANCH_LEVEL1//一级分支节点
{
int m_nIndex;
QString m_sName;
QString m_sNickname;
int m_nAlgoId;
bool m_bVisible;
QVector<int> m_vInvokeOrder;
QMap<int,BRANCH_LEVEL2> m_mapBranchLevel2;
};
struct ROOT//根节点
{
QString m_sVersion;
QString m_sTime;
QMap<int,BRANCH_LEVEL1> m_mapBranchLevel1;
};
class ConfigFileManager : public QObject
{
Q_OBJECT
public:
ConfigFileManager();
bool ParseConfigFile();
bool SaveConfigFile();
private:
void ParseROOT(QDomNode* node);
void ParseBRANCH_LEVEL1(QDomNode* node, QMap<int, BRANCH_LEVEL1> &mapBranchLevel1);
void ParseBRANCH_LEVEL2(QDomNode *node, QMap<int, BRANCH_LEVEL2> &mapBranchLevel2);
void ParseParameters(QDomNode *node, QMap<int,PARAM> &mapParam);
void SaveROOT(QDomNode* node);
void SaveBranchLevel1(QDomElement* parentNode,QMap<int, BRANCH_LEVEL1> &mapBranchLevel1);
void SaveBranchLevel2(QDomElement* parentNode, QMap<int, BRANCH_LEVEL2> &mapBranchLevel2);
void SaveParams(QDomElement* parentNode, QMap<int, PARAM> &mapParam);
QVector<int> SplitXmlStringInt(QString xmlText);
QVector<float> SplitXmlStringFloat(QString xmlText);
private:
ROOT m_tRoot;
QDomDocument m_domDocSaveConfig;
};
#endif // CONFIGFILEMANAGER_H
源文件如下:
#include "configfilemanager.h"
ConfigFileManager::ConfigFileManager()
{
}
bool ConfigFileManager::ParseConfigFile()//读取test.config文件并获取根节点
{
QString sConfigFilePath;
#if defined(Q_OS_LINUX)
sConfigFilePath = qApp->applicationDirPath() + "/../EditPic/test.config" ;//in linux
#else
sConfigFilePath = qApp->applicationDirPath() + "/../../EditPic/test.config" ;//in windows,我的工程名为EditPic
#endif
QFile file(sConfigFilePath);
if (!file.open(QFile::ReadOnly))
{
return false;
}
QString errorStr;
int errorLine;
int errorColumn;
QDomDocument qDomConfigFile;
if (!qDomConfigFile.setContent(&file, false, &errorStr, &errorLine,&errorColumn))
{
return false;
}
QDomElement root = qDomConfigFile.documentElement();
QDomNode child = root.firstChild();
if (!child.isNull())
{
if(child.toElement().tagName() == "ROOT")
{
ParseROOT(&child);
}
}
file.close();
return true;
}
bool ConfigFileManager::SaveConfigFile()
{
qSetGlobalQHashSeed(100);//为了使 通过QDomElement保存节点属性时, 每次保存的属性的顺序固定,与qSetGlobalQHashSeed(-1);搭配着用
//projectDoc.createProcessingInstruction("xml","version = "1.0"encoding = " UTF-8"");
QDomElement root = m_domDocSaveConfig.documentElement();
if(root.isNull())
{
root = m_domDocSaveConfig.createElement("configuration");
}
SaveROOT(&root);
m_domDocSaveConfig.appendChild(root);
//#if defined(Q_OS_LINUX)
// m_wstrFilePath = qApp->applicationDirPath() + "/../Tx2Oled/XMLTest/"+strProName+".config";//in linux system
//#else
QString sFilePath = qApp->applicationDirPath() + "/../../EditPic/test2.config";//in windows system XMLTest
//#endif
QFile file(sFilePath);
if (!file.open(QFile::WriteOnly|QFile::Truncate | QFile::Text))//1.QFile::WriteOnly如果文件不存在,则创建;2.QFile::Truncate打开的同时清空
{
return false;
}
QTextStream stream( &file );
stream.setCodec("utf-8");
m_domDocSaveConfig.save(stream,4,QDomNode::EncodingFromTextStream);
file.close();
qSetGlobalQHashSeed(-1);
return true;
}
void ConfigFileManager::ParseROOT(QDomNode *node)//解析根节点
{
m_tRoot.m_sVersion = node->toElement().attribute("version");
m_tRoot.m_sTime = node->toElement().attribute("time");
ParseBRANCH_LEVEL1(node,m_tRoot.m_mapBranchLevel1);
}
void ConfigFileManager::ParseBRANCH_LEVEL1(QDomNode *node, QMap<int, BRANCH_LEVEL1> &mapBranchLevel1)//解析一级分支
{
QDomNode childnode = node->toElement().firstChild();
while(!childnode.isNull())
{
if(childnode.toElement().tagName() == "BRANCH_LEVEL1")
{
BRANCH_LEVEL1 BranchLevel1;
BranchLevel1.m_sName = childnode.toElement().attribute("name");
BranchLevel1.m_nAlgoId = childnode.toElement().attribute("AlgorithmID").toInt();
BranchLevel1.m_sNickname = childnode.toElement().attribute("nickname");
BranchLevel1.m_nIndex = childnode.toElement().attribute("index").toInt();
QString sVisible = childnode.toElement().attribute("visible");
if(sVisible=="on")
{
BranchLevel1.m_bVisible = true;
}
else
{
BranchLevel1.m_bVisible = false;
}
QString sInvokerOrder = childnode.toElement().attribute("invokeOrder");
BranchLevel1.m_vInvokeOrder = SplitXmlStringInt(sInvokerOrder);
ParseBRANCH_LEVEL2(&childnode,BranchLevel1.m_mapBranchLevel2);
mapBranchLevel1.insert(BranchLevel1.m_nIndex,BranchLevel1);
}
childnode = childnode.nextSibling();
}
}
void ConfigFileManager::ParseBRANCH_LEVEL2(QDomNode *node, QMap<int, BRANCH_LEVEL2> &mapBranchLevel2)//解析二级分支
{
QDomNode childnode = node->toElement().firstChild();
while(!childnode.isNull())
{
if(childnode.toElement().tagName() == "BRANCH_LEVEL2")
{
BRANCH_LEVEL2 BranchLevel2;
BranchLevel2.m_sName = childnode.toElement().attribute("name");
BranchLevel2.m_nAlgoId = childnode.toElement().attribute("SubAlgoID").toInt();
BranchLevel2.m_sNickname = childnode.toElement().attribute("nickname");
BranchLevel2.m_nIndex = childnode.toElement().attribute("index").toInt();
QString sVisible = childnode.toElement().attribute("visible");
if(sVisible=="on")
{
BranchLevel2.m_bVisible = true;
}
else
{
BranchLevel2.m_bVisible = false;
}
ParseParameters(&childnode,BranchLevel2.m_mapParams);
mapBranchLevel2.insert(BranchLevel2.m_nIndex,BranchLevel2);
}
childnode = childnode.nextSibling();
}
}
void ConfigFileManager::ParseParameters(QDomNode *node, QMap<int,PARAM> &mapParam)//解析参数
{
QDomNode childnode = node->toElement().firstChild();
while(!childnode.isNull())
{
if(childnode.toElement().tagName() == "param")
{
PARAM Parameter;
Parameter.m_nIndex = childnode.toElement().attribute("index").toInt();
Parameter.m_sName = childnode.toElement().attribute("name");
Parameter.m_sNickname = childnode.toElement().attribute("nickname");
Parameter.m_sValueType = childnode.toElement().attribute("valuetype");
QString Value,RangeValue;
if(Parameter.m_sValueType == "int")
{
Value = childnode.toElement().attribute("value");
Parameter.m_vIntValue = SplitXmlStringInt(Value);
RangeValue = childnode.toElement().attribute("valueRange");
QStringList list = RangeValue.split(',');
if(2 == list.size())
{
Parameter.m_nValueRange[0] = list.at(0).toInt();
Parameter.m_nValueRange[1] = list.at(1).toInt();
}
}
else if(Parameter.m_sValueType == "float")
{
Value = childnode.toElement().attribute("value");
Parameter.m_vFloatValue = SplitXmlStringFloat(Value);
RangeValue = childnode.toElement().attribute("valueRange");
QStringList list = RangeValue.split(',');
if(2 == list.size())
{
Parameter.m_fValueRange[0] = list.at(0).toFloat();
Parameter.m_fValueRange[1] = list.at(1).toFloat();
}
}
else if(Parameter.m_sValueType == "string")
{
Parameter.m_sStringValue = childnode.toElement().attribute("value");
}
else if((Parameter.m_sValueType == "enum")||((Parameter.m_sValueType == "bool")))
{
Parameter.m_sStringValue = childnode.toElement().attribute("value");
QString valuelist = childnode.toElement().attribute("valueList");
Parameter.m_slistEnumValues = valuelist.split(",");
RangeValue = childnode.toElement().attribute("valueRange");
QStringList list = RangeValue.split(',');
if(2 == list.size())
{
Parameter.m_nValueRange[0] = list.at(0).toInt();
Parameter.m_nValueRange[1] = list.at(1).toInt();
}
}
QString sVisible = childnode.toElement().attribute("visible");
if(sVisible=="on")
{
Parameter.m_bVisible = true;
}
else
{
Parameter.m_bVisible = false;
}
mapParam.insert(Parameter.m_nIndex,Parameter);
}
childnode = childnode.nextSibling();
}
}
void ConfigFileManager::SaveROOT(QDomNode *node)
{
QDomElement eldRoot = m_domDocSaveConfig.createElement("ROOT");
eldRoot.setAttribute("version",m_tRoot.m_sVersion);
eldRoot.setAttribute("time",m_tRoot.m_sTime);
SaveBranchLevel1(&eldRoot,m_tRoot.m_mapBranchLevel1);
node->appendChild(eldRoot);
}
void ConfigFileManager::SaveBranchLevel1(QDomElement *parentNode, QMap<int, BRANCH_LEVEL1> &mapBranchLevel1)
{
for (int i = 1;i<(mapBranchLevel1.size()+1);i++)
{
QDomElement eleBranchLV1 = m_domDocSaveConfig.createElement("BRANCH_LEVEL1");
eleBranchLV1.setAttribute("name",mapBranchLevel1[i].m_sName);
eleBranchLV1.setAttribute("AlgorithmID",mapBranchLevel1[i].m_nAlgoId);
eleBranchLV1.setAttribute("nickname",mapBranchLevel1[i].m_sNickname);
eleBranchLV1.setAttribute("index",mapBranchLevel1[i].m_nIndex);
QString qstr = "";
int nNum = mapBranchLevel1[i].m_vInvokeOrder.size();
for(int j = 0;j<nNum;j++)
{
if(j == 0)
{
qstr = QString::number(mapBranchLevel1[i].m_vInvokeOrder[j],10);
}
else
{
qstr=qstr+","+QString::number(mapBranchLevel1[i].m_vInvokeOrder[j],10);
}
}
eleBranchLV1.setAttribute("invokeOrder",qstr);
if(mapBranchLevel1[i].m_bVisible == true)
{
eleBranchLV1.setAttribute("visible","on");
}
else
{
eleBranchLV1.setAttribute("visible","off");
}
SaveBranchLevel2(&eleBranchLV1,mapBranchLevel1[i].m_mapBranchLevel2);
parentNode->appendChild(eleBranchLV1);
}
}
void ConfigFileManager::SaveBranchLevel2(QDomElement *parentNode, QMap<int, BRANCH_LEVEL2> &mapBranchLevel2)
{
for (int i = 1;i<(mapBranchLevel2.size()+1);i++)
{
QDomElement eleBranchLV2 = m_domDocSaveConfig.createElement("BRANCH_LEVEL2");
eleBranchLV2.setAttribute("name",mapBranchLevel2[i].m_sName);
eleBranchLV2.setAttribute("SubAlgoID",mapBranchLevel2[i].m_nAlgoId);
eleBranchLV2.setAttribute("nickname",mapBranchLevel2[i].m_sNickname);
eleBranchLV2.setAttribute("index",mapBranchLevel2[i].m_nIndex);
if(mapBranchLevel2[i].m_bVisible == true)
{
eleBranchLV2.setAttribute("visible","on");
}
else
{
eleBranchLV2.setAttribute("visible","off");
}
SaveParams(&eleBranchLV2,mapBranchLevel2[i].m_mapParams);
parentNode->appendChild(eleBranchLV2);
}
}
void ConfigFileManager::SaveParams(QDomElement *parentNode, QMap<int, PARAM> &mapParam)
{
for (int i=1;i<(mapParam.size()+1);i++)
{
QDomElement param = m_domDocSaveConfig.createElement("param");
param.setAttribute("name",mapParam[i].m_sName);
param.setAttribute("nickname",mapParam[i].m_sNickname);
param.setAttribute("index",mapParam[i].m_nIndex);
param.setAttribute("valuetype",mapParam[i].m_sValueType);
if(mapParam[i].m_bVisible)
{
param.setAttribute("visible","on");
}
else
{
param.setAttribute("visible","off");
}
//
if(mapParam[i].m_sValueType == "int")
{
QString qstr = "";
qstr = QString::number(mapParam[i].m_nValueRange[0],10) +","+QString::number(mapParam[i].m_nValueRange[1],10);
param.setAttribute("valueRange",qstr);
qstr = "";
for(int j = 0;j<mapParam[i].m_vIntValue.size();j++)
{
if(j == 0)
{
qstr = QString::number(mapParam[i].m_vIntValue[j],10);
}
else
{
qstr=qstr+","+QString::number(mapParam[i].m_vIntValue[j],10);
}
}
param.setAttribute("value",qstr);
}
else if(mapParam[i].m_sValueType == "float")
{
QString qstr = "";
qstr = QString("%1").arg(mapParam[i].m_fValueRange[0]) +","+QString("%1").arg(mapParam[i].m_fValueRange[1]);
param.setAttribute("valueRange",qstr);
qstr = "";
for(int j = 0;j<mapParam[i].m_vFloatValue.size();j++)
{
if(j == 0)
{
qstr = QString("%1").arg(mapParam[i].m_vFloatValue[j]);
}
else
{
qstr=qstr+","+QString("%1").arg(mapParam[i].m_vFloatValue[j]);
}
}
param.setAttribute("value",qstr);
}
else if(mapParam[i].m_sValueType == "string")
{
param.setAttribute("value",mapParam[i].m_sStringValue);
}
else if(mapParam[i].m_sValueType == "enum")
{
param.setAttribute("value",mapParam[i].m_sStringValue);
int nNum = mapParam[i].m_slistEnumValues.size();
QString qstr = "";
qstr = "0,"+QString("%1").arg((nNum-1));
param.setAttribute("valueRange",qstr);
qstr = "";
for(int j = 0;j<nNum;j++)
{
if(j == 0)
{
qstr = mapParam[i].m_slistEnumValues.takeFirst();
}
else
{
qstr=qstr+","+mapParam[i].m_slistEnumValues.takeFirst();
}
}
param.setAttribute("valueList",qstr);
}
else if(mapParam[i].m_sValueType == "bool")
{
param.setAttribute("value",mapParam[i].m_sStringValue);
param.setAttribute("valueRange","0,1");
}
parentNode->appendChild(param);
}
}
QVector<int> ConfigFileManager::SplitXmlStringInt(QString xmlText)//将QString按逗号分割,并转为int类型,存放到QVector<int>
{
QVector<int> vParam;
QString value;
QStringList list = xmlText.split(',');
for (int i = 0; i < list.size(); ++i)
{
value = list.at(i);
vParam.push_back(value.toInt());
}
return vParam;
}
QVector<float> ConfigFileManager::SplitXmlStringFloat(QString xmlText)//将QString按逗号分割,并转为float类型,存放到QVector<float>
{
QVector<float> vParam;
QString value;
QStringList list = xmlText.split(',');
for (int i = 0; i < list.size(); ++i)
{
value = list.at(i);
vParam.push_back(value.toFloat());
}
return vParam;
}
在工程主线程中如下调用上述类:
ConfigFileManager cfg;
bool bret = cfg.ParseConfigFile();//读取配置文件
cfg.SaveConfigFile();//写入配置文件