4. Lire un document XML avec DOM

Lire un document XML avec DOM est relativement simple. Lire un document XML consiste à lire le document là où il est, à savoir en mémoire ou sur disque dans un fichier, par exemple. Cela consiste ensuite à interpréter son contenu, renvoyer d'éventuelles erreurs s'il y a des erreurs au niveau de la syntaxe XML. Attention, lire un document XML n'a rien à voir avec le fait qu'il soit valide ou non par rapport à une DTD, et n'effectue pas cette vérification. La lecture vérifie juste qu'on a bien du XML et qu'il n'y a pas de fautes d'orthographe dans le XML. Enfin, la lecture du document consiste à allouer un espace mémoire pour y construire un arbre et y mettre les données du document. Peu importe comment la lecture se fait, dans quel ordre, du moment que tout ce qui précède est fait.

4.1. Lire un fichier XML

La lecture d'un document XML contenu dans un fichier s'effectue avec l'instruction xmlParseFile() qui prend en seul et unique argument le nom du fichier. Elle renvoie une variable de type xmlDocPtr. Vous remarquerez tout au long de la lecture que libxml2 n'aime pas les étoiles. Ainsi, on préfère xmlDocPtr à xmlDocPtr* ou même à xmlDoc*. Cela donne:

1 xmlDocPtr xmldoc = NULL;
2 xmldoc = xmlParseFile ("permissions.xml");
3 if (!xmldoc)
4   {
5     fprintf (stderr, "%s:%d: y'aurait pas comme un petit probleme ?\n", 
6 	    __FILE__, __LINE__);
7     exit (EXIT_FAILURE);
8   }

xmldoc contient maintenant une structure prête à être utilisée avec les instructions DOM.

Attention: si votre programme est un programme avec des threads, vous devez initialiser le parseur avec xmlInitParser() (pas d'arguments, ne renvoie rien).

4.2. Lire un document en mémoire

Lire un document en mémoire ne semble pas présenter d'intérêt à première vue. En effet, les documents XML sont principalement des fichiers. Cependant, je connais rien que deux exemples, cas courants, qui peuvent se présenter. Le premier est lorsque vous lisez un document venant du réseau. Vous le lisez entièrement, le placez en mémoire. Ensuite, pas question de le sauvegarder dans un fichier pour le recharger avec ce que nous avons vu précédemment.

Le second concerne les fichiers de configuration. Je reviendrai sur les détails de l'utilisation d'un fichier de configuration avec libxml2 plus loin, mais voici en quoi sa lecture en mémoire peut être intéressante. Tout programme doit disposer d'une configuration par defaut. Il est très désagréable qu'un programme ne se lance pas s'il ne trouve pas le fichier de configuration de l'utilisateur. Certains programmes sont capables de se lancer malgré l'absence d'un fichier de configuration: ils contiennent la configuration par defaut via l'initialisation des variables aux bonnes valeurs. D'autres sont capables de générer un fichier de configuration par défaut avant de l'utiliser. D'autres encore ouvrent une fenêtre où l'utilisateur doit configurer son programme avant de pouvoir l'utiliser.

Lire un document XML en mémoire peut donc être intéressant pour avoir le fichier de configuration dans une variable codé en dur et, en l'absence de configuration sur le disque, le programme lit le fichier de configuration codé en dur.

Pour lire un document XML en mémoire, c'est comme pour un fichier, mais l'instruction est xmlParseDoc() et prend en argument un pointeur vers un xmlChar*. Un xmlChar peut être considéré comme un char habituel. En fait, c'est inexact, car un char est codé sur un octet. Un xmlChar est aussi codé sur un octet, mais est suscpetible de l'être sur plusieurs dans le cas d'un codage des caractères sur plusieurs octets.

Nous avons aussi l'instruction xmlParseMemory() qui fait comme xmlParseDoc(), mais qui prend en premier argument un const char*, c'est-à-dire du vrai char et non plus du xmlChar, et en second argument, la taille du bloc à lire. Cela donne par exemple:

 1 const char doc[] =
 2   "<?xml version='1.0'?><racine><texte>blabla</texte></racine>";
 3 xmlDocPtr xmldoc;
 4 xmldoc = xmlParseMemory (doc, sizeof (doc));
 5 if (!xmldoc)
 6   {
 7     fprintf (stderr, "%s:%d y'a vraiment comme un probleme ici\n", __FILE__,
 8 	     __LINE__);
 9     exit (EXIT_FAILURE);
10   }

4.3. Libérer la mémoire

Pour libérer la mémoire, comme l'on fait avec free() après un malloc(), veuillez utiliser l'instruction xmlFreeDoc(), avec en argument, le xmlDocPtr que vous avez utilisé, xmldoc dans notre cas:

1 xmlFreeDoc (xmldoc);
création est mise à disposition sous un contrat Creative Commons