XML(ExtensibleMarkup Language,可扩展标记语言),是一种类似于HTML的标记语言,但它的设计目的是用来传输数据,而不是显示数据。XML的标签没有被预定义,用户需要在使用时自行进行定义。XML是W3C(万维网联盟)的推荐标准。相对于数据库表格的二维表示,XML使用的树形结构更能表现出数据的包含关系,作为一种文本文件格式,XML简单明了的特性使得它在信息存储和描述领域非常流行。
在Qt中提供了QtXml模块来进行XML文档的处理,我们在Qt帮助中输入关键字QtXml Module,可以看到该模块的类表。这里主要提供了三种解析方法: DOM方法,可以进行读写;SAX方法,可以进行读取;基于流的方法,分别使用QXmlStreamReader和QXmlStreamWriter进行读取和写入。要在项目中使用QtXml模块,还需要在项目文件(.pro文件)中添加QT += xml一行代码。
新建一个项目
ui 界面
pro 文件
QT += core gui xml
.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_pushButton_search_clicked();
void on_pushButton_delete_clicked();
void on_pushButton_update_clicked();
void on_pushButton_add_clicked();
void on_pushButton_selectAll_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
.cpp 文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtXml>
#include <QFile>
#include <QDomComment>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFile file("my.xml");
if(!file.open(QIODevice::WriteOnly |QIODevice::Truncate))
{
return;
}
QDomDocument doc;
QDomProcessingInstruction instruction; //添加处理指令
instruction = doc.createProcessingInstruction("xml","version=\"1.0\"encoding=\"UTF-8\"");
doc.appendChild(instruction);
QDomElement root = doc.createElement(tr("书库"));
doc.appendChild(root); //添加根元素
// 添加第一个book元素及其子元素
QDomElement book = doc.createElement(tr("图书"));
QDomAttr id = doc.createAttribute(tr("编号"));
QDomElement title = doc.createElement(tr("书名"));
QDomElement author = doc.createElement(tr("作者"));
QDomText text;
id.setValue(tr("1"));
book.setAttributeNode(id);
text = doc.createTextNode(tr("Qt"));
title.appendChild(text);
text = doc.createTextNode(tr("shiming"));
author.appendChild(text);
book.appendChild(title);
book.appendChild(author);
root.appendChild(book);
// 添加第二个book元素及其子元素
book = doc.createElement(tr("图书"));
id = doc.createAttribute(tr("编号"));
title = doc.createElement(tr("书名"));
author = doc.createElement(tr("作者"));
id.setValue(tr("2"));
book.setAttributeNode(id);
text = doc.createTextNode(tr("Linux"));
title.appendChild(text);
text = doc.createTextNode(tr("yafei"));
author.appendChild(text);
book.appendChild(title);
book.appendChild(author);
root.appendChild(book);
QTextStream out(&file);
doc.save(out,4); // 将文档保存到文件,4为子元素缩进字符数
file.close();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::doXml(const QString operate)
{
ui->listWidget->clear();
ui->listWidget->addItem(tr("没有找到相关内容!"));
QFile file("my.xml");
if (!file.open(QIODevice::ReadOnly)) return ;
QDomDocument doc;
if (!doc.setContent(&file))
{
file.close();
return ;
}
file.close();
QDomNodeList list = doc.elementsByTagName(tr("图书"));
// 以标签名进行查找
for(int i=0; i<list.count(); i++)
{
QDomElement e = list.at(i).toElement();
// 如果元素的“编号”属性值与我们所查的相同
if(e.attribute(tr("编号")) == ui->lineEdit_id->text())
{
// 如果元素的“编号”属性值与我们所查的相同
if(operate == "delete") //如果是删除操作
{
QDomElement root = doc.documentElement(); //取出根节点
root.removeChild(list.at(i)); //从根节点上删除该节点
QFile file("my.xml"); //保存更改
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
return ;
QTextStream out(&file);
doc.save(out,4);
file.close();
ui->listWidget->clear();
ui->listWidget->addItem(tr("删除成功!"));
}
else if(operate == "update") //如果是更新操作
{
QDomNodeList child = list.at(i).childNodes();
//找到它的所有子节点,就是“书名”和“作者”
child.at(0).toElement().firstChild().setNodeValue(ui->lineEdit_title->text());
//将它子节点的首个子节点(就是文本节点)的内容更新
child.at(1).toElement().firstChild().setNodeValue(ui->lineEdit_author->text());
QFile file("my.xml"); //保存更改
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
return ;
QTextStream out(&file);
doc.save(out,4); //保存文档,4为子元素缩进字符数
file.close();
ui->listWidget->clear();
ui->listWidget->addItem(tr("更新成功!"));
}
else if(operate == "find") //如果是查找操作
{
ui->listWidget->clear();
ui->listWidget->addItem(e.tagName()+e.attribute(tr("编号")));
QDomNodeList list = e.childNodes();
for(int i=0; i<list.count(); i++)
{
QDomNode node = list.at(i);
if(node.isElement())
ui->listWidget->addItem(" "+node.toElement().tagName()
+" : "+node.toElement().text());
}
}
}
}
}
void MainWindow::on_pushButton_search_clicked()
{
doXml("find");
}
void MainWindow::on_pushButton_delete_clicked()
{
doXml("delete");
}
void MainWindow::on_pushButton_update_clicked()
{
doXml("update");
}
void MainWindow::on_pushButton_add_clicked()
{
ui->listWidget->clear(); //我们先清空显示,然后显示“无法添加!”
ui->listWidget->addItem(tr("无法添加!"));
QFile file("my.xml");
if (!file.open(QIODevice::ReadOnly)) return;
QDomDocument doc;
if (!doc.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement root = doc.documentElement();
QDomElement book = doc.createElement(tr("图书"));
QDomAttr id = doc.createAttribute(tr("编号"));
QDomElement title = doc.createElement(tr("书名"));
QDomElement author = doc.createElement(tr("作者"));
QDomText text;
// 我们获得了最后一个孩子结点的编号,然后加1,便是新的编号
QString num = root.lastChild().toElement().attribute(tr("编号"));
int count = num.toInt() +1;
id.setValue(QString::number(count));
book.setAttributeNode(id);
text = doc.createTextNode(ui->lineEdit_title->text());
title.appendChild(text);
text = doc.createTextNode(ui->lineEdit_author->text());
author.appendChild(text);
book.appendChild(title);
book.appendChild(author);
root.appendChild(book);
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
return ;
QTextStream out(&file);
doc.save(out,4); //将文档保存到文件,4为子元素缩进字符数
file.close();
ui->listWidget->clear(); //最后更改显示为“添加成功!”
ui->listWidget->addItem(tr("添加成功!"));
}
//读取所有的数据
void MainWindow::on_pushButton_selectAll_clicked()
{
ui->listWidget->clear();
QFile file("my.xml");
if(!file.open(QIODevice::ReadOnly)){
return;
}
QDomDocument doc;
if (!doc.setContent(&file))
{
file.close();
return ;
}
file.close();
//返回根节点及其子节点的元素标记名
QDomElement docElem = doc.documentElement(); //返回根元素
QDomNode n = docElem.firstChild(); //返回根节点的第一个子节点
while(!n.isNull()) //如果节点不为空
{
if (n.isElement()) //如果节点是元素
{
QDomElement e = n.toElement(); //将其转换为元素
ui->listWidget->addItem(e.tagName()+e.attribute(tr("编号")));
QDomNodeList list = e.childNodes();
for(int i=0; i<list.count(); i++)
{
QDomNode node = list.at(i);
if(node.isElement())
ui->listWidget->addItem(" "+node.toElement().tagName()+" : "+node.toElement().text());
}
}
n = n.nextSibling(); //下一个兄弟节点
}
}
运行界面如下