Introduction à la programmation en C des arbres Xml
Cette page reprend une section du cours qui était donné pour l'utilisation de la plateforme Dilib.
Sommaire
Arbres XML - notions de base
La bibliothèque Dilib est basée sur le norme Xml avec des adaptations légères pour pouvoir manipuler des grandes quantités de documents Xml.
L'objet de base : SxmlNode
Les arbres Xml sont réalisés à l'aide d'une structure élémentaire unique nommée "SxmlNode"
Type de base : SxmlNode
Nous avons adopté "un style objet" en programmation C. Les arbres Xml (ou les sous-arbres) seront toujours repérés pas des pointeurs sur des SxmlNode
.
Les méthodes élémentaires associées aux SxmlNode
Tout objet de type SgmlNode aura trois méthodes permettant d'accéder au père et aux frères d'un nœud Xml.
- Accès au parent
SxmlNode *SxmlParent (SgmlNode *myNode);
Un nœud Xml n'a, au plus, qu'un seul parent. C'est ainsi que des arbres peuvent être réalisés.
- Accès au suivant
SxmlNode *SxmlNextSibling (SgmlNode *myNode);
- Accès au précédant
SxmlNode *PreviousSibling (SgmlNode *myNode);
Types dérivés
- accès au premier fils
SgmlFirst (SgmlNode *)
accès au dernier fils
SgmlLast(SgmlNode *)
SgmlMark
(correspondant à <a>, <b>,<c>)SgmlData
(correspondant à a1, b1, c1)
<address><a href="#sommaire">-> sommaire</a></address>
<a name=build>
Construction d'arbres SGML
Constructeur de base
Toutes les fonctions de création utilisent un constructeur de base qui n'est pratiquement jamais directement utilisé par l'utilisateur :
SgmlNode *SgmlCreateNode(type); char type;
Constructeurs effectivement utiles :
- Création d'un élément qui n'a pas encore de contenu.
SgmlNode *SgmlCreateMark(tag); char *tag;
- Création d'un élément avec son contenu textuel.
SgmlNode *SgmlCreateLeaf(tag, string); char *tag; char *string;
- Exemples
SgmlCreateMark("a"); /* <a></a> */ SgmlCreateLeaf("a","text"); /* <a>text</a> */
Méthodes de construction de base
- Ajout d'un nouvel élément en tête des fils
SgmlNode *SgmlAddFirst(pere, fils); SgmlNode *pere, *fils;
- Ajout d'un nouvel élément en queue de la liste des fils
SgmlNode *SgmlAddLast(pere,fils); SgmlNode *pere, *fils;
Exemple :
/* création de <a><b>b1</b><c>c1</c></a> */ #include "Sgml.h" main() { SgmlNode *root; root =SgmlCreateMark("a"); SgmlAddLast(root, SgmlCreateLeaf("b","b1")); SgmlAddLast(root, SgmlCreateLeaf("c","c1")); SgmlPrint(root); putchar('\n'); exit(0); } |
Exercices
- Modifier le programme précédent pour qu'il imprime le document SGML donné
en introduction de ce chapitre :
<a>a1<b>b1</b><c>c1</c></a>
- Ecrire un programme qui produise le document suivant:
<doc><tit>Tintin au Congo</tit><kw><e>Tintin</e><e>Milou</e></kw></doc>
<address><a href="#sommaire">-> sommaire</a></address>
<a name=access>
Accès à l'environnement d'un noeud
Les voisins ou parents
Toutes les fonctions retournent un pointeur NULL en cas d'échec.
SgmlNode *SgmlNext(node);
SgmlNode *SgmlPrevious(node);
SgmlNode *SgmlFirst(node);
SgmlNode *SgmlLast(node);
SgmlNode *SgmlFather(node);
Les caractéristiques d'un noeud
pour un noeud de type Mark
char *SgmlTag(node);
pour un noeud de type Data
char *SgmlDataString(noeud);
test de type
int SgmlIsData(node);
int SgmlIsMark(node);
<address><a href=#sommaire>-> sommaire</a></address> <a name=iter>
Itérations sur les composants d'un noeud
<A NAME="pgfId=145835"> </A> Principe
<A NAME="pgfId=145836"> </A> Toutes les fonctions renvoient la valeur NULL en cas d'échec ou d'absence d'un élément.
<A NAME="pgfId=145837"> </A> Squelette d'une itération sur les fils d'un noeud
if ((son = SgmlFirst (node)) { do { <i>traitement sur son</i> } while ((son=SgmlNext(son)); } else { <i>traitement de l'exception </i>} <pre> </td></tr></table></center> <H2 CLASS="Intitulé2"> Exemple</H2> <P CLASS="Courant"> édition de toutes les étiquettes des fils d'un noeud</P> <center><table border=4><tr><td> <pre> editSonTag(node) SgmlNode *node; { SgmlNode *son; if ((son=SgmlFirst(node))) do{ if(SgmlIsMark(son)) printf("%s\n",SgmlTag(son)); } while ((son=SgmlNext(son))); } |
<address><a href=#sommaire>-> sommaire</a></address> <a name=io>
Import Export de structures SGML
<A NAME="pgfId=141012"> </A> Si la chaîne d'entrée est en forme normale, la construction d'un arbre SGML peut se faire sans DTD.
Conversion SGML <-> string
Les fonctions d'entrées sorties utilisent un noyau de 2 procédures de conversion vers les chaine (char *) de C.
- Conversion d'un arbre SGML en String
char *SgmlToString(node); SgmlNode *node; <li>Construction d'un arbre SGML à partir d'une string.
SgmlNode* SgmlFromString(string); char *string;
Entrées-sorties (Dam = Dilib Access Method)
Les fonctions qui réalisent les entrées sorties sont réalisées à partir des fonction précédentes.
- Impression d'un objet SGML sur la sortie standard :
SgmlPrint(node);
- Impression d'un objet SGML dans un fichier :
SgmlFilePrint(file, node); FILE *file;
- lecture du prochain document SGML sur l'entrée standard.
SgmlNode *SgmlInputNextDocument();
Exemple
Impression de tous les premiers fils ayant «a» pour tag.
#include «Sgml.h» main() { SgmlNode *docu ,*son; while(docu=SgmlInputNextDocument()) { if (son=SgmlFirst(docu)) {if (strcmp(SgmlTag(son),"a")==0) {SgmlPrint(son);putchar('\n'); }}}; } |
<address><a href=#sommaire>-> sommaire</a></address>
<a href="http://www.loria.fr/dilib"></a> |
[ <a href="http://www.loria.fr/projets/dilib/doc.html">Cours DILIB</a> ] |