Comment lire un fichier XML avec Qt ?

Introduction

Le format XML est devenu très populaire au fil des années. Cette popularité est principalement dûe à la simplicité de son format, mais aussi et surtout au fait que ce type de fichier peut aussi bien être interprété par des être humain que par des machine. Cette article présente un exemple de lecture de fichier avec Qt.

Configuration de Qt

Avant de pouvoir traiter des fichiers XML, le projet Qt doit être configuré. Dans le fichier projet (.pro), ajouter la ligne suivante afin de spécifier au compilateur qu’il va devoir utiliser la bibliothèque Qt/XML au moment de la compilation :

QT += xml

Ajouter les inclusions nécessaires à l’utilisation des fonctions XML :

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

Fichier XML d’exemple

Voici un fichier XML d’exemple nommé 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>

Chargement du fichier XML

Afin de lire le fichier XML il faut, en premier lieu, charger les données dans un objet de type QFile. Ensuite, le contenu est parsé avec la fonction 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();

Lecture du noeud principal

Lorsque le fichier est chargé, le premier noeud (appelé root) peut être lu de la façon suivante :

// 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;

Accès aux données

Enfin, l'ensemble des données peut être lu selon l'illustration suivante :

// 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();
}

Téléchargement

L'exemple détaillé sur cette page avec le fichier XML et les fichiers de configuration peuvent être téléchargés ci-dessous :


Dernière mise à jour : 26/10/2019