Qt通过QDomDocument实现将数据保存为xml文件

本机系统配置: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();//写入配置文件

猜你喜欢

转载自blog.csdn.net/weixin_43935474/article/details/89714873