How to read XML files with Qt ?

Introduction

XML files has became a very popular file format. This is mainly due to its simplicity and mostly beacuse these files are human and machine readable. This article shows an example of XML file reading with Qt.

Qt configuration

Before processing any XML file, Qt must be configured. In the project file (.pro), add the following line to set compiler to use the XML library:

QT += xml

Now add, the required libraries in your source code:

// Library needed for processing XML documents
#include <QtXml>
// Library needed for processing files
#include <QFile>

XML example file

Let’s consider the following XML file named billofmaterial.xml:

<!-- File billofmaterial.xml-->
<BOM BOARD="Motor controller" YEAR="2014">

   <COMPONENT ID="R1">
      <NAME>Resistor</NAME>
      <VALUE>47000</VALUE>
   </COMPONENT>

   <COMPONENT ID="C1">      
      <NAME>Capacitor</NAME>
      <VALUE>100e-6</VALUE>
   </COMPONENT>

   <COMPONENT ID="U1">
      <VALUE>0</VALUE>
      <NAME>Driver</NAME>
   </COMPONENT>

</BOM>

Loading XML file

To read an XML file, data must first be loaded in a QFile. Secondly, content must be parsed with setContent:

//The QDomDocument class represents an XML document.
QDomDocument xmlBOM;
// Load xml file as raw data
QFile f("billofmaterial.xml");
if (!f.open(QIODevice::ReadOnly ))
{
    // Error while loading file
    std::cerr << "Error while loading file" << std::endl;
    return 1;
}
// Set data into the QDomDocument before processing
xmlBOM.setContent(&f);
f.close();

Reading first node

Once the file is loaded, the first node (called root) can be read according to the following example:

// Extract the root markup
QDomElement root=xmlBOM.documentElement();

// Get root names and attributes
QString Type=root.tagName();
QString Board=root.attribute("BOARD","No name");
int Year=root.attribute("YEAR","1900").toInt();

// Display root data
std::cout << "Type  = " << Type.toStdString().c_str() << std::endl;
std::cout << "Board = " << Board.toStdString().c_str() << std::endl;
std::cout << "Year  = " << Year << std::endl;
std::cout << std::endl;

Data access

Finally, whole data can be read according to the following example:

// Get the first child of the root (Markup COMPONENT is expected)
QDomElement Component=root.firstChild().toElement();

// Loop while there is a child
while(!Component.isNull())
{    
    // Check if the child tag name is COMPONENT
    if (Component.tagName()=="COMPONENT")
    {

        // Read and display the component ID
        QString ID=Component.attribute("ID","No ID");

        // Get the first child of the component
        QDomElement Child=Component.firstChild().toElement();

        QString Name;
        double Value;

        // Read each child of the component node
        while (!Child.isNull())
        {
            // Read Name and value
            if (Child.tagName()=="NAME") Name=Child.firstChild().toText().data();
            if (Child.tagName()=="VALUE") Value=Child.firstChild().toText().data().toDouble();

            // Next child
            Child = Child.nextSibling().toElement();
        }

        // Display component data
        std::cout << "Component " << ID.toStdString().c_str() << std::endl;
        std::cout << "   Name  = " << Name.toStdString().c_str() << std::endl;
        std::cout << "   Value = " << Value << std::endl;
        std::cout << std::endl;        
    }

    // Next component
    Component = Component.nextSibling().toElement();
}

Download

Examples and source code can be downloaded below:


Last update : 12/09/2018