I. L'objet DOM▲
QtXml est un module qui permet d'utiliser des données XML dans un programme Qt. Pour que le compilateur sache que l'on veut utiliser QtXml, il faut ajouter dans le fichier .pro :
QT += xmlPuis, il ne reste plus qu'à préciser au compilateur que l'on veut utiliser le module en ajoutant un include, celui qui suit :
#include <QtXml>Cet include, comme vous avez dû le remarquer, permet d'utiliser le module dans son code. Maintenant, le code requis pour chaque fichier.
I-A. Le code▲
#include <QApplication>
#include <QtGui>
#include <QtXml>
#include "Xml_Dom.h"
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
Xml_Dom *Dom = new Xml_Dom();
Dom->show();
return app.exec();
}#ifndef XML_DOM
#define XML_DOM
#include <QtGui>
#include <QtXml>
#include <QWidget>
class Xml_Dom : public QWidget
{
public:
Xml_Dom();
~Xml_Dom();
// On ajoutera des variables et des méthodes après.
};
#endif#include "Xml_Dom.h"
#include <iostream>
using namespace std;
Xml_Dom::Xml_Dom() : QWidget()
{
/*//////////////////////////////////////////////////////////////////////*/
/* On définira ici le document XML et les actions que l'on va effectuer */
/*//////////////////////////en premier lieu/////////////////////////////*/
/*//////////////////////////////////////////////////////////////////////*/
}
Xml_Dom::~Xml_Dom()
{
}I-B. Les explications▲
Afin d'utiliser du XML, on va utiliser un objet DOM (Document Objet Model). Il faut donc définir un objet de ce type qui nous permettra d'agir sur le document XML. Afin de créer cet objet, il suffit d'utiliser la classe QDomDocument. Il faut l'instancier comme ceci :
QDomDocument *dom = new QDomDocument("Nom de votre document QDomDocument");]></code>
<paragraph>
Cette façon est la plus simple d'instancier un objet QDomDocument. Il en existe d'autres, qui ne seront d'aucune utilité pour le moment.
Il faut maintenant ouvrir le document XML ; pour cela, on utilise le code suivant :
</paragraph>
<code langage="qt" ><
Maintenant, on va établir les connexions. Toujours dans le constructeur :
connect(id_demand, SIGNAL(valueChanged(int)), this, SLOT(change(int)));
connect(open, SIGNAL(clicked()), this, SLOT(openDom()));Comme on peut le voir, on va utiliser des slots personnalisés : l'un servira à changer la valeur d'une variable qui sera l'identifiant demandé, l'autre ouvrira le document DOM et agira dessus.
Avant de commencer à vraiment coder, petite précision : ce petit programme sert à afficher une news en fonction de l'identifiant précisé dans le QSpinBox (la variable id_demand).
On s'occupe, dans un premier temps, de l'actualisation de la variable qui variera. En un premier lieu, on va remplacer le fichier Xml_Dom.h par :
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui>
#include <QWidget>
#include <QtXml>
class Xml_Dom : public QWidget
{
Q_OBJECT
public:
Xml_Dom(QWidget *parent = 0);
~Xml_Dom();
private:
QFile xml_doc;
QDomElement dom;
QDomNode noeud;
QDomElement element
QSpinBox *id_demand;
QPushButton *open;
int ids;
private slots:
void openDom();
void change(int change);
};
#endif // WIDGET_HCe code donne les variables nécessaires ainsi que le constructeur, le destructeur et les slots.
On peut voir que la variable qui va donner l'identifiant s'appelle ids. Maintenant, dans votre constructeur, on ajoute :
ids = 0; // On initialise ids à 0.On va maintenant voir le slot change(). Il est appelé quand le texte de id_demand est modifié. On va donc mettre ce texte dans une nouvelle variable. Voici le code de la fonction :
void Xml_Dom::change(int change)
{
ids = change;
}Ce code attribue la valeur change à ids. Maintenant que l'on a défini ids, on va pouvoir exécuter des opérations sur le document DOM. Créez la fonction Xml_Dom::openDom() comme ceci :
void Xml_Dom::openDom()
{
QDomDocument dom("mon_xml");
QFile file("xml_doc.xml");
if (!file.open(QIODevice::ReadOnly))
return;
if (!dom.setContent(&file))
{
file.close();
return;
}
file.close();
QDomElement docElem = dom.documentElement();
QDomNode n = docElem.firstChild();
while(!n.isNull())
{
QDomElement e = n.toElement();
// C'est ici que l'on va marquer le code
n = n.nextSibling();
}
}On va maintenant ajouter ce qui va permettre de vérifier si l'identifiant demandé est égal à ids. Pour cela, on va chercher l'attribut id. Comme ids est un int, on va aussi utiliser la fonction toInt(). Le code de test sera donc :
if(element.attribute("id").toInt() == ids)
QMessageBox::information(NULL, "Information", "La nouvelle news est :<br />" + e.attribute("value"));Il suffit d'intégrer ce code entre la déclaration de element et l'autre partie du code pour le compléter.
IV. Écrire dans le document XML ▲
Pour écrire dans un document XML, il faut d'abord passer par le document DOM afin de récupérer le fichier déjà pris. On crée un nouveau bouton et on l'appelle write_button, on utilise la méthode connect() comme ceci :
connect(write_button,SIGNAL(clicked()),this,SLOT(writeDom()));write_button va servir à lancer la fonction writeDom(), qui va écrire dans le document XML. On crée la fonction writeDom() et on ajoute sous private slots son prototype. On va y ajouter le code qui va lire le document XML :
QDomDocument dom("mon_xml");
QFile doc_xml("xml_doc.xml");
if(!doc_xml.open(QIODevice::ReadOnly))
{
QMessageBox::critical(this,"Erreur","Impossible d'ouvrir le ficher XML");
doc_xml.close();
return;
}
if(!dom.setContent(&doc_xml))
{
QMessageBox::critical(this,"Erreur","Impossible d'ouvrir le ficher XML");
doc_xml.close();
return;
}
doc_xml.close();On ajoute ensuite le code qui va explorer le nouveau document DOM :
QDomElement docElem = dom.documentElement();On peut maintenant écrire dans le document XML. Pour cela, on va d'abord passer par le document DOM. On crée un nouveau QDomElement et on l'appelle write_elem. On va en même temps préciser comment s'appelle la balise.
QDomElement write_elem = dom.createElement("information"); // On crée un QDomElement qui a comme nom "information".Le code ci-dessus va « préparer » une balise XML en la créant et en lui donnant déjà un nom (ici, information). On va ensuite lui donner des attributs avec setAttribute() :
write_elem.setAttribute("id", 2); // L'attribut id vaudra 2.
write_elem.setAttribute("value", "L'inflation arrive en France"); // L'attribut value vaudra "L'inflation arrive en France".Le code ci-dessus ajoute à l'élément write_elem deux attributs : id et value. On leur donne une valeur prédéfinie, mais ce n'est pas obligatoire. Enfin, on met tout dans le document DOM en passant par un QDomElement. On passera donc par docElem :
docElem.appendChild(write_elem);// On associe write_elem à domElem.appendChild() est une fonction qui permet d'ajouter au document DOM un nœud ou un élément. Son prototype est :
QDomNode QDomNode::appendChild (const QDomNode & newChild)Le code ci-dessus ajoute l'élément write_elem au nœud docElem. Maintenant que la balise XML est créée et intégrée au document DOM, on peut actualiser le document XML. Pour ce faire, on va devoir écrire directement dans le fichier XML.
Pour écrire dans le fichier XML, il faut donner une chaîne de caractères de type QString. On va donc devoir transformer un objet QDomDocument en QString. Voici le code pour créer un objet QString, write_elem, qui reçoit un objet de type QDomDocument :
QString write_doc = doc.toString();On utilise la méthode toString() pour transformer l'objet QDomDocument en QString. Cela donnera peut-être la même chose qu'un cast. Cette méthode n'est pas disponible partout !
On crée un objet de type QFile qui contiendra le fichier dans lequel écrire et on le teste aussi :
QFile fichier("xml_doc.xml");
if(!fichier.open(QIODevice::WriteOnly))
{
fichier.close();
QMessageBox::critical(this,"Erreur","Impossible d'écrire dans le document XML");
return;
}Ensuite, on crée un objet de type QTextStream :
QTextStream stream(&fichier);Puis on va enfin écrire dans ce fichier :
stream << write_doc; // On utilise l'opérateur << pour écrire write_doc dans le document XML.À la fin de l'opération, on peut fermer le fichier :
fichier.close();Avant le passage du programme :

Le programme :

Après le passage du programme :

V. Remerciements▲
Merci à Thibaut Cuvelier et à Claude Leloup pour leur relecture !



