QT XML相关QXmlStreamReader,QXmlStreamWriter 读写操作

一、基本介绍

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文件不了解,可先阅读:https://blog.csdn.net/DMC111qwf/article/details/84327075

 

相关头文件:

#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 声明)

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

             

                 XML(1)                                                                                   XML(2)

 

                  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.....

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值