Parser un fichier xml

boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 18 août 2009 à 21:46
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 - 24 nov. 2009 à 22:51
Bonsoir,

Je voulais parser mon fichier XML pouyr extraire certaines informations pour les utiliser dans mon programme C.

J'ai trouvé la librairie libxml2 qui est codée en C et qui possède deux méthodes DOM et SAX.

J'ai bien installé libxml2 et j'ai décidé de travailler avec la méthode SAX qui permet de parser des fichiers XML assez grand et n'est pas gourmande en mémoire.

J'ai trouvé des exemples en général et non simples pour un débutant sur le site officiel de libxml2. Ces exemples sont plus pour la méthode DOM. Je ne trouve pas un exemple pour SAX.

- Est ce que il y a quelqu'un qui a rencontré ce type de problème ?

- Pouvez vous me donner un exemple typique pour que j'applique sur mon fichier XML car j'ai besoin des informations qui se trouvent dans le dernier noeud de mon fichier XML ?

Merci.

208 réponses

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
26 août 2009 à 09:34
attend un peu....
je résume mon code source, tu ne semble pas l'avoir compris...

il va remplir (en mémoire) toutes les references (tableau) de chacune des entités 'Concept'

POINT BARRE

après, pour l'exemple (et controle), j'ai généré le fichier resultat.txt


si tu as besoin de manipuler ces references depuis d'autres partieds de ton programme, utilises _concepts : le tableau des entités <concept>

libre à toi d'en faire ce que tu veux.

c'est déjà tout en mémoire, facilement accessible (voir code permettant la génération de resultat.txt, c'est un exemple d'utilisation de _concepts)
inutile de placer le tout dans un fichier texte ou de renvoyer "d b c a" puisqu'il faudrait réanalyser cette chaîne pour en séparer les éléments.

là, tu as tout, dans un tableau de concept, qui contient une liste chainée permettant d'accéder à chaque référence...

que vouloir de plus ?

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
2 sept. 2009 à 10:14
Bonjour,

Je vous remercie pour votre assistance.
Je suis désolée pour le retard de vous répondre car j'ai eu un problème de connexion.
Votre solution nous affiche l'ensemble des intentions (les valeurs qui existent entre et de tous les identificateurs du fichier xml.

ceci me répond à une partie (un cas parmi les cas) de mon travail.
J'ai plusieurs cas dans le main de mon programme "main.c"

cas 1:
afficher l'extension (la valeur qui existe entre <extent> </extent> ) et l'intention (la valeur qui existe entre ) de dernier identificateur
par exemple dans notre cas, on a id= 11
le résultat à afficher
extent= est vide
intent= " d b c a"

cas 2:
la même chose que dans cas 1

cas 3:
la même chose que dans cas 1

cas 4 :
afficher l'extension (la valeur qui existe entre <extent> </extent> ) et l'intention (la valeur qui existe entre ) des identificateur qui sont les valeurs qui existent entre <concept_Ref> </concept_Ref>
de dernier identificateur de fichier xml

par exemple dans notre cas:
le dernier identificateur =11
on s'intéresse à cette partie de ce id = 11
les identificateurs 10, 8, 9 et 7 sont liés au id=10


<Concept_Ref>10</Concept_Ref>

<Concept_Ref>8</Concept_Ref>

<Concept_Ref>9</Concept_Ref>

<Concept_Ref>7</Concept_Ref>



Nous avons les id =10, id=8, id=9 et id =7
alors nous allons afficher comme décrit dans cas 1 cas 2 et cas 3 les extensions ((la valeur qui existe entre <extent> </extent> ) et les intentions (la valeur qui existe entre )
pour id =10, id= 8, id=9 et id =7

Donc nous obtenons pour ce cas:
5 d b a
1 c a
4 b c
3 d c

cas 5:
afficher seulement les intentions (la valeur qui existe entre ) de tous les identificateurs de fichier xml
dans notre cas, nous obtenons:
a
b
c
d
c a
b c
d b
d c
d b a
d b c a

Le problème est Comment vous adaptez votre solution pour obtenir selon les cas qui existent dans "main"?

Voici un exemple de "main"
Voici un exemple de "main.c" 

#include<stdio.h>

#include<conio.h>



int main()

{

........

.......

if(cas  == 1)

//appel de votre solution

//le résultat est doit être sauvegardé dans un fichier ou autre structure pour les utiliser après dans le main



if (cas == 1 )
//comment appeler et adapter  votre solution? 

if (cas == 2 )
//comment appeler et adapter  votre solution?

if (cas == 3 )
//comment appeler et adapter  votre solution?

if (cas == 4 )
//comment appeler et adapter  votre solution?

if (cas == 5 )
//comment appeler et adapter  votre solution?

...........

............

return 0;

}



Voici un exemple de fichier xml:
<Galicia_Document>

<Lattice numberObj="5" numberAtt="4" numberCpt="11">

<Name>lattice(essai)</Name>

<Object>3</Object>

<Object>2</Object>

<Object>1</Object>

<Object>5</Object>

<Object>4</Object>

d

b

c

a

<Concept>

 1 

<Extent>

<Object_Ref>3</Object_Ref>

<Object_Ref>2</Object_Ref>

<Object_Ref>1</Object_Ref>

<Object_Ref>5</Object_Ref>

<Object_Ref>4</Object_Ref>

</Extent>









</Concept>

<Concept>

 2 

<Extent>

<Object_Ref>1</Object_Ref>

<Object_Ref>5</Object_Ref>

</Extent>



a





<Concept_Ref>1</Concept_Ref>



</Concept>

<Concept>

 5 

<Extent>

<Object_Ref>2</Object_Ref>

<Object_Ref>5</Object_Ref>

<Object_Ref>4</Object_Ref>

</Extent>



b





<Concept_Ref>1</Concept_Ref>



</Concept>

<Concept>

 4 

<Extent>

<Object_Ref>3</Object_Ref>

<Object_Ref>1</Object_Ref>

<Object_Ref>4</Object_Ref>

</Extent>



c





<Concept_Ref>1</Concept_Ref>



</Concept>

<Concept>

 3 

<Extent>

<Object_Ref>3</Object_Ref>

<Object_Ref>2</Object_Ref>

<Object_Ref>5</Object_Ref>

</Extent>



d





<Concept_Ref>1</Concept_Ref>



</Concept>

<Concept>

 8 

<Extent>

<Object_Ref>1</Object_Ref>

</Extent>



c

a





<Concept_Ref>2</Concept_Ref>

<Concept_Ref>4</Concept_Ref>



</Concept>

<Concept>

 9 

<Extent>

<Object_Ref>4</Object_Ref>

</Extent>



b

c





<Concept_Ref>5</Concept_Ref>

<Concept_Ref>4</Concept_Ref>



</Concept>

<Concept>

 6 

<Extent>

<Object_Ref>2</Object_Ref>

<Object_Ref>5</Object_Ref>

</Extent>



d

b





<Concept_Ref>5</Concept_Ref>

<Concept_Ref>3</Concept_Ref>



</Concept>

<Concept>

 7 

<Extent>

<Object_Ref>3</Object_Ref>

</Extent>



d

c





<Concept_Ref>4</Concept_Ref>

<Concept_Ref>3</Concept_Ref>



</Concept>

<Concept>

 10 

<Extent>

<Object_Ref>5</Object_Ref>

</Extent>



d

b

a





<Concept_Ref>2</Concept_Ref>

<Concept_Ref>6</Concept_Ref>



</Concept>

<Concept>

 11 

<Extent>

</Extent>



d

b

c

a





<Concept_Ref>10</Concept_Ref>

<Concept_Ref>8</Concept_Ref>

<Concept_Ref>9</Concept_Ref>

<Concept_Ref>7</Concept_Ref>



</Concept>

</Lattice>

</Galicia_Document>



J'ai besoin de votre aide car je suis bloquée et je n'arrive pas à résoudre complètement ce problème.

Merci.
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
5 sept. 2009 à 08:04
Bonjour,

Je te remercie pour votre aide précédemment.
Vous avez bien compris ma dernière demande datée le mercredi 2 septembre 2009 à 10:14:19
sinon je te explique de nouveau ?

S'il vous plait j'ai besoin de votre aide.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:18
cas 1, 2 et 3 sont aisément faisables...
il s'agit d'afficher uniquement les infos du dernier concept en mémoire...

cas 5 facile aussi : il s'agit de ce qui est actuellement fait.

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:37
et voilà :

c'était pas la mer à boire !
faudrait que tu commence a comprendre la mécanique sinon tu vas pas t'en sortir.

les listes chainées, c'est le B.A.BA, on apprend ca très tot !

#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>
#pragma comment(lib,"libxml2.lib")

typedef struct {
char* reference;
void* next;
} REF;

typedef struct {
char* ID;
REF* references;
REF* upperCovers; 
} CONCEPT ;

CONCEPT* _concepts = 0;
int  _countCpt = 0;    // Permet de compter les occurrences de <Concept>
int  _currentCpt = -1;  // Permet de compter les occurrences de <Concept>
int  _inAttribute = 0;
int  _inConceptRef = 0;
int  _inID = 0;

void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs){
int i;
// Si on est sur un Lattice...
if (!xmlStrcmp(name, (xmlChar*)"Lattice") && attrs) {
// On parcoure les attributs
for (i = 0; attrs[i]; i+=2) {
// Jusqu'à trouver l'atribut numberCpt
            if (!xmlStrcmp(attrs[i], (xmlChar*)"numberCpt")) {
// Que l'on mémorise (strtol permet d'analyser la valeur texte, pour en faire une valeur numérique)
_countCpt = strtol((const char*)attrs[i+1],NULL,0);
// on créé un tableau qui va contenir les concepts.
_concepts = (CONCEPT*)calloc(_countCpt, sizeof(CONCEPT));

break; // inutile de considérer les attributs suivants
            }
        }
}
else if (!xmlStrcmp(name, (xmlChar*)"Concept") && _countCpt)
_currentCpt++;
else if (!xmlStrcmp(name, (xmlChar*)"Concept_Ref") && _countCpt)
_inConceptRef = 1;
else if (!xmlStrcmp(name, (xmlChar*)"Attribute_Ref"))
_inAttribute = 1; // On souhaite mémoriser les Attribute_Ref
else if (!xmlStrcmp(name, (xmlChar*)"ID"))
_inID = 1; // On souhaite mémoriser les Attribute_Ref

}

void characters(void* user_data, const xmlChar *ch, int len) {
if (_inID && len) {
_concepts[_currentCpt].ID = (char*)malloc(len+1);
strncpy(_concepts[_currentCpt].ID, ch, len);
*(_concepts[_currentCpt].ID+len) = 0;
_inID = 0;
}
else if ((_inAttribute || _inConceptRef) && len)
{	
// lien vers les references du concept courant
REF** source;
REF* ref;
REF* newRef;

if (_inAttribute)
source = &(_concepts[_currentCpt].references);
else
source = &(_concepts[_currentCpt].upperCovers);

ref = *source;

// on créé une nouvelle reference
newRef = (REF*)calloc(1, sizeof(REF));

// permet de relier la nouvelle reference a la structure (liste chainee)
if (ref) {
while(ref->next)
ref = (REF*)ref->next;
ref->next = newRef;
}
else
*source = newRef;			

// on recopie le contenu de la reference
newRef->reference = (char*)malloc(len+1);
strncpy(newRef->reference, ch, len);
*(newRef->reference+len) = 0;	

_inAttribute = 0;
_inConceptRef = 0;
}
}

// Permet de désallouer proporement la structure
void cleanup()
{
int i;
REF* ref;
for (i=0; i<_countCpt; i++) {
free(_concepts[i].ID);
ref = _concepts[i].references;
while (ref) {
free(ref->reference);
ref = ref->next;
}

ref = _concepts[i].upperCovers;
while (ref) {
free(ref->reference);
ref = ref->next;
}
}
free(_concepts);
}



int main()
{
REF* ref;
REF* index;
int i;

// structure permettant de renseigner les handlers perso à invoquer pour nos evenements de lecture
    xmlSAXHandler sh = { 0 };
sh.startElement = startElement;
    sh.characters = characters;

// On appelle l'enalyse du fichier XML
if(xmlSAXUserParseFile(&sh, NULL, "Input.xml")) {
printf("Un erreur est survenue. Le fichier XML est peut-être mal consitué");
return -1;
}

printf("\nCas 1, 2 et 3 :\n");
ref = _concepts[_countCpt-1].references;
while (ref) {
printf("%s ", ref->reference);
ref = ref->next;
}
printf("\n");

printf("\nCas 4 :\n");
index = _concepts[_countCpt-1].upperCovers;
while (index) {
printf("%s ", index->reference);
for (i=0; i<_countCpt; i++) {
if (strcmp(index->reference, _concepts[i].ID)==0) {
ref = _concepts[i].references;
if (ref) {
while (ref) {
if (ref->reference)
printf("%s ", ref->reference);
ref = ref->next;
}
}
}
}
printf("\n");	
index = index->next;
}

printf("\nCas 5 :\n");
for (i=0; i<_countCpt; i++) {
ref = _concepts[i].references;
if (ref) {
while (ref) {
if (ref->reference)
printf("%s ", ref->reference);
ref = ref->next;
}
printf("\n");
}
}

system("pause");

cleanup();
return 0;
}


NB: j'ai modifié le fichier XML : il semble que tu avais parfois :

1

au lieu de

1



Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:38
et en sortie, j'obtiens bien :



Cas 1, 2 et 3 :
d b c a

Cas 4 :
10 d b a
8 c a
9 b c
7 d c

Cas 5 :
a
b
c
d
c a
b c
d b
d c
d b a
d b c a
Appuyez sur une touche pour continuer...

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:39
NB. Pour le cas 4, j'ai pas mis l'extent, je te laisse relever enfin tes manches et le faire par toi même


Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:51
j'ai fait la modif pour l'extent, c'est aisé si tu réutilise l'existant.
je la garde de coté pour te corriger.

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:51
ma sortie actuelle est donc :


Cas 1, 2 et 3 :
d b c a

Cas 4 :
5 : d b a
1 : c a
4 : b c
3 : d c

Cas 5 :
a
b
c
d
c a
b c
d b
d c
d b a
d b c a
Appuyez sur une touche pour continuer...

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
7 sept. 2009 à 14:53
Bien évidemment, et encore une fois, la sortie dans la console ou dans un fichier n'est là qu'a titre d'exemple.

il n'est pas concevable d'utiliser ces fichiers pour stocker les structures au sein du programme : les données requises sont en mémoire et facilement accessibles via _concepts.

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
8 sept. 2009 à 00:30
Bonsoir,

Après la compilation et l'exécution de votre dernier code, j'obtiens cet affichage dans la console:

Cas 1, 2 et 3 :
d b c a

Cas 4 :
10
8
9
7

Cas 5 :
a
b
c
d
c a
b c
d b
d c
d b a
d b c a
Appuyez sur une touche pour continuer...



Mais, je voulais obtenir le résultat suivant:
Pour les cas 1, 2, 3 et 4 alors on affiche l'Extent et l'Intent de dernier identificateur

Dans notre exemple, on a pour le dernier identificateur un extent vide et intent égale "d b c a"
de façon générale nous obtenons:
extent intent

Cas 1, 2 et 3 :
d b c a

Cas 4 :
5 b d a
1 c a
4 b c
3 d c

Cas 5 :
a
b
c
d
c a
b c
d b
d c
d b a
d b c a
Appuyez sur une touche pour continuer...



Quelles sont les modifications à faire dans le dernier code proposé ?

Merci.
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
8 sept. 2009 à 00:34
Je crois que nous avons le même fichier xml.
Voici le fichier xml:
<Galicia_Document>
<Lattice numberObj="5" numberAtt="4" numberCpt="11">
<Name>lattice(input)</Name>
<Object>3</Object>
<Object>2</Object>
<Object>1</Object>
<Object>5</Object>
<Object>4</Object>
d
b
c
a
<Concept>
 1 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>5</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>




</Concept>
<Concept>
 2 
<Extent>
<Object_Ref>1</Object_Ref>
<Object_Ref>5</Object_Ref>
</Extent>

a


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 5 
<Extent>
<Object_Ref>2</Object_Ref>
<Object_Ref>5</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

b


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 4 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>4</Object_Ref>
</Extent>

c


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 3 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>5</Object_Ref>
</Extent>

d


<Concept_Ref>1</Concept_Ref>

</Concept>
<Concept>
 8 
<Extent>
<Object_Ref>1</Object_Ref>
</Extent>

c
a


<Concept_Ref>2</Concept_Ref>
<Concept_Ref>4</Concept_Ref>

</Concept>
<Concept>
 9 
<Extent>
<Object_Ref>4</Object_Ref>
</Extent>

b
c


<Concept_Ref>5</Concept_Ref>
<Concept_Ref>4</Concept_Ref>

</Concept>
<Concept>
 6 
<Extent>
<Object_Ref>2</Object_Ref>
<Object_Ref>5</Object_Ref>
</Extent>

d
b


<Concept_Ref>5</Concept_Ref>
<Concept_Ref>3</Concept_Ref>

</Concept>
<Concept>
 7 
<Extent>
<Object_Ref>3</Object_Ref>
</Extent>

d
c


<Concept_Ref>4</Concept_Ref>
<Concept_Ref>3</Concept_Ref>

</Concept>
<Concept>
 10 
<Extent>
<Object_Ref>5</Object_Ref>
</Extent>

d
b
a


<Concept_Ref>2</Concept_Ref>
<Concept_Ref>6</Concept_Ref>

</Concept>
<Concept>
 11 
<Extent>
</Extent>

d
b
c
a


<Concept_Ref>10</Concept_Ref>
<Concept_Ref>8</Concept_Ref>
<Concept_Ref>9</Concept_Ref>
<Concept_Ref>7</Concept_Ref>

</Concept>
</Lattice>
</Galicia_Document>

0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
8 sept. 2009 à 08:48
Pourquoi y a t'il des espaces là :

4



Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
8 sept. 2009 à 08:50
Lire les extent ou tout autre chose est aisé...

suffit de se baser sur le code actuel, et d'enrichir la structure d'une nouvelle liste chainee...


Vas tu te mettre enfin au boulot ou attend tu simplement du code clé en main ?

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
8 sept. 2009 à 20:43
Bonsoir,

C'est vraie que je dois maitriser votre solution et apprendre comment parser un fichier xml dans un programme C.

Vue c'est la premier fois que je fais ceci.
Pouvez vous me décrire les étapes que vous avez suit pour arriver à trouver une solution à ce problème malgré il reste une dernière étape concernant "l'extent" ?

Pouvez vous commenter votre solution pour puisse comprendre mieux vos idées ?

C'est possibles me donner les étapes à suivre en général en cas on va chercher autres informations à partir de fichier xml ?

Je serais très contente si vous m'aidez ?

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
9 sept. 2009 à 08:49
commenter ma solution ? elle l'est.
pour les étapes, c'est strictement identique (liste chainee) a ce qui se fait déjà.

je vais détailler davantage, et te filer la solution que tu chercheras, je l'espère a comprendre.

NB. sauf si la finalité est d'obtenir un fichier resultat.txt tel que tu me le décrit, IL FAUDRA exploiter la structure en mémoire.


ah... quand je pense qu'a la base tu demandais un exemple de parsing via SAX...

Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
9 sept. 2009 à 12:53
#include <stdlib.h>
#include <string.h>
#include <libxml/parser.h>
#pragma comment(lib,"libxml2.lib")

void DisplayConceptInfos(int, int);

// Structure de base pour nos listes chainées.
// Il s'agit en fait de stocker un nombre non défini de chaines de caractères
typedef struct {
char* reference; // la donnée proprement dite
void* next;      // pointeur vers la reference suivante (ou 0 s'il n'y a plus de donnée) 
} REF;

// Structure décrivant les <Concept>
typedef struct {
char* ID;         // Valeur de l'Id
REF* intent;      // Liste des  de l'
REF* upperCovers; // Liste des <Concept_Ref> de l'
REF* extent;      // Liste des <Object_Ref> de l'<extent>
} CONCEPT ;

CONCEPT* _concepts =  NULL;   // Tableau de <Concept>	    
int  _countCpt = 0;          // Permet de compter les occurrences de <Concept>
int  _currentCpt = -1;
int  _inIntent = 0;          // Si a 1, la prochaine donnée lue sera un  et sera ajoutée dans la liste des 
int  _inUpperCovers = 0;     // idem pour l' 
int  _inExtent = 0;          // idem pour l'<extent>
int  _inID = 0;              // Si a 1, la prochaine donnée lue sera l'ID du <Concept>

void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs){
int i;
// Si on est sur un Lattice...
if (!xmlStrcmp(name, (xmlChar*)"Lattice") && attrs) {
// On parcoure les attributs
for (i = 0; attrs[i]; i+=2) {
// Jusqu'à trouver l'atribut numberCpt
            if (!xmlStrcmp(attrs[i], (xmlChar*)"numberCpt")) {
// Que l'on mémorise (strtol permet d'analyser la valeur texte, pour en faire une valeur numérique)
_countCpt = strtol((const char*)attrs[i+1],NULL,0);
// on alloue un tableau qui va contenir les concepts.
_concepts = (CONCEPT*)calloc(_countCpt, sizeof(CONCEPT));				
break; // inutile de considérer les attributs suivants
            }
        }
}
else if (!xmlStrcmp(name, (xmlChar*)"Concept") && _countCpt)
_currentCpt++;
else if (!xmlStrcmp(name, (xmlChar*)"Concept_Ref") && _countCpt)
_inUpperCovers = 1;
else if (!xmlStrcmp(name, (xmlChar*)"Attribute_Ref"))
_inIntent = 1;
else if (!xmlStrcmp(name, (xmlChar*)"Object_Ref"))
_inExtent = 1;
else if (!xmlStrcmp(name, (xmlChar*)"ID"))
_inID = 1;
}

void characters(void* user_data, const xmlChar *ch, int len) {
if (_inID && len) {
// On va enregistrer l'ID, mais en supprimant les espaces qui semblent s'être introduits   5  
while(len>1 && *ch ==32) {
len--;
ch+=sizeof(xmlChar);
}

// On supprime également les espaces qui suivent la valeur.
while(len>1 && *(ch+len-1)==32)
len--;

_concepts[_currentCpt].ID = (char*)malloc(len+1);
strncpy(_concepts[_currentCpt].ID, ch, len);
*(_concepts[_currentCpt].ID+len) = 0;
_inID = 0;
}
else if ((_inIntent || _inUpperCovers || _inExtent) && len)
{	
// lien vers les references du concept courant
REF** source;
REF* ref;
REF* newRef;

if (_inIntent)
source = &(_concepts[_currentCpt].intent);
else if (_inUpperCovers)
source = &(_concepts[_currentCpt].upperCovers);
else if (_inExtent)
source = &(_concepts[_currentCpt].extent);

ref = *source;

// on créé une nouvelle reference
newRef = (REF*)calloc(1, sizeof(REF));

// permet de relier la nouvelle reference a la structure (liste chainee)
if (ref) {
// La liste contient au moins une cellule.
// On va parcourir la liste a la recherche de la dernière cellule (celle qui à le pointeur next à NULL)
while(ref->next)
ref = (REF*)ref->next;
ref->next = newRef;
}
else
*source = newRef; // Première cellule de la liste chainée

// on recopie la donnée
newRef->reference = (char*)malloc(len+1);
strncpy(newRef->reference, ch, len);
// 0 terminal de la chaine de caractères
*(newRef->reference+len) = 0;	

// Remise à 0 des flags de position
_inIntent _inUpperCovers _inExtent = 0;
}
}

// Permet de désallouer proprement la structure
void cleanup()
{
int i;
REF* ref;
for (i=0; i<_countCpt; i++) {
// On libère donc une a une les zones mémoire allouées
free(_concepts[i].ID);

// On néttoie ensuite les listes chainées, une à une.
ref = _concepts[i].intent;
while (ref) {
free(ref->reference);
ref = ref->next;
}

ref = _concepts[i].upperCovers;
while (ref) {
free(ref->reference);
ref = ref->next;
}

ref = _concepts[i].extent;
while (ref) {
free(ref->reference);
ref = ref->next;
}
}
// Avant de désallouer le tableau de Concepts
free(_concepts);
}

int main()
{
REF* index;
int i;

// structure permettant de renseigner les handlers perso à invoquer pour nos evenements de lecture
    xmlSAXHandler sh = { 0 };
sh.startElement = startElement;
    sh.characters = characters;

// On appelle l'enalyse du fichier XML
if(xmlSAXUserParseFile(&sh, NULL, "Input.xml")) {
printf("Un erreur est survenue. Le fichier XML est peut-être mal consitué");
return -1;
}

printf("\nCas 1, 2 et 3 :\n");
DisplayConceptInfos(_countCpt-1, 1);
printf("\n");

printf("\nCas 4 :\n");
index = _concepts[_countCpt-1].upperCovers;
while (index) {
for (i=0; i<_countCpt; i++) {
if (strcmp(index->reference, _concepts[i].ID)==0)
DisplayConceptInfos(i, 1);
}
index = index->next;
}

printf("\nCas 5 :\n");
for (i=0; i<_countCpt; i++)
DisplayConceptInfos(i, 0);

system("pause");

cleanup();
return 0;
}

// Procédure servant d'exemple
// Permet d'afficher les détails concernant un Concept
// index: indice du concept a afficher
// showExtent: indique si l'on doit ou non afficher les <Extent>
void DisplayConceptInfos(int index, int showExtent) {
REF* ref;

// On valide la valeur de l'index
if (index>0 && index<_countCpt) {
if (showExtent) {
ref = _concepts[index].extent;
if (ref) {
while (ref) {
if (ref->reference)
printf("%s ", ref->reference);
ref = ref->next;
}
printf(": ");
}
}

ref = _concepts[index].intent;
while (ref) {
if (ref->reference)
printf("%s ", ref->reference);
ref = ref->next;
}
printf("\n");	
}
}




Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
10 sept. 2009 à 10:16
Bonjour,

Oui çà marche. Je vous remercie pour votre aide.
ah... quand je pense qu'a la base tu demandais un exemple de parsing via SAX...

Je ne comprends pas. Pouvez vous expliciter de plus ?

Je voulais c'est possible que vous me répondez sur quelques questions:

1)
system("pause");

on peut ne pas mettre cette instruction ?
car j'ai le message sur la console sans faire "pause"

2)
DisplayConceptInfos(i, 0);}


void DisplayConceptInfos(int index, int showExtent) {

REF* ref;
.........
.........
}

void DisplayConceptInfos(int, int);


vous déclarez la fonction DisplayConceptInfos deux fois au début(sans code) de programme et à la fin (avec code) de programme. Pourquoi vous ne la déclarez pas au début seulement ou bien il faut les deux car elles sont différentes ?

3)Vous utilisez malloc et calloc dans le même programme. Quelle est la différence entre les deux ? et dans quel cas on utilise chacune ?
est ce que les deux allouent le même espace mémoire ?

4) Est ce que il y a des outils sous windows qui nous permet de savoir si on a un débordement en mémoire dans un programme C Si non comment utiliser correctement le déboguer de Visual studio 2008 car je n'ai pas utilisé un déboguer avant ?

5) Vous avez travaillé avant sur le parseur xml en C ? sans vous je n'arrive pas à sortir de ce problème car je ne sais pas même le principe et les étapes à suivre pour parser un fichier xml en C.
Je sais que dans un programme C habituel je peux exécuter même manuellement le programme en partant de la première instruction dans "main" jusqu'à la dernière instruction et si il y a un appel à une fonction alors on exécute cette fonction puis retour au "main".

Donc notre cas, comment s'exécute ce programme
Je serais très contente de me donner une trace manuellement de l'exécution de ce programme pour comprendre mieux ? car je ne sais pas de quelle instruction commence l'exécution ? et quand on appelle les fonctions :"startElement", "characters", "xmlSAXUserParseFile",...?
et dans quel ordre ?

Est ce que le code suivant qui se trouve au début de "main" s'exécute une seule fois ou bien autrement ?

  xmlSAXHandler sh = { 0 };

sh.startElement = startElement;

    sh.characters = characters;


7) Est ce que on peut améliorer cette solution de sorte que le temps d'exécution soit inférieur ? et Est ce que tous les cas sont prévus par exemple l'allocation et libération de mémoire , pas autres tests à faire etc..?

8) A part l'affichage en console, je voulais sauvegarder le résultat de chaque cas dans un fichier texte.
FILE *fp;
fp = fopen("resultat.txt","w");
fprintf(fp,............);
fclose(fp)


Est ce que ce code doit être mis dans la fonction
"DisplayConceptInfos(int index, int showExtent)"
ou bien on doit le mettre dans une autre fonction à part ?

9)Je voulais faire une expérimentation où je vais tracer une courbe (temps en fonctions de nombre de concepts). Pour voir l'allure de la courbe si il est polynomiale ou bien exponentielle.
Pour mesurer le temps d'exécution de ce traitement qui permet de parser un fichier, j'ai mis ceci:
int main()
{
double debut,end;
..............
..............
debut = clock();
//traitements
..........
..........

 fin = clock();

fprintf(stderr, "\ntemps : %f\n", (double)(fin-debut) / (double) CLOCKS_PER_SEC);

    return 0;
}


Est ce que cette fonction est bonne ou bien il y a autres fonctions qui nous donnent le temps précis ni plus ni moins ? j'obtiens un temps t différent ou bien égale à chaque fois que je lance l'exécution de plus il arrive que
t =0.000000 malgré que il existe un traitement.
et comment éviter d'obtenir un temps nul ?

10)
J'ai décidé de travailler avec la librairie libxml2 car il est en C et surtout avec la méthode SAX car elle n'est pas couteuse en mémoire et rapide par rapport à la méthode DOM qui génère un arbre présentant le fichier xml.
Que pensez vous à ce choix ?

Je serais très contente pour toute proposition et tout conseil.

Merci.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
10 sept. 2009 à 10:43
1)
system("pause");
on peut ne pas mettre cette instruction ? 
car j'ai le message sur la console sans faire "pause" 


ben oui, tu fais ce que tu veux ^^


2)
void DisplayConceptInfos(int, int);

Il s'agit d'un prototype. Il faut en fait 'annoncer' la fonction pour main, parce qu'elle est codée après elle dans le code.


3)
calloc initialize la mémoire à 0
http://msdn.microsoft.com/fr-fr/library/3f8w183e.aspx


4)
Je ne sais pas trop... j'ai fait les choses proporement, me semble-t'il.



5)
J'avais jamais touché libXml avant...
Tu peux tracer le code en pressant F10 ...
il fonctionne comme tout programme, en executant une a une les lignes du Main.
concernant StartElement et characters, en fait, c'est libXMl qui s'occupe d'en faire l'appel lorsqu'en analysant notre fichier XML il tombe sur une ouverture de balise, ou sur la lecture de contenu CData. Ainsi, on a juste a mémoriser certains états et hop!


7)
L'utilisation de liste chainées évite les lenteurs de la réallocation.
La vitesse d'execution me semble plus que correcte.
a noter que je ne fais allusion qu'au remplissage du tableau _concepts.
après, l'utilisation que tu feras de ce tableau ne regarde que toi.
tant que tu appelles bien Cleanup(), tout ira bien avec la mémoire, normallement.

8)
a toi de voir...
l'ouverture du fichier dans le Main, je dirai, passage du fp à DisplayConceptInfos qui lui utilisera fprintf


9)
0 ? c'est que c'est rapide.
faire des tests avec de très gros fichiers XML, c'est uniquement cela qui importe.
je pense pas que le temps soit exponentiel... on n'utilise pas des espaces mémoire contigus du coup, pas de reallocation ni d'incidence lourde du nombre d'elements.


10)
libxml n'est pas la seule a te permettre d'utiliser SAX.
néanmoins c'est une bonne idée puisqu'elle n'est pas gourmande en mémoire : elle lit le fichier et appelle des fonctions pour avertir qu'elle a trouvé tel ou tel element : elle ne stocke rien.
Concernant l'avantage par rapport à DOM... je dirai qu'on a supprimé les infos qui nous etaient inutiles. J'ai recréé les données dans des structures en mémoires également donc...


Renfield - Admin CodeS-SourceS - MVP Visual Basic
0
boualiasma Messages postés 393 Date d'inscription lundi 22 juin 2009 Statut Membre Dernière intervention 23 décembre 2011 5
11 sept. 2009 à 08:05
Bonjour,

Merci beaucoup.

a toi de voir...
l'ouverture du fichier dans le Main, je dirai, passage du fp à DisplayConceptInfos qui lui utilisera fprintf


OK.Je vais voir.

A bientôt
0
Rejoignez-nous