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 la norme XML avec des adaptations légères (Stream XML ou Sxml) pour pouvoir manipuler des grandes quantités de documents XML.
L'objet de base : SxmlNode
Les arbres Sxml 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 objets SxmlNode
Tout objet de type SxmlNode 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 (SxmlNode *myNode);
Un nœud XML n'a, au plus, qu'un seul parent. C'est ainsi que des arbres peuvent être réalisés. Dans la figure précédente le noeud <b> est le parent de b1
.
- Accès au suivant
SxmlNode *SxmlNextSibling (SxmlNode *myNode);
- Accès au précédant
SxmlNode *PreviousSibling (SxmlNode *myNode);
Types dérivés
SxmlElement
(correspondant à <a>, <b>,<c>)
- accès au premier fils
SxmlFirstChild (SgmlNode *)
accès au dernier fils
SxmlLastChild(SgmlNode *)
SxmlText
(correspondant à a1, b1, c1)
<address><a href="#sommaire">-> sommaire</a></address>
<a name=build>
Construction d'arbres Sxml
Constructeur de base
Toutes les fonctions de création utilisent un constructeur de base qui n'est pratiquement jamais directement utilisé par l'utilisateur :
SxmlNode *SxmlNodeCreate(type);
char type;
Constructeurs effectivement utiles
- Création d'un élément qui n'a pas encore de contenu.
SgmlNode *SxmlElementCreate(tag); char *tag;
- Création d'un élément avec son contenu textuel.
SgmlNode *SxmlLeafCreate(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 *SxmlAddFirstChild(pere, fils); SgmlNode *pere, *fils;
- Ajout d'un nouvel élément en queue de la liste des fils
SgmlNode *SgmlAppendChild(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 *SxmlNodeName(node);
pour un noeud de type Data
char *SxmlText(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* SxmlFromString(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 :
SxmlFilePrint(file, node); FILE *file;
- lecture du prochain document SGML sur l'entrée standard.
SgmlNode *SxmlInputNextDocumentElement();
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> ] |