Exploration d'un document XML en langage C : Différence entre versions

De Wicri Manuel
imported>Jacques Ducloy
(Page créée avec « {{Exploration corpus, header |module=Introduction aux serveurs d'exploration sous Unix |précédent=Introduction à la programmation en C des arbres Xml |suivant= }} »)
 
imported>Jacques Ducloy
 
(17 révisions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
 
{{Exploration corpus, header
 
{{Exploration corpus, header
  |module=Introduction aux serveurs d'exploration sous Unix  
+
  |module=Exploration d'un document XML en langage C
  |précédent=Introduction à la programmation en C des arbres Xml
+
|précédent=Introduction aux serveurs d'exploration sous Unix
|suivant=
+
  |suivant=Exploration d'un document de métadonnées en langage C
 
}}
 
}}
 +
[[File:Dilib XmlProg C06-1.gif|400px|right|thumb|un arbre XML contenant 6 nœuds]]
 +
==Création d'un arbre à partir d'une chaîne==
 +
En langage C les chaînes de caractères sont de type <code>char *</code>.
 +
 +
Dans la bibliothèque Dilib, il est très facile de construire un arbre XML à partir de la fonction <code>SxmlFromString</code>.
 +
<source lang="c">
 +
  SxmlNode *SxmlFromgString(char *string);
 +
</source>
 +
 +
Exemple, pour créer l'arbre de la figure ci-dessus :
 +
<source lang="c">
 +
 +
#include "SxmlNode.h"
 +
#include <stdio.h>
 +
main()
 +
{
 +
  SxmlNode *myNodeTest; 
 +
    ...
 +
  myNodeTest=SxmlFromString("<a>a1<b>b1</b><c>c1</c></a>");
 +
    ...
 +
}
 +
</source>
 +
 +
==Accès à l'environnement d'un nœud==
 +
 +
===Les voisins ou parents===
 +
 +
Toutes les fonctions retournent un pointeur NULL en cas d'échec.
 +
 +
Les 2 fonctions suivantes permettent d'accéder au premier et au dernier fils d'un noeud.
 +
 +
<source lang="c">
 +
SxmlNode *SxmlFirstChild(SxmlNode *node);
 +
</source>
 +
 +
<source lang="c">
 +
SxmlNode *SxmlLastChild(SxmlNode *node);
 +
</source>
 +
 +
Exemple :
 +
<source lang="c">
 +
...
 +
SxmlPrint (SxmlFirstChild(myNodeTest)) ;  /* imprime a1 */
 +
SxmlPrint (SxmlLastChild(myNodeTest));  /* imprime <c>c1</c> */
 +
...
 +
</source>
 +
 +
 +
Les 2 fonctions suivantes permettent d'accéder aux voisins (avant, après) d'un noeud.
 +
 +
<source lang="c">
 +
SxmlNode *SgmlNextSibling(SxmlNode *node);
 +
</source>
 +
 +
<source lang="c">
 +
SxmlNode *SxmlPreviousSibling(SxmlNode *node);
 +
</source>
 +
 +
Enfin cette fonction permet d'accéder au père.
 +
 +
<source lang="c">
 +
SxmlNode *SgmlParent(SxmlNode *node);
 +
</source>
 +
 +
===Les caractéristiques d'un nœud===
 +
 +
Pour un nœud de type SxmlElement
 +
 +
<source lang="c">
 +
char *SxmlNodeName(node);
 +
</source>
 +
 +
Pour un noeud de type SxmlText :
 +
<source lang="c">
 +
char *SxmlText(noeud);
 +
</source>
 +
 +
===test de type===
 +
 +
<source lang="c">
 +
int SgmlIsText(node);
 +
int SgmlIsElement(node);
 +
</source>
 +
 +
 +
==Itérations sur les composants d'un noeud==
 +
 +
 +
===Principe===
 +
 +
Toutes les fonctions renvoient la valeur NULL en cas d'échec ou d'absence d'un élément. Ceci permet de réaliser des itérations sur les objets XML contenus dans un élément.
 +
 +
Squelette d'une itérations sur les fils d'un nœud.
 +
;Avec une boucle do:
 +
 +
if ((fils = SxmlFirstChild (pere)))
 +
  {
 +
    do
 +
      { ''traitement sur fils'' }
 +
    while ((fils=SxmlNextSibling(fils)));
 +
  }
 +
else
 +
  { ''traitement de l'exception''}
 +
 +
;Avec une boucle while:
 +
  fils = SxmlFirstChild (pere);
 +
  while (fils)
 +
  {
 +
    ''traitement sur fils''
 +
    fils=SxmlNextSibling(fils);
 +
  }
 +
 +
===Exemple===
 +
Édition de toutes les étiquettes des fils d'un nœud.
 +
<source lang="c">
 +
editChildTag ( SxmlNode *node)
 +
{
 +
  SxmlNode *c1;
 +
  if ((c1=SxmlFirstChild(node)))
 +
do{
 +
            if(SxmlIsElement(c1))
 +
        printf("%s\n",SgmlTag(c1));
 +
      } while ((son=SxmlNextSibling(c1)));
 +
}
 +
</source>
 +
===Itérateurs===
 +
Dans la bibliothèque Dilib, un itérateur est associé à un élément XML. La fonction <code>SxmlNextNode</code> renvoie le fils suivant. La fonction <code>SxmlReset</code> initialise l'itérateur. L'exemple précédent se réécrit ainsi.
 +
<source lang="c">
 +
editChildTag ( SxmlNode *node)
 +
{
 +
  SxmlNode *c1;
 +
  SxmlReset (node);
 +
  while (c1=SxmlNextNode(node))
 +
    {
 +
      if(SxmlIsElement(c1)) printf("%s\n",SgmlTag(c1));
 +
    }
 +
}
 +
</source>
 +
 +
==Import export de structures XML==
 +
La construction d'un arbre XML bien formé peut se faire sans DTD ni schéma.
 +
 +
===Conversion XML en string===
 +
Les fonctions d'entreés sorties utilisent un noyau de 2 procédures de conversion vers les
 +
chaine (char *) de C.
 +
 +
Nous avons vu la construction d'un arbre XML à partir d'une chaîne.
 +
<source lang="c">
 +
SxmlNode* SxmlFromString(char *string);
 +
</source>
 +
 +
Il est possible de convertir un arbre XML en String.
 +
<source lang="c">
 +
char *SxmlToString (SgmlNode *node);
 +
</source>
 +
 +
==Entrées-sorties==
 +
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 :
 +
 +
<pre>
 +
SgmlPrint(node);
 +
</pre>
 +
 +
Impression d'un objet SGML dans un fichier :
 +
 +
<pre>
 +
SxmlFilePrint(FILE *file, SxmlNode* node);          ;
 +
</pre>
 +
 +
lecture du prochain document SGML sur l'entrée standard.
 +
<pre>
 +
SgmlNode *SxmlInputGetDocumentElement();
 +
</pre>
 +
===Exemple===
 +
Impression de tous les premiers fils ayant &#171;a&#187; pour balise.
 +
 +
<source lang="c">
 +
#include "SxmlNode.h"
 +
main()
 +
{
 +
  SxmlNode *docu ,*son;
 +
  while(docu=SxmlInputGetDocumentElement())
 +
    {
 +
      if (son=SxmlFirstChild(docu))
 +
        {if (strcmp(SxmlNodeName(son), "a")==0)
 +
                {SxmlPrint(son);putchar('\n');
 +
    }}};
 +
}
 +
</source>
 +
 +
Pour tester :
 +
<source lang="xml">
 +
<doc>texte<a>ah ah</a><b><a>ne doit pas sortir</a></b><a><b>ici B dans A</b></a>fin</doc>
 +
</source>

Version actuelle datée du 25 juin 2020 à 08:03

un arbre XML contenant 6 nœuds

Création d'un arbre à partir d'une chaîne

En langage C les chaînes de caractères sont de type char *.

Dans la bibliothèque Dilib, il est très facile de construire un arbre XML à partir de la fonction SxmlFromString.

  SxmlNode *SxmlFromgString(char *string);

Exemple, pour créer l'arbre de la figure ci-dessus :

#include "SxmlNode.h"
#include <stdio.h>
main()
{
   SxmlNode *myNodeTest;  
     ...
   myNodeTest=SxmlFromString("<a>a1<b>b1</b><c>c1</c></a>");
     ...
}

Accès à l'environnement d'un nœud

Les voisins ou parents

Toutes les fonctions retournent un pointeur NULL en cas d'échec.

Les 2 fonctions suivantes permettent d'accéder au premier et au dernier fils d'un noeud.

SxmlNode *SxmlFirstChild(SxmlNode *node);
SxmlNode *SxmlLastChild(SxmlNode *node);

Exemple :

 ...
 SxmlPrint (SxmlFirstChild(myNodeTest)) ;  /* imprime a1 */
 SxmlPrint (SxmlLastChild(myNodeTest));   /* imprime <c>c1</c> */
 ...


Les 2 fonctions suivantes permettent d'accéder aux voisins (avant, après) d'un noeud.

SxmlNode *SgmlNextSibling(SxmlNode *node);
SxmlNode *SxmlPreviousSibling(SxmlNode *node);

Enfin cette fonction permet d'accéder au père.

SxmlNode *SgmlParent(SxmlNode *node);

Les caractéristiques d'un nœud

Pour un nœud de type SxmlElement

char *SxmlNodeName(node);

Pour un noeud de type SxmlText :

char *SxmlText(noeud);

test de type

int SgmlIsText(node);
int SgmlIsElement(node);


Itérations sur les composants d'un noeud

Principe

Toutes les fonctions renvoient la valeur NULL en cas d'échec ou d'absence d'un élément. Ceci permet de réaliser des itérations sur les objets XML contenus dans un élément.

Squelette d'une itérations sur les fils d'un nœud.

Avec une boucle do
if ((fils = SxmlFirstChild (pere)))
  {
    do 
      { traitement sur fils }
    while ((fils=SxmlNextSibling(fils)));
  }
else
 { traitement de l'exception}
Avec une boucle while
 fils = SxmlFirstChild (pere);
 while (fils)
  {
    traitement sur fils 
    fils=SxmlNextSibling(fils);
  }

Exemple

Édition de toutes les étiquettes des fils d'un nœud.

editChildTag ( SxmlNode *node)
{
  SxmlNode *c1;
  if ((c1=SxmlFirstChild(node)))
	do{ 
            if(SxmlIsElement(c1))
	        printf("%s\n",SgmlTag(c1));
      } while ((son=SxmlNextSibling(c1)));
}

Itérateurs

Dans la bibliothèque Dilib, un itérateur est associé à un élément XML. La fonction SxmlNextNode renvoie le fils suivant. La fonction SxmlReset initialise l'itérateur. L'exemple précédent se réécrit ainsi.

editChildTag ( SxmlNode *node)
{
  SxmlNode *c1;
  SxmlReset (node);
  while (c1=SxmlNextNode(node))
    {
       if(SxmlIsElement(c1)) printf("%s\n",SgmlTag(c1));
    }
}

Import export de structures XML

La construction d'un arbre XML bien formé peut se faire sans DTD ni schéma.

Conversion XML en string

Les fonctions d'entreés sorties utilisent un noyau de 2 procédures de conversion vers les chaine (char *) de C.

Nous avons vu la construction d'un arbre XML à partir d'une chaîne.

SxmlNode* SxmlFromString(char *string);

Il est possible de convertir un arbre XML en String.

char *SxmlToString (SgmlNode *node);

Entrées-sorties

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 *file, SxmlNode* node);          ;

lecture du prochain document SGML sur l'entrée standard.

SgmlNode *SxmlInputGetDocumentElement();

Exemple

Impression de tous les premiers fils ayant «a» pour balise.

#include "SxmlNode.h"
main()
{
  SxmlNode *docu ,*son;
  while(docu=SxmlInputGetDocumentElement())
    {
       if (son=SxmlFirstChild(docu))
         {if (strcmp(SxmlNodeName(son), "a")==0)
                 {SxmlPrint(son);putchar('\n');
    }}};
}

Pour tester :

<doc>texte<a>ah ah</a><b><a>ne doit pas sortir</a></b><a><b>ici B dans A</b></a>fin</doc>