qt读写xml文件(DOM和SAX两种方式)

一、XML简介:

      XML, 全称为扩展标记语言, 可用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据,是Internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。XML常用于接口调用,配置文件,数据存储等场景。

二、XML解析技术:

1)dom (Document Object Model)

      将整个文档当作一个对象装入内存进行处理,根据xml的层级结构,在内存中分配一个树形结构,把xml中的每部分都封装成对象,开发者可以访问这个对象中得每一个节点,每一个节点对应XML文件里得一个标记。

      优点:方便实现增删查改操作
      缺点:如果文件过大时,造成内存溢出

      实现类:QDomDocument
      .Pro文件加上 QT += xml

      使用示例:
            QDomDocument doc(“mydocument”);
            QFile file(“mydocument.xml”);
            if (!file.open(QIODevice::ReadOnly))
            return;
            if (!doc.setContent(&file))
            {
                 file.close();
                 return;
            }
            file.close();

            通过setContent将指定的内容指定给QDomDocument解析,解析成功得到一个完整的QDomDocument对象doc,只要访问doc的节点就能得到XML上的内容。

2)sax (Simple API for XML)

      按阶段将文档读取到内存中,进行边读边解析,从上到下,一行一行解析对象,返回对象名称。

      优点:不存在内存溢出,方便实现查询
      缺点:不便于随机访问任意节点

      实现类:QXmlSimpleReader

      使用示例:
            QFile file(“mydocument.xml”);
            QXmlStreamReader xmlRead; //创建一个类对象
            xmlRead.setDevice(&file); //通过setDevice设置要处理的XML文件
            if(xmlRead.readNextStartElement()) //挨个读入节点
            {
                if(xmlRead.name().toString() == “root”)
                {
                    if(xmlRead.readNextStartElement())
                    {
                        if(xmlRead.name().toString() == “config”)
                        {
                            …
                        }
                    }
                }
            }

三、CSV与XML的区别:

1)CSV

      格式语法不同,CSV每条记录占一行,以逗号为分隔符,逗号前后的空格会被忽略。
CSV格式很简单。 它具有包含类别和术语及其属性值(例如描述,缩写和自定义属性值)的功能。 它还使您能够定义管家关系。

2)XML

      XML格式更全面,更复杂。 它具有定义术语,类别和其他对象类型(包括与其他术语有关的术语,与术语有关的类别,链接到已分配资产的术语)之间的每种可能关系的功能。

四、XML语法注意点:

1)一个xml元素可以包含字母、数字以及其他一些可见字符:

      1.不可以数字或部分标点符号开头
      2.不能包含空格和特定的几个符号
      3.标签必须成对出现,不允许缺省结束标签
      4.根元素有且只有一个,必须包含根元素
      5.大小写敏感
      6.允许多层嵌套但是不允许交叉嵌套

2)注释

      1.注释内容中不要出现–
      2.不要把注释放在标签中间
      3.注释不能嵌套

五、XML读写demo:

1)界面

在这里插入图片描述

2)核心代码

ctxml.h

#ifndef CTXML_H
#define CTXML_H
#include <QObject>
#include "commondef.h"

class CtXml : public QObject
{
    Q_OBJECT
public:
    CtXml();
    ~CtXml();
    static CtXml& getInstance();
signals:
    void sig_returnXmlData(PERSION_T stPersion);

public slots:
    void on_writeToXmlFileWithDom(PERSION_T stPersion);
    void on_readFromXmlFileWithDom();

    void on_writeToXmlFileWithSax(PERSION_T stPersion);
    void on_readFormXmlFileWithSax();
};

#endif // CTXML_H

ctxml.cpp

#include "ctxml.h"
#include <QDomDocument>
#include <QFile>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>

CtXml::CtXml()
{
}

CtXml::~CtXml()
{
}

CtXml &CtXml::getInstance()
{
    static CtXml s_obj;
    return s_obj;
}

void CtXml::on_writeToXmlFileWithDom(PERSION_T stPersion)
{
    QDomDocument dDoc;
    QString sHeader("version=\"1.0\" encoding=\"UTF-8\"");
    dDoc.appendChild(dDoc.createProcessingInstruction("xml", sHeader));//生成说明
    //生成根节点
    QDomElement sRootElement = dDoc.createElement("Root");
    dDoc.appendChild(sRootElement);

    QDomElement PersionElement = dDoc.createElement("Persion");

    QDomElement Item1Element = dDoc.createElement("Item");
    Item1Element.setAttribute("Name", "Name");
    Item1Element.setAttribute("Type", "QString");
    QDomText Item1Text = dDoc.createTextNode("Item");
    Item1Text.setData(stPersion.sName);
    Item1Element.appendChild(Item1Text);
    PersionElement.appendChild(Item1Element);

    QDomElement Item2Element = dDoc.createElement("Item");
    Item2Element.setAttribute("Name", "Age");
    Item2Element.setAttribute("Type", "Int");
    QDomText Item2Text = dDoc.createTextNode("Item");
    Item2Text.setData(QString::number(stPersion.nAge));
    Item2Element.appendChild(Item2Text);
    PersionElement.appendChild(Item2Element);

    QDomElement Item3Element = dDoc.createElement("Item");
    Item3Element.setAttribute("Name", "Sex");
    Item3Element.setAttribute("Type", "QString");
    QDomText Item3Text = dDoc.createTextNode("Item");
    Item3Text.setData(stPersion.Sex);
    Item3Element.appendChild(Item3Text);
    PersionElement.appendChild(Item3Element);

    QDomElement Item4Element = dDoc.createElement("Item");
    Item4Element.setAttribute("Name", "Height");
    Item4Element.setAttribute("Type", "Int");
    QDomText Item4Text = dDoc.createTextNode("Item");
    Item4Text.setData(QString::number(stPersion.nHeight));
    Item4Element.appendChild(Item4Text);
    PersionElement.appendChild(Item4Element);

    QDomElement Item5Element = dDoc.createElement("Item");
    Item5Element.setAttribute("Name", "Weight");
    Item5Element.setAttribute("Type", "Int");
    QDomText Item5Text = dDoc.createTextNode("Item");
    Item5Text.setData(QString::number(stPersion.nWeight));
    Item5Element.appendChild(Item5Text);
    PersionElement.appendChild(Item5Element);

    sRootElement.appendChild(PersionElement);

    QFile file(XML_FILE_PATH);
    if(!file.open(QFile::WriteOnly | QFile::Text | QFile :: Truncate))//Truncate:覆盖重写
    {
        MY_DEBUG << "Open XML File Failed";
        return;
    }

    file.write(dDoc.toString().toLocal8Bit().data());
    file.close();
}

void CtXml::on_readFromXmlFileWithDom()
{
    QDomDocument dDoc;
    QFile file(XML_FILE_PATH);
    if(!file.open(QFile::ReadOnly | QFile::Text))
    {
        MY_DEBUG << "Open XML File Failed";
        return;
    }

    int iErrorLine;
    int iErrorCol;
    QString sErrorMsg;
    if (!dDoc.setContent(&file, false, &sErrorMsg, &iErrorLine, &iErrorCol))
    {
        sErrorMsg = QString::fromLocal8Bit("Parse Failed.");
        MY_DEBUG << "sErrorMsg:" << sErrorMsg;
        file.close();
        return;
    }
    file.close();

    PERSION_T stPersion;
    QDomElement deRootNode = dDoc.documentElement();
    if(deRootNode.tagName() == "Root")
    {
        MY_DEBUG << "readFromXmlFileWithDom 000";
        QDomNode PersionNode = deRootNode.firstChild();
        while(!PersionNode.isNull())
        {
            MY_DEBUG << "readFromXmlFileWithDom 111";
            QString sPersion = PersionNode.toElement().tagName();
            if(!sPersion.compare("Persion"))
            {
                MY_DEBUG << "readFromXmlFileWithDom 222";
                QDomNodeList ItemNodeList = PersionNode.childNodes();
                for(int i = 0; i < ItemNodeList.size(); i++)
                {
                    MY_DEBUG << "readFromXmlFileWithDom 333";
                    QDomElement ItemElement = ItemNodeList.at(i).toElement();
                    if(!ItemElement.tagName().compare("Item"))
                    {
                        MY_DEBUG << "readFromXmlFileWithDom 444";
                        if(ItemElement.hasAttribute("Name"))
                        {
                            MY_DEBUG << "readFromXmlFileWithDom 555";
                            QString str = ItemElement.attribute("Name");
                            if(!str.compare("Name"))
                            {
                                stPersion.sName = ItemElement.text();
                            }
                            else if(!str.compare("Age"))
                            {
                                stPersion.nAge = ItemElement.text().toInt();
                            }
                            else if(!str.compare("Sex"))
                            {
                                stPersion.Sex = ItemElement.text();
                            }
                            else if(!str.compare("Height"))
                            {
                                stPersion.nHeight = ItemElement.text().toInt();
                            }
                            else if(!str.compare("Weight"))
                            {
                                stPersion.nWeight = ItemElement.text().toInt();
                            }
                        }
                    }
                }
            }
            PersionNode = PersionNode.nextSibling();
        }
    }
    emit sig_returnXmlData(stPersion);
}

void CtXml::on_writeToXmlFileWithSax(PERSION_T stPersion)
{
    QFile file(XML_FILE_PATH2);
    if(!file.open(QFile::WriteOnly | QFile::Text | QFile :: Truncate))
    {
        MY_DEBUG << "XML File Open Failed.";
        return;
    }
    QXmlStreamWriter xmlWrite(&file);
    xmlWrite.setAutoFormatting(true);
    xmlWrite.writeStartDocument("1.0",true);
    xmlWrite.writeStartElement("Root");
    xmlWrite.writeStartElement("Persion");

    xmlWrite.writeStartElement ("Item");
    xmlWrite.writeAttribute("Name","Name");
    xmlWrite.writeAttribute("Type","QString");
    xmlWrite.writeCharacters(stPersion.sName);
    xmlWrite.writeEndElement();

    xmlWrite.writeStartElement ("Item");
    xmlWrite.writeAttribute("Name","Age");
    xmlWrite.writeAttribute("Type","Int");
    xmlWrite.writeCharacters(QString::number(stPersion.nAge));
    xmlWrite.writeEndElement();

    xmlWrite.writeStartElement ("Item");
    xmlWrite.writeAttribute("Name","Sex");
    xmlWrite.writeAttribute("Type","QString");
    xmlWrite.writeCharacters(stPersion.Sex);
    xmlWrite.writeEndElement();

    xmlWrite.writeStartElement ("Item");
    xmlWrite.writeAttribute("Name","Height");
    xmlWrite.writeAttribute("Type","Int");
    xmlWrite.writeCharacters(QString::number(stPersion.nHeight));
    xmlWrite.writeEndElement();

    xmlWrite.writeStartElement ("Item");
    xmlWrite.writeAttribute("Name","Weight");
    xmlWrite.writeAttribute("Type","Int");
    xmlWrite.writeCharacters(QString::number(stPersion.nWeight));
    xmlWrite.writeEndElement();

    xmlWrite.writeEndElement();    //Persion结束
    xmlWrite.writeEndElement();    //Root结束
    xmlWrite.writeEndDocument();   //Document结束

    file.close();
}

void CtXml::on_readFormXmlFileWithSax()
{
    QFile file(XML_FILE_PATH2);
    if(!file.open(QFile::ReadOnly | QFile::Text))
    {
        MY_DEBUG << "XML File Open Failed.";
        return;
    }

    PERSION_T stPersion;
    QXmlStreamReader xmlRead;
    xmlRead.setDevice(&file);
    if(xmlRead.readNextStartElement())
    {
        if(xmlRead.name().toString() == "Root")
        {
           if(xmlRead.readNextStartElement())
           {
               if(xmlRead.name().toString() == "Persion")
               {
                   while(xmlRead.readNextStartElement()) //循环读取Item
                   {
                      if(xmlRead.name().toString() == "Item")
                      {
                          QXmlStreamAttributes attributes = xmlRead.attributes();
                          if(attributes.hasAttribute("Name"))
                          {
                              QString sName = attributes.value("Name").toString();
                              if(!sName.compare("Name"))
                              {
                                  stPersion.sName = xmlRead.readElementText();
                              }
                              else if(!sName.compare("Age"))
                              {
                                  stPersion.nAge = xmlRead.readElementText().toInt();
                              }
                              else if(!sName.compare("Sex"))
                              {
                                  stPersion.Sex = xmlRead.readElementText();
                              }
                              else if(!sName.compare("Height"))
                              {
                                  stPersion.nHeight = xmlRead.readElementText().toInt();
                              }
                              else if(!sName.compare("Weight"))
                              {
                                  stPersion.nWeight = xmlRead.readElementText().toInt();
                              }
                              else
                              {
                                  xmlRead.readNextStartElement();
                              }
                          }
                      }
                   }
               }
           }
        }
    }
    emit sig_returnXmlData(stPersion);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "commondef.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void sig_writeToXmlFileWithDom(PERSION_T stPersion);
    void sig_readFromXmlFileWithDom();
    void sig_writeToXmlFileWithSax(PERSION_T stPersion);
    void sig_readFormXmlFileWithSax();

public slots:
    void on_returnXmlData(PERSION_T stPersion);

private slots:
    void on_pushButton_Save_Dom_clicked();
    void on_pushButton_Read_Dom_clicked();
    void on_pushButton_Save_Sax_clicked();
    void on_pushButton_Read_Sax_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ctxml.h"
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qRegisterMetaType<PERSION_T>("PERSION_T");
    connect(&CtXml::getInstance(), SIGNAL(sig_returnXmlData(PERSION_T)),
            this, SLOT(on_returnXmlData(PERSION_T)));
    connect(this, SIGNAL(sig_writeToXmlFileWithDom(PERSION_T)),
            &CtXml::getInstance(), SLOT(on_writeToXmlFileWithDom(PERSION_T)));
    connect(this, SIGNAL(sig_readFromXmlFileWithDom()),
            &CtXml::getInstance(), SLOT(on_readFromXmlFileWithDom()));
    connect(this, SIGNAL(sig_writeToXmlFileWithSax(PERSION_T)),
            &CtXml::getInstance(), SLOT(on_writeToXmlFileWithSax(PERSION_T)));
    connect(this, SIGNAL(sig_readFormXmlFileWithSax()),
            &CtXml::getInstance(), SLOT(on_readFormXmlFileWithSax()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_returnXmlData(PERSION_T stPersion)
{
    ui->lineEdit_Age->setText(QString::number(stPersion.nAge));
    ui->lineEdit_Sex->setText(stPersion.Sex);
    ui->lineEdit_Name->setText(stPersion.sName);
    ui->lineEdit_Height->setText(QString::number(stPersion.nHeight));
    ui->lineEdit_Weight->setText(QString::number(stPersion.nWeight));
}

void MainWindow::on_pushButton_Save_Dom_clicked()
{
    PERSION_T stPersion;
    stPersion.Sex = ui->lineEdit_Sex->text();
    stPersion.nAge = ui->lineEdit_Age->text().toInt();
    stPersion.sName = ui->lineEdit_Name->text();
    stPersion.nHeight = ui->lineEdit_Height->text().toInt();
    stPersion.nWeight = ui->lineEdit_Weight->text().toInt();

    emit sig_writeToXmlFileWithDom(stPersion);

    QMessageBox::information(this, "Tip", "Save Xml With Dom Success.");
}

void MainWindow::on_pushButton_Read_Dom_clicked()
{
    emit sig_readFromXmlFileWithDom();
}

void MainWindow::on_pushButton_Save_Sax_clicked()
{
    PERSION_T stPersion;
    stPersion.Sex = ui->lineEdit_Sex->text();
    stPersion.nAge = ui->lineEdit_Age->text().toInt();
    stPersion.sName = ui->lineEdit_Name->text();
    stPersion.nHeight = ui->lineEdit_Height->text().toInt();
    stPersion.nWeight = ui->lineEdit_Weight->text().toInt();

    emit sig_writeToXmlFileWithSax(stPersion);

    QMessageBox::information(this, "Tip", "Save Xml With Sax Success.");
}

void MainWindow::on_pushButton_Read_Sax_clicked()
{
    emit sig_readFormXmlFileWithSax();
}

3)demo工程下载

下载地址链接:https://download.csdn.net/download/linyibin_123/87374629

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅笑一斤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值