Qt读取XML文件

本文根据霍亚飞老师的《Qt Creator快速入门》(第三版)整理。

读取过程及方式简析:

一、DOM(Document Object Model)方式(可读取,可修改)
XML文档有且只有一个根元素
说明、元素、属性和文本都由QDomNode来表示

           类名                                                      含义
QDomProcessingInstruction                        XML说明
QDomElement                                            表示元素的类
QDomAttr                                                    表示元素属性的类
QDomText                                                   表示文本的类
QDomNode                                                 表示一个节点的类(便捷接口isProcessingInstruction,isElement,isAttr,isText
                                                                     toProcessingInstruction,toElement,toAttr,toText)
QDomDocument                                          表示一个XML文档

读取文件大概操作:
1、使用QFile打开XML文件;
2、使用setContent()函数将文件内容加载到QDomDocument中;
3、使用firstChild()函数获取第一个节点,即XML文件说明,该函数属于QDomNode类,故也可通过该函数获取根节点的第一个子节点;
4、使用QDomDocument::documentElement()获取根元素;
5、使用QDomNode::nodeName()获取节点名称,QDomNode::nodeValue()获取节点值,
      QDomElement::tagName()获取标签名,QDomElement::attribute("attr name")获取属性attr name的值,
      QDomElement::text()获取元素文本名
6、使用QDomNode::nextSibling()转到下一个兄弟节点,QDomElement::childNodes()获取该节点的所有子节点列表


二、SAX(Simple API for XML)方式(读取方便)
1、继承自QXmlDefaultHandler类;
2、主要处理函数     bool startElement(const QString &namespaceURI,const QString &localName,
                                  const QString &qName,const QXmlAttributes &atts);
            bool endElement(const QString &namespaceURI,const QString &localName,    
                                const QString &qName);     //qName为标签名
            bool characters(const QString &ch);    //ch为解析当前节点所得到的文本
            bool fatalError(const QXmlParseException &exception);    //QXmlParseException 为异常类型
3、处理函数readFile(QString fileName)主要思路:
    1)读取文件内容
        QFile lv_file(fileName);
        QXmlnputSource lv_inputSource(&lv_file);
    2) 建立QXmlSimpleReader对象
        QXmlSimpleReader lv_reader;
    3) 设置内容处理器
        lv_reader.setContentHandler(this);
    4) 设置错误处理器
        lv_reader.setErrorHandler(this);
    5) 解析文件
        return lv_reader.parse(lv_inputSource);

代码:

方式一读取显示XML文件实例:

//.pro文件 注意读取XML文件要添加一句 : QT  += xml

QT += core
QT -= gui
CONFIG += c++11
QT += xml
TARGET = myDOM1
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
//main.cpp文件
#include <QCoreApplication>
#include <QtXml>
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //新建QDomDocument类对象,代表一个XML文档
    QDomDocument lv_doc;
    QFile lv_file("../myDOM1/my.xml");
    if ( !lv_file.open(QIODevice::ReadOnly))
    {
        return 0;
    }
    //将文件内容读到doc中
    if ( !lv_doc.setContent(&lv_file) )
    {
        lv_file.close();
        return 0;
    }
    //关闭文件
    lv_file.close();
    //获取lv_doc的第一个节点,即XML说明
    QDomNode lv_firstNode = lv_doc.firstChild();
    //输出XML说明,nodeName()为“xml",nodeValue()为版本和编码信息
    qDebug()<<qPrintable(lv_firstNode.nodeName())<<qPrintable(lv_firstNode.nodeValue());
    //返回根元素
    QDomElement lv_docElem = lv_doc.documentElement();
    //返回根节点的第一个子节点
    QDomNode lv_n = lv_docElem.firstChild();
    //如果节点不为空,转到下一个节点
    while( !lv_n.isNull() )
    {
        //如果节点是元素
        if ( lv_n.isElement() )
        {
            //将其转为元素
            QDomElement lv_e = lv_n.toElement();
            //返回元素标记和id属性的值
            qDebug()<<qPrintable(lv_e.tagName())<<"  "<<qPrintable(lv_e.attribute("id"));
            //获取元素lv_e的所有子节点的列表
            QDomNodeList lv_list = lv_e.childNodes();
            //遍历该列表
            for ( int i = 0; i < lv_list.count(); ++i)
            {
                QDomNode lv_node = lv_list.at(i);
                if ( lv_node.isElement() )
                {
                    qDebug()<<"    "<<qPrintable(lv_node.toElement().tagName())
                           <<"  "<<qPrintable(lv_node.toElement().text());
                }
            }
        }
        //转到下一个兄弟节点
        lv_n = lv_n.nextSibling();
    }
    return a.exec();
}
方式一读取显示及修改XML文件实例:

//.pro文件

QT       += core gui
QT       += xml
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = myDOM2
TEMPLATE = app
SOURCES += main.cpp\
        mainwindow.cpp
HEADERS  += mainwindow.h
FORMS    += mainwindow.ui

//mainWindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void doXml(const QString operate);
private slots:
    void on_showAllBtn_clicked();
    void on_addBtn_clicked();
    void on_findBtn_clicked();
 
    void on_deleteBtn_clicked();
    void on_updateBtn_clicked();
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
//mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtXml>
#include <QFile>
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    QDomDocument lv_doc;
    //添加处理指令即XML说明
    QDomProcessingInstruction lv_instruction;
    lv_instruction = lv_doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
    lv_doc.appendChild(lv_instruction);
    //添加根元素
    QDomElement lv_root = lv_doc.createElement("书库");
    lv_doc.appendChild(lv_root);
    //添加第一个图书元素及其子元素
    QDomElement lv_book = lv_doc.createElement("图书");
    QDomAttr    lv_id = lv_doc.createAttribute("编号");
    QDomElement lv_title = lv_doc.createElement("书名");
    QDomElement lv_author = lv_doc.createElement("作者");
    QDomText    lv_text;
    lv_id.setValue(QString("1"));
    lv_book.setAttributeNode(lv_id);
    lv_text = lv_doc.createTextNode("Qt");
    lv_title.appendChild(lv_text);
    lv_text = lv_doc.createTextNode("shiming");
    lv_author.appendChild(lv_text);
    lv_book.appendChild(lv_title);
    lv_book.appendChild(lv_author);
    lv_root.appendChild(lv_book);
    //添加第二个图书元素及其子元素
    lv_book = lv_doc.createElement("图书");
    lv_id = lv_doc.createAttribute("编号");
    lv_title = lv_doc.createElement("书名");
    lv_author = lv_doc.createElement("作者");
    lv_id.setValue(QString("2"));
    lv_book.setAttributeNode(lv_id);
    lv_text = lv_doc.createTextNode("Linux");
    lv_title.appendChild(lv_text);
    lv_text = lv_doc.createTextNode("yafei");
    lv_author.appendChild(lv_text);
    lv_book.appendChild(lv_title);
    lv_book.appendChild(lv_author);
    lv_root.appendChild(lv_book);
    QFile lv_file("my.xml");
    if ( !lv_file.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        return ;
    }
    //将文档保存到文件,4为子元素缩进字符数
    QTextStream lv_out(&lv_file);
    lv_doc.save(lv_out,4);
    lv_file.close();
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::doXml(const QString operate)
{
    ui->listWidget->clear();
    ui->listWidget->addItem(tr("没有找到相关内容"));
    QFile lv_file("my.xml");
    if ( !lv_file.open(QIODevice::ReadOnly) )
    {
        return ;
    }
    QDomDocument lv_doc;
    if ( !lv_doc.setContent(&lv_file) )
    {
        lv_file.close();
        return ;
    }
    //以标签名进程查找
    QDomNodeList lv_list = lv_doc.elementsByTagName("图书");
    for ( int i = 0; i < lv_list.size(); ++i)
    {
        QDomElement lv_e = lv_list.at(i).toElement();
        if ( lv_e.attribute("编号") == ui->bookNumLineEdit->text())
        {
            //如果“编号”属性值与所查找的相同
            if ( operate == "delete")
            {
                QDomElement lv_root = lv_doc.documentElement();
                //从根节点上删除该节点
                lv_root.removeChild(lv_list.at(i));
                QFile lv_file("my.xml");
                if ( !lv_file.open(QIODevice::WriteOnly | QIODevice::Truncate) )
                {
                    return;
                }
                QTextStream lv_out(&lv_file);
                lv_doc.save(lv_out,4);
                lv_file.close();
                ui->listWidget->clear();
                ui->listWidget->addItem(tr("删除成功!"));
            }
            else if ( operate == "update")
            {
                QDomNodeList lv_child = lv_list.at(i).childNodes();
                //将塔子节点的首个子节点(就是文本节点)的内容更新
                lv_child.at(0).toElement().firstChild().setNodeValue(ui->bookNameLineEdit->text());
                lv_child.at(1).toElement().firstChild().setNodeValue(ui->authorLineEdit->text());
                QFile lv_file("my.xml");
                if ( !lv_file.open(QIODevice::WriteOnly | QIODevice::Truncate))
                {
                    return;
                }
                QTextStream lv_out(&lv_file);
                lv_doc.save(lv_out,4);
                lv_file.close();
                ui->listWidget->clear();
                ui->listWidget->addItem(tr("更新成功"));
            }
            else if ( operate == "find")
            {
                ui->listWidget->clear();
                ui->listWidget->addItem(lv_e.tagName() + lv_e.attribute("编号"));
                QDomNodeList lv_list = lv_e.childNodes();
                for ( int i = 0; i < lv_list.size(); ++i)
                {
                    QDomNode lv_node = lv_list.at(i);
                    if ( lv_node.isElement())
                    {
                        ui->listWidget->addItem("    " + lv_node.toElement().tagName() + " : "
                                                + lv_node.toElement().text());
                    }
                }
            }
        }
    }
}
 
void MainWindow::on_showAllBtn_clicked()
{
    //先清空显示
    ui->listWidget->clear();
    QFile lv_file("my.xml");
    if ( !lv_file.open(QIODevice::ReadOnly) )
    {
        return ;
    }
    QDomDocument lv_doc;
    if ( !lv_doc.setContent(&lv_file))
    {
        lv_file.close();
        return ;
    }
    lv_file.close();
    QDomElement lv_docElem = lv_doc.documentElement();  //获取根元素
    QDomNode lv_n = lv_docElem.firstChild();
    while ( !lv_n.isNull() )    //遍历根节点及其子节点
    {
        if ( lv_n.isElement() )
        {
            QDomElement lv_e = lv_n.toElement();
            ui->listWidget->addItem(lv_e.tagName()+lv_e.attribute("编号"));
            QDomNodeList lv_list = lv_e.childNodes();
            for ( int i = 0; i < lv_list.size(); ++i )
            {
                QDomNode lv_node = lv_list.at(i);
                ui->listWidget->addItem("    "+lv_node.toElement().tagName()+":"+lv_node.toElement().text());
            }
        }
 
        lv_n = lv_n.nextSibling();
    }
}
 
void MainWindow::on_addBtn_clicked()
{
    //先清空显示,然后显示“无法添加!”,这样如果添加失败则会显示“无法添加!”
    ui->listWidget->clear();
    ui->listWidget->addItem(tr("无法添加!"));
    QFile lv_file("my.xml");
    if ( !lv_file.open(QIODevice::ReadOnly) )
    {
        return;
    }
    QDomDocument lv_doc;
    if ( !lv_doc.setContent(&lv_file))
    {
        lv_file.close();
        return;
    }
    lv_file.close();
    QDomElement lv_root = lv_doc.documentElement(); //获取根节点
    QDomElement lv_book = lv_doc.createElement("图书");
    QDomAttr    lv_id = lv_doc.createAttribute("编号");
    QDomElement lv_title = lv_doc.createElement("书名");
    QDomElement lv_author = lv_doc.createElement("作者");
    QDomText lv_text;
    //我们获得了最后一个孩子节点的编号,然后加上1,便是新的编号
    QString lv_num = lv_root.lastChild().toElement().attribute("编号");
    int lv_count = lv_num.toInt() + 1;
    lv_id.setValue(QString::number(lv_count));
    lv_book.setAttributeNode(lv_id);
    lv_text = lv_doc.createTextNode(ui->bookNameLineEdit->text());
    lv_title.appendChild(lv_text);
    lv_text = lv_doc.createTextNode(ui->authorLineEdit->text());
    lv_author.appendChild(lv_text);
    lv_book.appendChild(lv_title);
    lv_book.appendChild(lv_author);
    lv_root.appendChild(lv_book);
    if ( !lv_file.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        return ;
    }
    QTextStream lv_out(&lv_file);
    lv_doc.save(lv_out,4);
    lv_file.close();
    //最后显示为“添加成功!“
    ui->listWidget->clear();
    ui->listWidget->addItem(tr("添加成功!"));
}
 
void MainWindow::on_findBtn_clicked()
{
    doXml("find");
}
 
void MainWindow::on_deleteBtn_clicked()
{
    doXml("delete");
}
 
void MainWindow::on_updateBtn_clicked()
{
    doXml("update");
}
//main.cpp文件
#include "mainwindow.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
方式二读取显示XML实例:

//mySAX.pro

QT += xml widgets
 
HEADERS += \
    mysax.h
 
SOURCES += \
    mysax.cpp \
    main.cpp
//mysax.h
#ifndef MYSAX_H
#define MYSAX_H
 
#include <QXmlDefaultHandler>
class QListWidget;
 
class MySAX : public QXmlDefaultHandler
{
public:
    MySAX();
    ~MySAX();
    bool readFile(const QString &fileName);
protected:
    bool startElement(const QString &namespaceURI,const QString &localName,
                      const QString &qName,const QXmlAttributes &atts);
    bool endElement(const QString &namespaceURI,const QString &localName,
                    const QString &qName);
    bool characters(const QString &ch);
    bool fatalError(const QXmlParseException &exception);
private:
    QListWidget *m_list;
    QString      m_currentText;
 
};
#endif // MYSAX_H
//mysax.cpp
#include "mysax.h"
#include <QtXml>
#include <QListWidget>
 
MySAX::MySAX()
{
    m_list = new QListWidget;
    m_list->show();
}
 
MySAX::~MySAX()
{
    delete m_list;
    m_list = NULL;
}
 
bool MySAX::readFile(const QString &fileName)
{
    QFile lv_file(fileName);
    //读取文件内容
    QXmlInputSource lv_inputSource(&lv_file);
    //建立QXmlSimpleReader对象
    QXmlSimpleReader lv_reader;
    //设置内容处理器
    lv_reader.setContentHandler(this);
    //设置错误处理器
    lv_reader.setErrorHandler(this);
    //解析文件
    return lv_reader.parse(lv_inputSource);
}
 
bool MySAX::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
{
    //已解析完一个元素的起始标签
    if ( qName == "library")    //根节点(根元素)
    {
        m_list->addItem(qName);
    }
    else if ( qName == "book")  //图书节点(次层节点)
    {
        m_list->addItem("    " + qName + atts.value("id"));
    }
    return true;
}
 
bool MySAX::endElement(const QString &namespaceURI, const QString &localName, const QString &qName)
{
    //已经解析完一个元素的结束标签        qName是标签名
    if ( qName == "title" || qName == "author")
    {
        m_list->addItem("        " + qName + " : " + m_currentText);
    }
    return true;
}
 
bool MySAX::characters(const QString &ch)
{
    //已解析完一块字符数据
    m_currentText = ch;
    return true;
}
 
bool MySAX::fatalError(const QXmlParseException &exception)
{
    //错误处理
    qDebug()<<exception.message();
    return false;
}
//main.cpp
#include "mysax.h"
#include <QApplication>
 
int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    MySAX sax;
    sax.readFile("../mySAX/my.xml");
    return app.exec();
}
  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值