Qt 读写xml文件(QDomDocument)

一、简述

XML是一种标记语言,被设计用来结构化存储以及传输信息,是一种常用的文档数据结构。
就我个人而言,Qt下读写XML格式文件可以有三种方法:
一是使用纯C++的rapidxml开源库。优点是速度快,媲美strlen()的速度;缺点是处理中文比较麻烦,编码只有ANSI格式。
二是使用QXmlStreamReader类,适当结合QXmlQuery类。优点是灵活性强,节约内存;缺点是理解起来相对较难,还需要一点数据库语言的知识。
三是使用QDomDocument类。是Qt下读写xml文件传统而普遍的做法,缺点就是如果读写的文件很大,会消耗大量的内存空间。
QDomDocument类可以理解为一个QFile,这个类的对象代表了整个文件,通常也是一个xml文件的主节点。还需使用到的类有QDomNode(节点基类)、QDomElement(节点类)、QDomText(内容)、QDomAttr(属性)、QDomProcessingInstruction(文件头)。

二、读写样式
<?xml version='1.0' encoding='utf-8'?>
<日销售清单>
    <日期 date="2020-05-29">
        <时间 time="21:27:41">
            <厂家>二汽神龙</厂家>
            <品牌>毕加索</品牌>
            <报价>39</报价>
            <数量>1</数量>
            <金额>50</金额>
        </时间>
        <时间 time="21:27:51">
            <厂家>二汽神龙</厂家>
            <品牌>毕加索</品牌>
            <报价>39</报价>
            <数量>1</数量>
            <金额>50</金额>
        </时间>
        <时间 time="21:27:57">
            <厂家>二汽神龙</厂家>
            <品牌>毕加索</品牌>
            <报价>39</报价>
            <数量>1</数量>
            <金额>50</金额>
        </时间>
    </日期>
</日销售清单>

头文件

#ifndef DOCXML_H
#define DOCXML_H

#include <QString>
#include <QStringList>
#include <QDomDocument>
#include <QDomElement>

class DocXml
{
public:
    DocXml();

    static void CreateXml(const QString &filePath);     //创建xml 空文件
    static void AppendXml(const QString &filePath,QStringList list);
    static void WriteXml(QDomDocument &doc,QDomElement &root,QStringList &list);

    static void ReadXml(const QString &filePath,QStringList &fList,
                        QStringList &bList, QStringList &pList,
                        QStringList &nList, QStringList &tList);
};
#endif // DOCXML_H

创建空的XML文件

#include "docxml.h"
#include <QFile>
#include <QDomDocument>      //文件
#include <QDomProcessingInstruction>    //格式头部
#include <QDomElement>  //元素
#include <QTextStream>
#include <QDebug>
#include <QDateTime>

#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

DocXml::DocXml()
{

}
void DocXml::CreateXml(const QString &filePath)
{
    QFile file(filePath);
    if(true == file.exists())       //如果文件存在就不创建
    {
        cout << "文件已存在";
        return;
    }
    else {
       if(file.open(QIODevice::WriteOnly))
       {
            //创建Xml文档
           QDomDocument doc;
           //创建XML头部格式
           QDomProcessingInstruction ins = doc.createProcessingInstruction("xml","version = \'1.0\' encoding = \'utf-8\'");
           //追加元素
           doc.appendChild(ins);
           //根节点元素
           QDomElement root = doc.createElement("日销售清单");
           doc.appendChild(root);

           //保存
           QTextStream stream(&file);       //文本流关联文件
           doc.save(stream,4);      //4 代表缩进4个字符

           file.close();        //关闭文件

       }
       else
       {
            cout << "打开文件失败";
       }
    }
}

追加 XML 文件

void DocXml::AppendXml(const QString &filePath, QStringList list)
{
    QFile file(filePath);
    if(file.open(QIODevice::ReadOnly))
    {
        //file和xml文档对象关联
        QDomDocument doc;
        if(doc.setContent(&file))   //关联成功
        {
            file.close();     //关闭文件
            //获取根节点元素
            QDomElement root = doc.documentElement();

            //获取当前时间
            QDateTime date = QDateTime::currentDateTime();
            QString strDate = date.toString("yyyy-MM-dd");

            //判断根节点下面有没有子节点
            if(root.hasChildNodes())
            {
                //查找最后一个子节点
                QDomElement lastEmt = root.lastChildElement();
                if(lastEmt.attribute("date") == strDate)
                {
                    //写有效数据
                    WriteXml(doc,lastEmt,list);
                }
                else
                {
                    //创建子节点元素
                    QDomElement dateEmt = doc.createElement("日期");
                    //dateEmt.setAttribute("date",strDate);   //建议写法
                    //创建date属性
                    QDomAttr dateAttr = doc.createAttribute("date");
                    //设置属性的值
                    dateAttr.setNodeValue(strDate);
                    //节点和属性关联
                    dateEmt.setAttributeNode(dateAttr);
                    //把日期节点追加到根节点
                    root.appendChild(dateEmt);

                    //写有效数据
                    WriteXml(doc,dateEmt,list);
                }
            }
            else
            {
                //创建子节点元素
                QDomElement dateEmt = doc.createElement("日期");
                ------------------------------------------------
                dateEmt.setAttribute("date",strDate);   //建议写法
                ------------------------------------------------
                //创建date属性
                //QDomAttr dateAttr = doc.createAttribute("date");
                //设置属性的值
                //dateAttr.setNodeValue(strDate);
                //节点和属性关联
                //dateEmt.setAttributeNode(dateAttr);
                //把日期节点追加到根节点
                root.appendChild(dateEmt);

                //写有效数据
                WriteXml(doc,dateEmt,list);

            }
            //保存文件
            if(file.open(QIODevice::WriteOnly))
            {
                QTextStream stream(&file);
                doc.save(stream,4);
                file.close();
            }
        }
        else
        {
            cout << "关联失败";
        }
    }
    else {
        cout << "打开文件失败";
    }
}

向XML文件中写入

void DocXml::WriteXml(QDomDocument &doc, QDomElement &root, QStringList &list)
{
    //当前时间获取
    QDateTime time = QDateTime::currentDateTime();
    QString strTime = time.toString("hh:mm:ss");

    //创建节点元素
    QDomElement timeEmt = doc.createElement("时间");
    timeEmt.setAttribute("time",strTime);      //设置属性值
    //把时间节点追加到日期节点后面
    root.appendChild(timeEmt);

    QDomElement factory = doc.createElement("厂家");
    QDomElement brand = doc.createElement("品牌");
    QDomElement price = doc.createElement("报价");
    QDomElement num = doc.createElement("数量");
    QDomElement total = doc.createElement("金额");

    QDomText text = doc.createTextNode(list.at(0));
    factory.appendChild(text);

    text = doc.createTextNode(list.at(1));
    brand.appendChild(text);

    text = doc.createTextNode(list.at(2));
    price.appendChild(text);

    text = doc.createTextNode(list.at(3));
    num.appendChild(text);

    text = doc.createTextNode(list.at(4));
    total.appendChild(text);

    timeEmt.appendChild(factory);
    timeEmt.appendChild(brand);
    timeEmt.appendChild(price);
    timeEmt.appendChild(num);
    timeEmt.appendChild(total);
}

从XML文件中读取

void DocXml::ReadXml(const QString &filePath,QStringList &fList,
                    QStringList &bList, QStringList &pList,
                    QStringList &nList, QStringList &tList)
{
    QFile file(filePath);
    if(file.open(QIODevice::ReadOnly))
    {
        //file和xml文档对象关联
        QDomDocument doc;
        if(doc.setContent(&file))
        {
            file.close();

            QDateTime date = QDateTime::currentDateTime();
            QString strDate = date.toString("yyyy-MM-dd");
            //获取根节点
            QDomElement root = doc.documentElement();
            if(root.hasChildNodes())
            {
            	---------------------------------------------------------------------
                //推荐用法
                QDomElement element = root.firstChildElement("日期");     //日期节点
                //判断节点是否为空,获取属性值
                if(!element.isNull())
                {
                     QString  qstr = element.attribute("date");
                }
				---------------------------------------------------------------------
                //找最后一个元素
                QDomElement lastEmt = root.lastChildElement();
                if(lastEmt.attribute("date") == strDate)   //判断有没有当天日期
                {
                    //找出当前日期下所有时间子节点
                    QDomNodeList list = lastEmt.childNodes();
                    for(int i = 0;i < list.size(); ++i)
                    {
                        //list.at(0).toElement();
                        //转换为元素,找到时间节点下所有的子节点
                        QDomNodeList nodeList =  list.at(i).toElement().childNodes();
                        //厂家
                        QString factory = nodeList.at(0).toElement().text();
                        fList.append(factory);
                        //
                        QString brand = nodeList.at(0).toElement().text();
                        bList.append(brand);

                        QString price = nodeList.at(0).toElement().text();
                        pList.append(price);

                        QString num = nodeList.at(0).toElement().text();
                        nList.append(num);

                        QString total = nodeList.at(0).toElement().text();
                        tList.append(total);
                    }
                }
                else
                {
                    cout << "没有当天日期";
                    return ;
                }
            }
            else
            {
                cout << "没有子节点";
                return ;
            }
        }
        else
            cout << "file 和 xml 文档对象关联失败";
    }
    else {
        cout << "读取时打开文件失败";
    }
}

你可能感兴趣的:(Qt基础)