22.QT-XML介绍,QXmlStreamReader解析
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>的子元素
在 XML 中,有 5 个预定义的实体引用
比如这样会产生 XML 错误:
- <message>if salary < 1000 then</message>
为了避免这个错误,请用实体引用来代替 “<“ 字符:
- <message>if salary < 1000 then</message>
XML属性
属性必须被引号包围,比如:
- <person sex="female">
- <firstname>Anna</firstname>
- <lastname>Smith</lastname>
- </person>
上面的female便是属性,其中sex便是命名空间
注意:需要避免使用属性,如果信息感觉起来很像数据,那么请使用元素吧。
比如:
- <person>
- <sex>female</sex>
- <firstname>Anna</firstname>
- <lastname>Smith</lastname>
- </person>
XML命名空间
XML 命名空间属性被放置于元素的开始标签之中
它的作用是将多个相同的元素区别开来,比如:
- <entry term="of pictures">
- <page>115</page>
- <page>244</page>
- </entry>
<entry term="of vectors">- <page>9</page>
- </entry>
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();
- }
效果: