Construction de documents XML en langage C

De Wicri Manuel

Le type Buffer

La construction de documents demande souvent l'élaboration de chaînes. La gestion des chaînes de longueur variables est relativement difficiles à gérer en langage C.


Un type Buffer a été introduit pour simplifier ce type de tâche.

Une documentation technique est disponible sur Wicri/Outils.

Exemple introductif

En pratique ces objets ne se manipulent que par des pointeurs. Voici un exemple du calcul d'une url utilisant un Buffer.

#include "Buffer.h"

Buffer *bufUrl;
char *myPage;
 ...
bufUrl=NewBuffer();
BufferStrcpy(bufUrl,"http://myWebSite/");
BufferStrcat(bufUrl,myPage);
printf ("<a href=\"%s\">Pour aller sur %s</a>", BufferString(bufUrl), myPage);

Déclaration et création

L'utilisation des Buffers demande l'appel du ficher "Buffer.h".

Ces structures doivent être explicitement crées avec la fonction NewBuffer().

Dans un programme principal
#include "Buffer.h"
 ...
main() {
 ...
Buffer *bufUrl;
 ...
bufUrl=NewBuffer();
 ...
Dans une fonction
#include "Buffer.h"
 ...
 int maFonction ( ... ) {
 static Buffer *monBufferLocal = NULL; /* déclare le Buffer avec un pointeur NULL */

 ...
 if (! monBufferLocal) monBufferLocal = NewBuffer(); /* création au premier appel */

Opérations sur un Buffer

Copie

BufferStrcpy
BufferStrcpy copie une chaîne dans un Buffer.
Synopsis
char *BufferStrcpy(Buffer *b, char *str)
Paramètres
b un Buffer,
str la chaîne à copier.

Concaténation

BufferStrcat
ajoute une chaîne de caractères à la fin du Buffer.
Synopsis
char *BufferStrcat(Buffer *b, char *str)
Paramètres
b un Buffer,
str la chaîne à concaténer.

Gestion de flots de documents

Accès au document courant

Nous avons déjà utilisé la fonction :

SgmlNode *SxmlInputGetDocumentElement();

Cette fonction accède à un document sur le flot d'entrée.

En fait elle appelle une fonction interne (SxmlInputGetRecord). Celle-ci qui une ligne contenant des zones séparées par des tabulations et terminée par un document XML (un SxmlRecord).

Par exemple, l'enregistrement suivant :

000001 ➔ <idx><k>France</k><f>25</f></idx>

Donnera lieu à la structure suivante (les termes précédés de # sont des notations internes, propres à Dilib) :

<#record #type="SXML_NODE_RECORD">
   <#documentFragment #type="SXML_NODE_DOCUMENT_FRAGMENT">
        000001
   </#documentFragment>
   <idx #type="SXML_NODE_DOCUMENT">
         <idx #type="SXML_NODE_ELEMENT">
             <k>France</k>
             <f>25</f>
         </idx>
   </idx>
</#record>


La fonction SxmlInputGetRecord construit donc un arbre XML assez complexe. La fonction SxmlInputGetDocumentElement renvoie simplement un pointeur sur le document attendu (ici sur élément idx ayant comme attribut interne SXML_NODE_DOCUMENT).

Elle renvoie NULL quand il n'y a rien à lire. Ceci permet de réaliser une boucle while.

Exemple, (déjà vu), pour extraire les métadonnées pubmed d'un flot de données ScienceExplor.

#include "SxmlNode.h"
main()
{
  SxmlNode *docu ,*pubmed;
  while(docu=SxmlInputGetDocumentElement())
    {
       if (pubmed=SxmlGetFirstChildByTagName(docu, "pubmed"))
                 {SxmlPrint(pubmed);putchar('\n');
    };
}

Accès à la clé du document courant

De très nombreux flots de données Dilib sont composés d'enregistrements structurés en 2 zones : une clé et un document.

Pour permettre de travailler sur les clés une variable globale nommée

char *SxmlInputRecordKey;

permet d'accéder à la chaîne contenant cette clé.

Exemple, ce programme imprime les clés d'un flots de données qui contiennent la chaîne « (fr) ».


#include "SxmlNode.h"
main()
{
  SxmlNode *docu;
  while(docu=SxmlInputGetDocumentElement())
    {
       if (strstr(SxmlInputRecordKey, "(fr)")) printf ("%s\n", SxmlInputRecordKey);
    };
}

il peut être appliqué à la table des wikis décrite sur Wicri/Base 1.30