firemail
标题: Qt XML读写操作 [打印本页]
作者: hechengjin 时间: 2016-7-4 16:28
标题: Qt XML读写操作
我们知道对XML的操作有两种方法,即DOM方式和SAX方式。二者主要区别是:DOM实现方式操作非常简单,但不适合处理过大文件;而SAX实现方式是能处理很大的XML文件,但是需要开发者写一些复杂的代码。Qt提供了对应于这两种用于读取、操作和编写XML的实现类,分别是QDomDocument类和QXmlStreamReader类。
作者: hechengjin 时间: 2016-7-4 18:14
本帖最后由 hechengjin 于 2016-7-4 18:15 编辑
http://blog.sina.com.cn/s/blog_a6fb6cc90101eupl.html
如何使用QXmlStreamReader来解析格式良好的XML,Qt的文档中指出,它是一种更快、更方便的Qt自己的SAX解析器(QXmlSimpleReader)的替代,它也较快,在某种情况下,比DOM(QDomDocument)更方便。
XML文件:
解析方法:
- void ParseXML::parseXML(QString file_name)
- {
- if(file_name.isEmpty())
- return;
-
- QFile *file = new QFile(file_name);
- if(!file->open(QFile::ReadOnly | QFile::Text))
- {
- QMessageBox::information(NULL, QString("title"), QString("open error!"));
- return;
- }
- //QXmlStreamReader操作任何QIODevice.
- QXmlStreamReader xml(file);
- QList> persons;
- //解析XML,直到结束
- while(!xml.atEnd() && !xml.hasError())
- {
- //读取下一个element.
- QXmlStreamReader::TokenType token = xml.readNext();
- //如果获取的仅为StartDocument,则进行下一个
- if(token == QXmlStreamReader::StartDocument)
- {
- continue;
- }
- //如果获取了StartElement,则尝试读取
- if(token == QXmlStreamReader::StartElement)
- {
- //如果为persons,直接进入下一个
- if(xml.name() == "persons")
- {
- continue;
- }
-
- //如果为person,则对其进行解析
- if(xml.name() == "person")
- {
- persons.append(this->parsePerson(xml));
- }
- }
- }
-
- if(xml.hasError())
- {
- QMessageBox::information(NULL, QString("parseXML"), xml.errorString());
- }
-
- //从reader中删除所有设备、数据,并将其重置为初始状态
- xml.clear();
- }
-
- QMap ParseXML::parsePerson(QXmlStreamReader& xml)
- {
- QMap person;
- //检查是否获取person
- if(xml.tokenType() != QXmlStreamReader::StartElement &&
- xml.name() == "person")
- {
- return person;
- }
- //获取person属性
- QXmlStreamAttributes attributes = xml.attributes();
- if(attributes.hasAttribute("id"))
- {
- person["id"] = attributes.value("id").toString();
- }
-
- //操作下一个
- xml.readNext();
- while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
- xml.name() == "person"))
- {
- if(xml.tokenType() == QXmlStreamReader::StartElement)
- {
- if(xml.name() == "name")
- {
- this->addElementDataToMap(xml, person);
- }
-
- if(xml.name() == "age")
- {
- this->addElementDataToMap(xml, person);
- }
-
- if(xml.name() == "email")
- {
- this->addElementDataToMap(xml, person);
- }
-
- if(xml.name() == "website")
- {
- this->addElementDataToMap(xml, person);
- }
- }
-
- xml.readNext();
- }
- QString id = person["id"];
- QString name = person["name"];
- QString age = person["age"];
- QString email = person["email"];
- QString website = person["website"];
- return person;
- }
-
- void ParseXML::addElementDataToMap(QXmlStreamReader& xml,
- QMap& map) const
- {
- if(xml.tokenType() != QXmlStreamReader::StartElement)
- {
- return;
- }
- QString elementName = xml.name().toString();
- xml.readNext();
-
- if(xml.tokenType() != QXmlStreamReader::Characters)
- {
- return;
- }
-
- map.insert(elementName, xml.text().toString());
- }
复制代码
作者: hechengjin 时间: 2016-7-4 18:16
http://www.devbean.net/2013/08/qt-study-road-2-read-xml-with-sax/
作者: hechengjin 时间: 2016-7-5 14:41
一 API介绍
readNext():从xml输入流中读取下一个记号
name():记号的名称,即<名称></名称>
isStartElement():判断当前已读取的记号是否为开始元素,开始元素即<>
isEndElement():判断当前已读取的记号是否为结束元素,结束元素即</>
readElementText():读取当前记号对应的文本值,<>文本值</>
atEnd():判断是否为文件结尾
二 应用实例
对短信message.xml进行读取,xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<DATA>
<Sms>
<Name>wlc</Name>
<Number>18725658147</Number>
<Content>短信测试1</Content>
<Time>2012-07-25 23:54:10</Time>
</Sms>
<Sms>
<Name>rt</Name>
<Number>13555555555</Number>
<Content>短信测试2</Content>
<Time>2012-07-26 00:21:24</Time>
</Sms>
<Sms>
<Name>wzg</Name>
<Number>18656765434</Number>
<Content>短息测试3</Content>
<Time>2012-07-26 00:22:03</Time>
</Sms>
</DATA>
读取代码如下:
- void read_message()
- {
- QFile file(fi"message.xml");
- if(file.open(QIODevice::ReadOnly | QIODevice::Text))
- {
- Message *message;
- QXmlStreamReader reader(&file);
- reader.readNext();
- while (!reader.atEnd())
- {
- if(reader.isStartElement())
- {
- if(reader.name() == "Sms")
- {
- message = new Message();
- }
- else if(reader.name() == "Name")
- {
- message->SetMsgName(reader.readElementText());
- }
- else if(reader.name() == "Number")
- {
- message->SetMsgPhone(reader.readElementText());
- }
- else if(reader.name() == "Content")
- {
- message->SetMsgContent(reader.readElementText());
- }
- else if(reader.name() == "Time")
- {
- message->SetMsgTime(reader.readElementText());
- }
- }
- else if(reader.isEndElement())
- {
- if(reader.name() == "Sms")
- {
- message_map->insert(std::make_pair(message->GetMsgPhone(), message));
- }
- }
- reader.readNext();
- }
- }
- else
- {
- //qDebug()<<"read inbox file error...";
- }
- file.close();
- }
复制代码
作者: hechengjin 时间: 2016-7-6 14:26
http://mobile.51cto.com/symbian-268953.htm
本文介绍的是在Qt使用QDomDocument类实现XML文件的操作,QDomNode类是一个父类,QDomDocument是QDomNode的一个子类,鉴于大部分QDomNode的类型都是QDomDocument。
XML,全称为扩展标记语言(extensible markup language).是一种非常方便的数据交换工具。现在Blog的订阅系统输出格式就是满足XML规范的RSS格式,还有SVG矢量图形也使用了XML格式。
我们在取得一个XML格式的文件后,需要作句法分析去提取发布方提供的信息。而Qt为XML提供了很好的支持,包括DOM的实现和SAX的实现。
DOM是Document Object Model的简称,其实现方式是将整个文档当作一个对象来装入内存进行处理,然后开发者可以访问这个对象中的每一个节点,每一个节点对应XML文件里的一个标记。这种方式的优点是操作非常简单,缺点是需要将整个文件放入内存,不适合处理过大文件。这种方式在Qt中的实现类是QDomDocument,也是本文将要讲解的。以Blog为代表的RSS文件都不会很大,适合用这种方式来处理。
SAX是Simple API for XML的简称,其实现方式是按阶段将文档读取到内存中,在碰到标签或者其它阶段的时候,调用开发者预先设计好的回调函数去处理。这种方式的缺点是需要开发者写回调函数去处理不同标签,代码复杂一些,优点是能处理很大的XML文件。这种方式在Qt中的实现类叫QXmlStreamReader。
下面部分是代码讲解
(1)如果需要使用QDomDocument,那么请在你的项目.pro文件里加上一句”QT += xml”,不然无法编译通过。
(2)
- QDomDocument doc;
- QFile file(”rss.xml”);
- QString errorStr;
- int errorLine;
- int errorCol;
- //setContent是将指定的内容指定给QDomDocument解析,第一参数可以是QByteArray或者是文件名等
- if(!doc.setContent(&file,true,&errorStr,&errorLine,&errorCol))
- {
- //如果出错,则会进入这里。errorStr得到的是出错说明
- //errorLine和errorCol则是出错的行和列
- }
如果上面的步骤没出错,那么恭喜你,你已经得到了一个完整的QDomDocument对象doc,你只要访问doc的子节点或子子节点就可以取得XML中所有标记上的内容了。
(3)
可以通过doc.childNodes()获得doc的所有的子节点列表QDomNodeList。比如
- QDomNodeList list=doc.childNodes();
- for(int i=0;i<list.count();i++){
- QDomNode node=list.at(i);//好的风格当然是把定义写在外面
- //qDebug()<<”node name is “<<node.nodeName();
- //qDebug()<<”node type is “<<.nodeType();
- }
通过上面的方法你就能知道每个节点的名字和类型了,节点名字就是标记的名字。打印出来对照着xml文件看就很容易明白了。QDomNode类是一个父类,QDomDocument是QDomNode的一个子类,鉴于大部分QDomNode的类型都是QDomDocument.那么你可以使用toDocument()函数将QDomNode类型转换成QDomDocument.
- QString text=node.toElement().text();
上面的语句可以将一个节点里的文本取出,也就是标记内的文本部分。使用该函数获得的编码就已经是unicode格式了,不需要再做转换。
小结:对于Qt使用QDomDocument操作XML文件的内容讲解完了,希望本篇文章对你有所帮助吧。
欢迎光临 firemail (http://firemail.wang:8088/) |
Powered by Discuz! X3 |