You Are Here:

Community: Wiki

This page was last modified on 6 November 2009, at 08:44.

Using QXmlStreamReader to parse XML

From Forum Nokia Wiki


ID Creation date June 8, 2009
Platform Qt Tested on devices 5800 XpressMusic
Category Qt for Symbian Subcategory


Keywords (APIs, classes, methods, functions): Qt, XML, SAX, QXmlStreamReader

Overview

This example shows you how you parse XML with QXmlStreamReader. The QXmlStreamReader class provides a fast parser for reading well-formed XML via a simple streaming API.

This snippet can be self-signed. As it does not use any API which require developer/certified signing.

Preconditions

QXmlStreamReader Example

XML file

<?xml version="1.0" encoding="UTF-8" ?>
<persons>
<person>
<firstname>John</firstname>
<surname>Doe</surname>
<email>john.doe@example.com</email>
<website>http://en.wikipedia.org/wiki/John_Doe</website>
</person>
<person>
<firstname>Jane</firstname>
<surname>Doe</surname>
<email>jane.doe@example.com</email>
<website>http://en.wikipedia.org/wiki/John_Doe</website>
</person>
<person>
<firstname>Matti</firstname>
<surname>Meikäläinen</surname>
<email>matti.meikalainen@example.com</email>
<website>http://fi.wikipedia.org/wiki/Matti_Meikäläinen</website>
</person>
</persons>

Header file

#include <QtXml/QXmlStreamReader>
 
class QXSRExample : public QMainWindow {
Q_OBJECT
 
public:
QXSRExample(QWidget *parent = 0);
~QXSRExample();
 
private slots:
void parseXML();
 
private:
QPointer<QVBoxLayout> _layout;
 
void setupUI();
 
QMap<QString, QString> parsePerson(QXmlStreamReader& xml);
void addElementDataToMap(QXmlStreamReader& xml,
QMap<QString, QString>& map) const;
 
void addPersonsToUI(QList< QMap<QString,QString> >& persons);
};

Source file

void QXSRExample::parseXML() {
/* We'll parse the example.xml */
QFile* file = new QFile(":/example.xml");
/* If we can't open it, let's show an error message. */
if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::critical(this,
"QXSRExample::parseXML",
"Couldn't open example.xml",
QMessageBox::Ok);
return;
}
/* QXmlStreamReader takes any QIODevice. */
QXmlStreamReader xml(file);
QList< QMap<QString,QString> > persons;
/* We'll parse the XML until we reach end of it.*/
while(!xml.atEnd() &&
!xml.hasError()) {
/* Read next element.*/
QXmlStreamReader::TokenType token = xml.readNext();
/* If token is just StartDocument, we'll go to next.*/
if(token == QXmlStreamReader::StartDocument) {
continue;
}
/* If token is StartElement, we'll see if we can read it.*/
if(token == QXmlStreamReader::StartElement) {
/* If it's named persons, we'll go to the next.*/
if(xml.name() == "persons") {
continue;
}
/* If it's named person, we'll dig the information from there.*/
if(xml.name() == "person") {
persons.append(this->parsePerson(xml));
}
}
}
/* Error handling. */
if(xml.hasError()) {
QMessageBox::critical(this,
"QXSRExample::parseXML",
xml.errorString(),
QMessageBox::Ok);
}
xml.clear();
this->addPersonsToUI(persons);
}
 
QMap<QString, QString> QXSRExample::parsePerson(QXmlStreamReader& xml) {
QMap<QString, QString> person;
/* Let's check that we're really getting a person. */
if(xml.tokenType() != QXmlStreamReader::StartElement &&
xml.name() == "person") {
return person;
}
/* Next element... */
xml.readNext();
/*
* We're going to loop over the things because the order might change.
* We'll continue the loop until we hit an EndElement named person.
*/

while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
xml.name() == "person")) {
if(xml.tokenType() == QXmlStreamReader::StartElement) {
/* We've found first name. */
if(xml.name() == "firstname") {
this->addElementDataToMap(xml, person);
}
/* We've found surname. */
if(xml.name() == "surname") {
this->addElementDataToMap(xml, person);
}
/* We've found email. */
if(xml.name() == "email") {
this->addElementDataToMap(xml, person);
}
/* We've found website. */
if(xml.name() == "website") {
this->addElementDataToMap(xml, person);
}
}
/* ...and next... */
xml.readNext();
}
return person;
}
 
void QXSRExample::addElementDataToMap(QXmlStreamReader& xml,
QMap<QString, QString>& map) const {
/* We need a start element, like <foo> */
if(xml.tokenType() != QXmlStreamReader::StartElement) {
return;
}
/* Let's read the name... */
QString elementName = xml.name().toString();
/* ...go to the next. */
xml.readNext();
/*
* This elements needs to contain Characters so we know it's
* actually data, if it's not we'll leave.
*/

if(xml.tokenType() != QXmlStreamReader::Characters) {
return;
}
/* Now we can add it to the map.*/
map.insert(elementName, xml.text().toString());
}
 
void QXSRExample::addPersonsToUI(QList< QMap<QString,QString> >& persons) {
while(!persons.isEmpty()) {
QGroupBox* personGB = new QGroupBox("Person");
QFormLayout* layout = new QFormLayout;
QMap<QString,QString> person = persons.takeFirst();
layout->addRow("First name", new QLineEdit(person["firstname"]));
layout->addRow("Surname", new QLineEdit(person["surname"]));
layout->addRow("E-mail", new QLineEdit(person["email"]));
layout->addRow("Website", new QLineEdit(person["website"]));
personGB->setLayout(layout);
this->_layout->addWidget(personGB);
}
}

Postconditions

You've been able to parse the XML and display it in the UI.

Supplementary material

  • You can test the QXSRExample with a test application. The application is available for download at Media:QXSRExample.zip.


Parsing XML with attributes

Lets take example of parsing following XML file

<?xml version="1.0" encoding="UTF-8" ?>
<persons>
<person firstname="abc" surname="def" number="1234" />
<person firstname="ghi" surname="jkl" number="51234" />
<person firstname="mno" surname="pqr" number="61234" />
<person firstname="stv" surname="wxy" number="81234" />
<person firstname="zab" surname="cde" number="61234" />
</persons>

Header file

#include <QtXml/QXmlStreamReader>
 
class ContactDatabse
{
public:
ContactDatabse(QString firstName, QString surName, QString phoneNumber);
~ContactDatabse();
QString getFirstName();
QString getSurName();
QString getPhoneNumber();
private:
QString firstName;
QString surName;
QString phoneNumber;
};
 
class QXSRExample : public QMainWindow {
Q_OBJECT
 
public:
QXSRExample(QWidget *parent = 0);
~QXSRExample();
 
private slots:
void parseXML();
 
private:
QPointer<QVBoxLayout> _layout;
 
void setupUI();
void addPersonsToUI();
void parsePerson(QXmlStreamReader& reader);
QList<ContactDatabse> database;
};

Source file

/* The implementaion of parseXML() is same as explained in above example, so ommitted from here */
 
void QXSRExample::parsePerson(QXmlStreamReader& xml)
{
/* parse each tag and add data to list
*We'll continue the loop until we hit an EndElement named persons
*/

while (!xml.atEnd())
{
/* check whether it is starting of tag <person> , if yes then parse it
*/

if (xml.isStartElement() && xml.name() == "person")
{
/* get all attributes and its value of a tag in attrs variable.
*/

QXmlStreamAttributes attrs = xml.attributes();
/*get value of each attribute from QXmlStreamAttributes */
QStringRef fName = attrs.value("firstname");
QStringRef sName = attrs.value("surname");
QStringRef pNumber = attrs.value("number");
 
if (fName.isEmpty())
{
xml.readNext();
continue;
}
/*create database of one person*/
ContactDatabse data(fName.toString(),sName.toString(),pNumber.toString());
/*add database to list*/
database.append(data);
}
else if(xml.isEndElement() && xml.name() == "persons")
{
/*if EndElement is persons then stop the loop and create UI */
addPersonsToUI();
return;
}
xml.readNext();
}
}
 
void QXSRExample::addPersonsToUI()
{
/* add all contact data to UI */
while(!database.isEmpty())
{
QGroupBox* personGB = new QGroupBox("Person");
QFormLayout* layout = new QFormLayout;
ContactDatabse person = database.takeFirst();
layout->addRow("First name", new QLineEdit(person.getFirstName()));
layout->addRow("Surname", new QLineEdit(person.getSurName()));
layout->addRow("Phone Number", new QLineEdit(person.getPhoneNumber()));
 
personGB->setLayout(layout);
this->_layout->addWidget(personGB);
}
}

Postconditions

You've been able to parse the XML and display it in the UI.

Image:XmlReader.JPG

Example Code


See also

Related Wiki Articles

No related wiki articles found

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia 
RDF Facets: qdcZidentifierQSxhttpE3aE2fE2fwikiE2eforumE2enokiaE2ecomE2findeE78E2ephpE2fCS001424E5fE2dE5fUsingE5ftheE5fE44E45PE4cOYME45NTE5fkeywordE5finE5faE5fE51tE5fpackageE5ffileX qdcZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qdcZtypeQUqfntypeZCommunityContentQ qdcZtypeQUqfntypeZE52esourceQ qdcZtypeQUqfntypeZWebpageQ qdcZtypeQUqfntypeZWikiContentQ qdcZtypeQUqmarsZManagedE52esourceQ qdcZtypeQUqwebZInformationE52esourceQ qdcZtypeQUqwebZPageQ qdcZtypeQUqwebZE52esourceQ qdcZtypeQUqrdfsZE52esourceQ qfnZtopicQUqfnTopicZE71tQ qfnZtypeQUqfntypeZCommunityContentQ qfnZtypeQUqfntypeZE52esourceQ qfnZtypeQUqfntypeZWebpageQ qfnZtypeQUqfntypeZWikiContentQ qfnZuserE5ftagQSxE71tX qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX qrdfZtypeQUqfnZE45E78cludedFromGeneralE4cistingsQ qrdfZtypeQUqfntypeZCommunityContentQ qrdfZtypeQUqfntypeZE52esourceQ qrdfZtypeQUqfntypeZWebpageQ qrdfZtypeQUqfntypeZWikiContentQ qrdfZtypeQUqmarsZManagedE52esourceQ qrdfZtypeQUqwebZInformationE52esourceQ qrdfZtypeQUqwebZPageQ qrdfZtypeQUqwebZE52esourceQ qrdfZtypeQUqrdfsZE52esourceQ