一、基本介绍

1 老版的Qt提供了两种访问XML文件的方式:DOM和SAX。

2 DOM 方式:将 XML 文档转换为树形结构存储到内存中,再进行读取,消耗的内存比较多。此外,由于文档都已经存储到内存,所以需要频繁实现修改等操作时,使用起来比较方便。

3 SAX 方式:相比于 DOM,SAX 是一种速度更快,更有效的方法,它逐行扫描文档,一边扫描一边解析(由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势)。而且相比于 DOM,SAX 可以在解析文档的任意时刻停止解析。但操作复杂,很难修改 XML 数据。

自QT4.3版本开始,QT提供了两个新类来读写XML:QXmlStreamReader 和 QXmlStreamWriter。读写方式可类比于SAX。目前QT已经停止对DOM和SAX的维护与更新。

4 QXmlStreamWriter 类提供了一个使用简单的流 API,用于写入 XML,与之相对应的是 QXmlStreamReader(读取 XML)。

5 QXmlStreamReader类支持对XML读取的操作。对于 XML 的内容,通常情况下,我们只关心 XML 元素的解析。这时,可以通过 QXmlStreamReader 中的便利函数 readNextStartElement() 来实现。

实例
         1案例介绍:读取qt运行当前目录下所有文件,通过类QXmlStreamWriter将其按照xml格式对文件进行写操作,并将xml文件保存在当前目录。通过类QXmlStreamReader读取生成的xml文件,并输出。(注意需要.pro文件中添加 xml 如  QT += xml)

生成的XML文件内容为:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<文件列表>
<目录 Dirname="E:/myTest/myXml/build-myXml-Desktop_Qt_5_9_1_MinGW_32bit-Debug">
<文件名>.qmake.stash</文件名>
<文件名>debug</文件名>
<文件名>fileList.xml</文件名>
<文件名>Makefile</文件名>
<文件名>Makefile.Debug</文件名>
<文件名>Makefile.Release</文件名>
<文件名>release</文件名>
<文件名>ui_widget.h</文件名>
</目录>
</文件列表>

对XML文件不了解,

 

相关头文件:

#include <QXmlStreamAttributes>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>

XML写存函数:

QDir *dir=new QDir(".");
void writeFile(){

QFileInfoList infoList = dir->entryInfoList();
infoList.removeFirst();
infoList.removeFirst();
QString strFile("fileList.xml");
QFile file(strFile);
if (!file.open(QFile::WriteOnly | QFile::Text)) { // 只写模式打开文件
qDebug() << QString("Cannot write file %1(%2).").arg(strFile).arg(file.errorString());
return;
}
QXmlStreamWriter writer(&file);
writer.setCodec("UTF-8"); // XML 编码
writer.setAutoFormatting(true); // 自动格式化
writer.writeStartDocument("1.0", true); // 开始文档(XML 声明)
writer.writeStartElement("文件列表"); // 开始根元素 <Blogs>
writer.writeStartElement("目录"); // 开始子元素 <Blog>
QString DirName = dir->currentPath();
writer.writeAttribute("Dirname", DirName); // 属性
foreach (QFileInfo info, infoList) {
QString fileName = info.fileName();
writer.writeTextElement("文件名", fileName);
}
writer.writeEndElement(); // 结束子元素 </Blog>
writer.writeEndElement(); // 结束根元素 </Blogs>
writer.writeEndDocument(); // 结束文档
file.close();
}

XML读取函数: 

void readFile(){
QString strFile("fileList.xml");
QFile file(strFile);
if (!file.open(QFile::ReadOnly | QFile::Text)) { // 只写模式打开文件
qDebug() << QString("Cannot write file %1(%2).").arg(strFile).arg(file.errorString());
return;
}
QXmlStreamReader reader(&file);
while(!reader.atEnd()){
QXmlStreamReader::TokenType nType = reader.readNext();
if( nType == QXmlStreamReader::StartElement ){
QString nameStr = reader.name().toString();
QXmlStreamAttributes Attributes = reader.attributes();
if(Attributes.hasAttribute("Dirname")){
qDebug()<<Attributes.value("Dirname").toString();
}
if(QString::compare(nameStr,QStringLiteral("文件名")) == 0) {
reader.readNext();
qDebug() << QStringLiteral("文件名:%1").arg(reader.text().toString());
// qDebug() << QStringLiteral("文件名:%1").arg(reader.readElementText()); //该语句等效于上面两条语句

}
}
}
}

读取的文件格式: 

"E:/myTest/myXml/build-myXml-Desktop_Qt_5_9_1_MinGW_32bit-Debug"
"文件名:.qmake.stash"
"文件名:debug"
"文件名:fileList.xml"
"文件名:Makefile"
"文件名:Makefile.Debug"
"文件名:Makefile.Release"
"文件名:release"
"文件名:ui_widget.h"

 

参考对比分析xml的写存:

安装基本例子,设置  writer.setCodec("UTF-8");  // XML 编码
    writer.setAutoFormatting(true); // 自动格式化
    writer.writeStartDocument("1.0", true);  // 开始文档(XML 声明)

应该不会出现中文乱码,否则可能出现中文乱码,建议不使用中文。

QT XML相关QXmlStreamReader,QXmlStreamWriter 读写操作_文件名

             

QT XML相关QXmlStreamReader,QXmlStreamWriter 读写操作_QXmlStreamWriter _02

                 XML(1)                                                                                   XML(2)

 

QT XML相关QXmlStreamReader,QXmlStreamWriter 读写操作_文件名_03

                  XML(3)

总结:writeEmptyElement();是一个空节点,里面不存在其他节点,因此结尾是/>,writeEmptyElement()相当于在:

writer->writeStartElement("po");
 writer->writeEndElement();

两句中不插入任何节点,因此为空节点,空节点也可以添加属性值,空节点的结尾和其他节点的结尾不同,以/>结尾。

writer->writeTextElement("name", "ssssssssssssss");不是空节点,是文本节点,具有正常的结尾。

QString::compare(reader.name().toString(),QStringLiteral("文件名")) == 0

reader.text()

writer->writeStartElement("po");
 writer->writeEndElement();

都是成对出现的;

   XML(1) 代码:   

bool Annotation::toXML(QXmlStreamWriter* writer) const {
if (!writer)
return false;

QString number;
writer->writeStartElement("annotation");
if (!_comments.isEmpty())
writer->writeAttribute("comments", _comments);
if (_positionSet) {
writer->writeEmptyElement("position");
writer->writeAttribute("x", number.setNum(_position[0]));
writer->writeAttribute("y", number.setNum(_position[1]));
writer->writeAttribute("z", number.setNum(_position[2]));
writer->writeEmptyElement("po");

}
writer->writeStartElement("mulu");
writer->writeTextElement("name", "ssssssssssssss");
writer->writeEndElement();
writer->writeEndElement(); //annotation

if (writer->hasError())
return false;

return true;
}

   XML(2) 代码:   

bool Annotation::toXML(QXmlStreamWriter* writer) const {
if (!writer)
return false;

QString number;
writer->writeStartElement("annotation");
if (!_comments.isEmpty())
writer->writeAttribute("comments", _comments);
if (_positionSet) {
writer->writeStartElement("position");
writer->writeAttribute("x", number.setNum(_position[0]));
writer->writeAttribute("y", number.setNum(_position[1]));
writer->writeAttribute("z", number.setNum(_position[2]));
writer->writeStartElement("po");
writer->writeEndElement();
writer->writeEndElement(); //annotation

}
writer->writeStartElement("mulu");
writer->writeTextElement("name", "ssssssssssssss");
writer->writeEndElement();
writer->writeEndElement(); //annotation

if (writer->hasError())
return false;

return true;
}

 XML(3) 代码:   

bool Annotation::toXML(QXmlStreamWriter* writer) const {
if (!writer)
return false;

QString number;
writer->writeStartElement("annotation");
if (!_comments.isEmpty())
writer->writeAttribute("comments", _comments);
if (_positionSet) {
writer->writeStartElement("position");
writer->writeAttribute("x", number.setNum(_position[0]));
writer->writeAttribute("y", number.setNum(_position[1]));
writer->writeAttribute("z", number.setNum(_position[2]));
writer->writeEndElement(); //annotation

}
writer->writeStartElement("mulu");
writer->writeTextElement("name", "ssssssssssssss");
writer->writeEndElement();
writer->writeEndElement(); //annotation

if (writer->hasError())
return false;

return true;

参考对比分析xml的读取:

基本介绍中的读取:

总结:读取writeTextElement("name", "ssssssssssssss"),则需要使用  reader.readNext()读取到name后再读取一次,或者直接使用reader.readElementText()进度读取
if(QString::compare(nameStr,QStringLiteral("文件名")) == 0) {
reader.readNext();
qDebug() << QStringLiteral("文件名:%1").arg(reader.text().toString());
// qDebug() << QStringLiteral("文件名:%1").arg(reader.readElementText()); //该语句等效于上面两条语句

}

基本介绍中使用:reader.readNext()循环读取。

while (!reader->atEnd()) {
QXmlStreamReader::TokenType nType = reader->readNext();
if (nType == QXmlStreamReader::StartElement) {
QString nameStr = reader->name().toString();
qDebug() << "test"<<nameStr;
}
}

新的读取方法,使用  reader.readNextStartElement(),reader.readElementText(), reader->readNext()混合进行读取:

需要先调用:

reader.readNextStartElement();

不然读取不到数据。 

bool Annotation::fromXML(QXmlStreamReader* reader) {
if (!reader || "annotation" != reader->name()) {

return false;
}

QXmlStreamAttributes attr;
attr = reader->attributes();
if (attr.hasAttribute("comments")) {
setComments(attr.value("comments").toString());
}
do {
reader->readNext();
} while (reader->isWhitespace());
//reader.readNextStartElement();//可以代替do while语句
if (reader->isStartElement() && "position" == reader->name()) {
attr = reader->attributes();
if (!attr.hasAttribute("x") || !attr.hasAttribute("y") || !attr.hasAttribute("z")) {
qWarning() << Q_FUNC_INFO << "Position missing x, y, or z.";
return false;
}
setPosition(attr.value("x").toString().toDouble(), attr.value("y").toString().toDouble(),
attr.value("z").toString().toDouble());
reader->readNext();
if (!(reader->isEndElement() && "position" == reader->name())) {
qWarning() << Q_FUNC_INFO << "Format error";
return false;
}
do {
reader->readNext();
} while (reader->isWhitespace());
}
if (!(reader->isEndElement() && "annotation" == reader->name())) {
qWarning() << Q_FUNC_INFO << "Format error";
return false;
}

if (reader->hasError()) {
qWarning() << Q_FUNC_INFO << "Reader error";
return false;
}


return true;
}

三、QXmlStreamReader,QXmlStreamWriter 可写入Qstring或者文件

文件读写:

QFile tempFile("annotation_file.xml");
tempFile.open(QFile::WriteOnly | QFile::Text | QIODevice::Truncate);
QXmlStreamWriter writer(&tempFile);

write.....

tempFile.close();

 

QFile tempFile("annotation_file.xml");
tempFile.open(QFile::ReadOnly | QFile::Text | QIODevice::Truncate);
QXmlStreamReader reader(&tempFile);

read....

tempFile.close();
if (tempFile.exists())
{
tempFile.remove();
}

Qstring读写:

QString xml;
QXmlStreamWriter writer(&xml);
write.....

QXmlStreamReader reader(xml);
read.....