22.QT-QXmlStreamReader解析,QXmlStreamWriter写入
XML介绍
XML 用于存储数据,数据的形式类似于树结构(参考: http://www.runoob.com/xml/)
示例如下
<?xml version="1.0" encoding="ISO-8859-1"?> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
其中第一行是XML声明,定义XML版本(1.0)以及所使用的编码格式
接下来的<note>,便是该文档的根元素
剩下的<to>,<from>,<heading>,<body>便是<note>的子元素
QXmlStreamReader
常用函数:
QStringRef documentEncoding(); //获取XML编码,如果XML声明中未指定,则返回NULL
QStringRef documentVersion () ; //获取XML版本,如果XML声明中未指定,则返回NULL
bool atEnd ();
//如果读者一直读到XML文档的末尾,或者出现了错误,并且阅读被中止,那么返回true。否则,它将返回false。
//读取XML内容,如果读到XML末尾,或者读取出错时,将返回true,否则返回false
//当返回true时,可以通过error()判断是否读取出错
Error error () ; //返回错误类型,如果未出错,将返回QXmlStreamReader::NoError(数值0)
void raiseError ( constQString & message = QString() );
//主动上报错误,并填入message 错误信息(可以通过errorString()获取),可以使得下次调用atEnd()时,直接返回true值
QString errorString();
//获取发生的错误信息
void QXmlStreamReader::setDevice ( QIODevice *device );
//设置QXmlStreamReader的解析设备,等价于QXmlStreamReader ( QIODevice *)构造函数
TokenType readNext(); //读取一次记号,并返回该数据的标志位,也可以通过
//常用标记如下所示:
QXmlStreamReader::StartDocument //文档开始位置,用来定义XML版本,编码等信息,
QXmlStreamReader::StartElement //元素开始位置
QXmlStreamReader::EndElement //元素结束位置
//比如<firstname>Anna</firstname>
//<firstname> </firstname>元素便是元素开始以及结束位置.
//“Anna”信息可以通过readElementText()成员函数获取.
QXmlStreamAttributes attributes(); //获取元素的属性
//比如<entry term="of pictures">
//通过attributes().value("term").toString()则可以得到元素值"of pictures"
XML解析示例
以解析G:/QT/in.xml为例,该文件内容如下所示:
<?xml version="1.0"?> <bookindex> <entry term="sidebearings"> <page>10</page> <page>34-35</page> <page>307-308</page> </entry> <entry term="subtraction"> <entry term="of pictures"> <page>115</page> <page>244</page> </entry> <entry term="of vectors"> <page>9</page> </entry> </entry> </bookindex>
代码如下所示:
#include <QtGui>
void ParseEntry(QXmlStreamReader* reader,QTreeWidgetItem* widget) //递归函数,用来解析entry元素
{
QTreeWidgetItem *item =new QTreeWidgetItem(widget); //在widget下创建节点
item->setText(0,reader->attributes().value("term").toString());
//获取entry元素的"term"值,并添加到第1列,比如"sidebearings"
QString pages;
while(!reader->atEnd())
{
QXmlStreamReader::TokenType type=reader->readNext();
if(type==QXmlStreamReader::EndElement && reader->name()=="entry") //如果遇到 </entry>,则表示解析完成
{
break;
}
if(type==QXmlStreamReader::StartElement)
{
if(reader->name()=="entry")
ParseEntry(reader,item); //如果是entry子元素,则继续递归执行
else if(reader->name()=="page")
pages=pages+reader->readElementText()+" "; //如果是page,则获取文本信息
else
reader->raiseError("Element Name Error "); //是其它元素,则上报Error信息
}
}
item->setText(1,pages); //添加页数到第二列
}
void readFile(QFile* File)
{
QXmlStreamReader* reader = new QXmlStreamReader(File);
QTreeWidget* widget = new QTreeWidget();
QStringList header;
header<<"term"<<"page";
widget->setHeaderLabels(header);
while(!reader->atEnd())
{
QXmlStreamReader::TokenType type=reader->readNext();
if(type==QXmlStreamReader::StartElement && reader->name()=="entry")
ParseEntry(reader,widget->invisibleRootItem()); //开始解析"entry"元素里的内容
}
File->close();
widget->show();
if(reader->hasError()) //如果解析出错
{
QMessageBox::information(NULL,"Read","Read :"+reader->errorString());
}
}
int main(int argc, char *argv[])
{
QApplication a(argc,argv);
QFile* File = new QFile("G:/QT/in.xml");
if(!File->open(QFile::ReadOnly | QFile::Text))
{
QMessageBox::information(NULL,"Open","Open error!");
return 0;
}
readFile(File); //解析File
a.exec();
}
效果:
QXmlStreamWriter
常用函数
void setAutoFormatting(bool enable) //设置自动格式化文本,XML文本输出时,转化成容易读的形式,否则,就是一整行
void setAutoFormattingIndent(int spacesOrTabs)//格式化时缩进值,默认4个空格位
void setCodec(const char * codecName );
//设置编码格式,必须放在writeStartDocument()函数前面才起作用
void writeStartDocument();
void writeEndDocument();
void writeStartElement(constQString & qualifiedName );
void writeEndElement()
void writeAttribute( constQString & qualifiedName, const QString & value );
//写入元素的属性值
void writeTextElement( constQString & qualifiedName, const QString & text );
//写入文本元素,比如<page>10</page>等于writeTextElement("page","10");
示例
#include <QtGui>
#include "widget.h"
void WriteEntry(QXmlStreamWriter *writer,QString value,QStringList pages)
{
writer->writeStartElement("entry");
writer->writeAttribute("term",value);
foreach(QString page,pages)
writer->writeTextElement("page",page);
writer->writeEndElement();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file("./out.xml");
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QMessageBox::information(NULL,"Error","Write Error");
return 0;
}
QXmlStreamWriter writer(&file);
writer.setAutoFormatting(true);
writer.writeStartDocument();
WriteEntry(&writer,"sidebearings",QStringList()<<"10"<<"34-35"<<"307-308");
writer.writeStartElement("entry");
writer.writeAttribute("term","subtraction");
WriteEntry(&writer,"of pictures",QStringList()<<"115"<<"34-35"<<"244");
WriteEntry(&writer,"of vectors",QStringList()<<"9");
writer.writeEndElement();
writer.writeEndDocument();
file.close();
return 0;
}
实现
<?xml version="1.0" encoding="UTF-8"?>
<entry term="sidebearings">
<page>10</page>
<page>34-35</page>
<page>307-308</page>
</entry>
<entry term="subtraction">
<entry term="of pictures">
<page>115</page>
<page>34-35</page>
<page>244</page>
</entry>
<entry term="of vectors">
<page>9</page>
</entry>
</entry>
人间有真情,人间有真爱。