Parser un fichier xml

Signaler
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
-
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

Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
[quote]a toi de voir...
l'ouverture du fichier dans le Main, je dirai, passage du fp à DisplayConceptInfos qui lui utilisera fprintf /quote

Merci. c'est bon çà marche.


Je suis entrain de faire des tests sur des fichiers xml.
J'ai découvert un autre cas intéressant:
on va afficher la liste des "intent" de tous les identificateurs sauf les "intent" de premier "id" et de dernier "id" à condition que "intent" de premier "id" soit vide et "extent" de dernier "id" soit vide

Voici un exemple de fichier xml:
[code=xml]

lattice(Ctx_2)
3
2
1
4
d
c
b
a

1

3
2
1
4







3

2
1
4


b


1



4

3
2
1


a


1



5

3
2
4


d


1



2

3
1
4


c


1



8

3
4


d
c


5
2



11

1
4


c
b


3
2



9

3
1


c
a


4
2



10

3
2


d
a


4
5



6

2
1


b
a


3
4



7

2
4


d
b


3
5



12

4


d
c
b


8
11
7



13

2


d
b
a


10
6
7



14

3


d
c
a


8
9
10



15

1


c
b
a


11
9
6



16



d
c
b
a


12
13
14
15




/code

Comment vous voyez ici:
[code=xml] 1

3
2
1
4


/code
ici on a "intent" de premier "id" est vide donc on n'a pas besoin d'afficher et de sauvegarder cet "intent"

[code=xml] 16

/code
ici on a "extent" de dernier "id" est vide donc on n'a pas besoin d'afficher et de sauvegarder cet "intent"

Donc le résultat souhaité obtenu est :
b
a
d
c
d c
c b
c a
d a
b a
d b
d c b
d b a
d c a
c b a

si par exemple dans un autre fichier xml on a :

"intent" de premier "id" n'est pas vide donc on va afficher et sauvegarder cet "intent"
et/ou
on a "extent" de dernier "id" n'est pas vide donc on va afficher et sauvegarder son "intent"

Quelles sont les modifications à faire dans votre solution pour obtenir le résultat suivant :
b
a
d
c
d c
c b
c a
d a
b a
d b
d c b
d b a
d c a
c b a

tout en vérifiant les deux conditions :
- si on a "intent" de premier "id" n'est pas vide donc on va afficher et sauvegarder cet "intent" sinon(il est vide) on ne l'affiche pas.
et/ou
- si on a "extent" de dernier "id" n'est pas vide donc on va afficher et sauvegarder son "intent" sinon(il est vide) on ne l'affiche pas.

Je serais très contente pour votre aide.

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
pour tester si tel ou tel element est ide, vérifier si la liste chainee corresponde est vide :
si .extent ou .intent du _concepts[0] ou _concepts[_countCpt-1]

est NULL ou pas...

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

Donc, il suffit de faire un test dans la fonction "DisplayConceptInfos" et exactement avant de faire l'affichage ?
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,

J'ai modifié un peu dans la fonction
"DisplayConceptInfos"

J'ai ajouté:
ref1 = _concepts[index].extent;

while (ref && ref1) 


J'ai remarqué que lorsque on a
while(ref)

dèjà ceci c'est un test implicite si si .extent est vide ou non
donc il me reste de tester si .intent est vide ou non.
Voici ma proposition :

void DisplayConceptInfos(int index, int showExtent) {

REF* ref,*ref1;


// 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;
ref1 = _concepts[index].extent;

while (ref && ref1) {

if (ref->reference)
               
printf("%s ", ref->reference);

ref = ref->next;
            
}

printf("\n");

}

}


est ce que il y a des cas ou mon idée ne marche pas ?
Que proposez vous ?

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
a toi de voir, ca ne me choque pas trop...

perso, je ferai :

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



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

Merci beaucoup.

J'ai testé la solution sur le fichier xml suivant nommé "input.xml".

<Galicia_Document>
<Lattice numberObj="4" numberAtt="2" numberCpt="1">
<Name>lattice(Ctx_0)</Name>
<Object>3</Object>
<Object>2</Object>
<Object>1</Object>
<Object>10</Object>
salaire_faible
taille_petite
<Concept>
 1 
<Extent>
<Object_Ref>3</Object_Ref>
<Object_Ref>2</Object_Ref>
<Object_Ref>1</Object_Ref>
<Object_Ref>10</Object_Ref>
</Extent>

nom
prenom



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


Ce fichier comme vous remarquez contient un seul concept et donc on a un seul identificateur

Lorsque j'exécute le programme sur fichier xml alors il m'affiche le résultat suivant:


cas 1, 2 et 3:

cas 4:

cas 5:
Appuyez sur une touche pour continuer...


Mais le résultat souhaité dans ce cas et sur cet exemple d'après notre principe est:
cas 1, 2 et 3:
nom prenom
cas 4:

cas 5:
nom prenom

Pourquoi la solution ne marche pas sur ce fichier xml ?
C'est le même format que les fichiers qui nous avons déjà testé seulement il contient un seul concept et donc un seul identificateur.
Car on peut avoir des fichiers xml avec le nombre des concepts supérieur ou égale à 1.

Que proposez vous ?

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
en executant la chose pas a pas, on trouve rapidement....


void DisplayConceptInfos(int index, int showExtent) {
REF* ref;

// On valide la valeur de l'index
if (index>=0 && index<_countCpt) {



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

J'ai fait cette modification:
// On valide la valeur de l'index
if (index>=0 && index<_countCpt) {


sur le fichier xml "input.xml" :

<Galicia_Document>

<Lattice numberObj="4" numberAtt="2" numberCpt="1">

<Name>lattice(Ctx_0)</Name>

<Object>3</Object>

<Object>2</Object>

<Object>1</Object>

<Object>10</Object>

nom

prenom

<Concept>

 1 

<Extent>

<Object_Ref>3</Object_Ref>

<Object_Ref>2</Object_Ref>

<Object_Ref>1</Object_Ref>

<Object_Ref>10</Object_Ref>

</Extent>



nom

prenom







</Concept>

</Lattice>

</Galicia_Document>


alors j'obtiens:

cas 1, 2 et 3:
3 2 1 10 : nom prenom
cas 4:

cas 5:
nom prenom


Mais le résultat souhaité dans ce cas et sur cet exemple d'après notre principe est:
cas 1, 2 et 3:
nom prenom
cas 4:

cas 5:
nom prenom


Que proposez vous ?

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
qu'est-ce que je propose ?

que tu ouvres tes yeux...

// 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) {


suffit donc de mettre à 0:

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

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

Merci beaucoup pour votre aide.
Je voulais ajouter la solution à ce problème comme un module dans mon projet C.
Je vais nommer ce module 'extraction.c'

Voici qu'est ce que je fais:

Ceci mon programme 'main.c':
#include <stdio.h>
#include <stdlib.h> 
#include <string.h> 

#include "extraction.h" 
.........

int main()
{
..........
.........
char nom_fichier[32];

sprintf(nom_fichier,"input.xml");
//appel au solution en passant le ficher xml
int extraction(nom_fichier[32])

............
............
return 0;
}


Ceci le module 'extraction.h':
#ifndef CAUSE_REPONSE_H
#define EXTRACTION_H

void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs);

void characters(void *user_data, const xmlChar *ch, int len);

void cleanup();

void DisplayConceptInfos(int index, int showExtent);

int extraction(char nom_fichier[32]);

#endif // EXTRACTION_H


Ceci le module 'extraction.c':
contient la solution proposée par vous tout en changeant
le
int main()
de cette solution par
int extraction(char nom_fichier[32])


on remplace aussi
if(xmlSAXUserParseFile(&sh, NULL, "input.xml"))

par
if(xmlSAXUserParseFile(&sh, NULL, nom_fichier))


et en ajoutant au début :
#include "extraction.h" 



lorsque je compile le 'main.c', j'obtiens ce message des erreurs :

1>c:\test\test\extraction.h(4) : error C2143: erreur de syntaxe : absence de ')' avant '*'

1>c:\test\test\extraction.h(4) : error C2143: erreur de syntaxe : absence de '{' avant '*'

1>c:\test\test\extraction.h(4) : warning C4228: extension non standard utilisée : les qualificateurs situés après la virgule dans la liste des déclarateurs sont ignorés

1>c:\test\test\extraction.h(4) : error C2143: erreur de syntaxe : absence de ';' avant '*'

1>c:\test\test\extraction.h(4) : error C2059: erreur de syntaxe : ')'

1>c:\test\test\extraction.h(5) : error C2143: erreur de syntaxe : absence de ')' avant '*'

1>c:\test\test\extraction.h(5) : error C2143: erreur de syntaxe : absence de '{' avant '*'

1>c:\test\test\cextraction.h(5) : error C2059: erreur de syntaxe : 'type'

1>c:\test\test\extraction.h(5) : error
C2059: erreur de syntaxe : ')'

1>Le journal de génération a été enregistré à l'emplacement "file://c:\test\test\Debug\BuildLog.htm"

1>test - 8 erreur(s), 1 avertissement(s)

======== Génération : 0 a réussi, 1 a échoué, 0 mis à jour, 0 a été ignoré ==========


J'ai remarqué ces erreurs sont liés à la déclaration de deux fonctions suivant dans le module 'extraction.h':
void startElement(void *user_data, 	const xmlChar *name, const xmlChar **attrs);

void characters(void *user_data, const xmlChar *ch, int len);



Pourquoi ces erreurs ?
Je déclare dans la partie *.h les fonctions utilisées dans la partie *.c
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
tu n'as pas à déclarer ces fonctions, elles font partie du fonctionnement interne au parsing.

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

#ifndef _EXTRACTION_H_
#define _EXTRACTION_H_

// 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 ;

void cleanup();
int lire_fichier(char*);

CONCEPT* _concepts;   // Tableau de <Concept>	    
int  _countCpt;          // Permet de compter les occurrences de <Concept>

#endif



main.c
#include "extraction.h"

// 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");	
}
}

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

lire_fichier("Input.xml");

printf("\nCas 1, 2 et 3 :\n");
DisplayConceptInfos(_countCpt-1, 0);
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;
}





extraction.c
#include "extraction.h"

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 lire_fichier(char* nom_fichier)
{
// 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, nom_fichier)) {
printf("Un erreur est survenue. Le fichier XML est peut-être mal consitué");
return -1;
}

return 0;
}


Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
tu n'as pas à déclarer ces fonctions, elles font partie du fonctionnement interne au parsing.


JOui c'est vraie. J'ai supprimé
de 'extraction.h' les deux fonctions internes de parsnig :


#ifndef CAUSE_REPONSE_H

#define EXTRACTION_H

void cleanup();

void DisplayConceptInfos(int index, int showExtent);

int extraction(char nom_fichier[32]);

#endif // EXTRACTION_H



Alors la compilation et l'exécution se passe bien.

j'ai proposé une solution et vous avez proposé une solution.
Laquelle à garder ?

Merci beaucoup pour votre aide.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
Il est logique de déclarer les structures dans le .h puisqu'elle sont utilisées dans main.c et dans extraction.c

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
C'est je voulais mettre les structures dans 'extraction.c' et mettre tout le traitement dans 'extraction.c'.
Juste j'appelle le traitement de 'extraction.c' dans le 'main.c'.
Alors donc ce cas ma solution est logique pas de problème ?
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
oui... tant que ça compile, no soucy

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

Je vois que votre solution concernant l'organisation des modules 'extraction.c', 'extraction.h' et 'main.c' est plus mieux que mienne. De plus, à chaque fois je lis un fichier xml différent et J'ai eu des résultats souhaités différents.
donc de préférence de laisser les fonctions personnalisées dans le 'main.c' et les fonctions internes de parsing dans 'extraction.c'.

Je voulais afficher les résultats souhaités dans un fichier.
Donc, il aura une modification dans la fonction:
void DisplayConceptInfos(int index, int showExtent);


cette fonction va devenir:

void DisplayConceptInfos(int index, int showExtent, FILE *fp_res);


je ne sais pas on va utiliser cette fonction ou non ?

Dans je voulais discuter des cas qui sont discutés avant mais avec un peu de changement.

les valeurs des cas possibles sont générés automatiquement dans le 'main.c'

on a 3 cas :

if(cas == 1)
{

/* dans ce cas je suis sur que dans le fichier xml on a un seul identificateur qui possède un 'extent' non vide et 'intent' non vide.
Je voulais afficher dans le fichier "resultat.txt" (son descripteur est fp_res)
et sur la même ligne la valeur de 'extent' suivie de la valeur 'intent'.
Donc chaque ligne de ce fichier possède deux champs: 'extent et intent'.*/
}

else if (cas == 2)
{

/* c'est le même résultat que nous avons trouvé dans la solution précédente.
c'est à dire c'est le même cas 4 discuté avant
mais Je voulais afficher dans le fichier "resultat.txt" (son descripteur est fp_res)
et sur la même ligne la valeur de 'extent' suivie de la valeur 'intent'.
Donc chaque ligne de ce fichier possède deux champs: 'extent' et 'intent'*/

}

else if (cas == 3)
{

/* c'est le même résultat que nous avons trouvé dans la solution précédente.
c'est à dire c'est le même cas 5 discuté avant
mais Je voulais afficher dans un autre fichier "output.txt" (son descripteur est fp_out)
chaque ligne contient la valeur 'intent'.
Donc chaque ligne de ce fichier possède un seul champ: 'intent'*/

}


Voici le code de 'main.c':
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "extraction.h"

void DisplayConceptInfos(int index, int showExtent, FILE *fp)
{
/*je ne sais pas on va utiliser cette fonction ou non ? */
}

int main()

{

 FILE *fp_res, *fp_out;	
 REF* index;
 int i,cas;

//il y a autres traitements ici
........
.........
//création de deux fichiers 
fp_res = fopen("resultat.txt","w");
fp_out = fopen("output.txt","w");

 lire_fichier("Input.xml");

 if (cas == 1)
{
printf("\nCas 1 :\n");

/* afficher le résultat souhaité dans le fichier "resultat.txt" */

}

else if (cas == 2)
{
printf("\nCas 2 :\n");

/* afficher le résultat souhaité dans le fichier "resultat.txt" */

}

else if (cas == 3)
{
printf("\nCas 3 :\n");

/* afficher le résultat souhaité dans le fichier "out.txt" */

}


system("pause");

cleanup();


return 0;

}




Est ce que on va utiliser la fonction 'DisplayConceptInfos' ou bien non ?

Comment on va adapter la fonction 'DisplayConceptInfos' car on a 3 cas différents de plus on aura les résultats dans deux fichiers différents ?

J'ai besoin de votre aide.

Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
DisplayConceptInfos, oui, c'est une fonction de base...
après, tout est question des parametres qu'on lui transmet et de l'ordonnancement des appels qui lui sont faits.


concernant ton test cas ==1 etc.

j'avoue ne pas comprendre ton tracas. tu as tous les cas détaillés dans mon code, dans le main.c


encore une fois, j'avoue ne pas comprendre pourquoi tu génères un fichier texte... tu pourrais exploiter directement les données extraites, depuis _concepts

Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
encore une fois, j'avoue ne pas comprendre pourquoi tu génères un fichier texte... tu pourrais exploiter directement les données extraites, depuis _concepts


Mon projet C contient des modules.
J'ai besoin dans un autre module de deux fichiers "resultat.txt" et "output.txt"

De plus, je voulais après créer une interface graphique pour visualiser les résultats.
par exemple en cliquant sur un bouton il aura un affichage de contenu de fichier "resultat.txt" dans une listebox etc..

tu as tous les cas détaillés dans mon code, dans le main.c 

Ce n'est pas presque la même chose.
Voici votre code 'main.c':
#include "extraction.h"



// 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");	

}

}



int main()

{

REF* index;

int i;



lire_fichier("Input.xml");



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

DisplayConceptInfos(_countCpt-1, 0);

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;

}


Comment vous allez modifier ce code ? de sorte que:
- le Cas 1, 2 et 3 : c'est bon mais elle affiche seulement la valeur de 'intent'

Mais, Comment vous le modifiez de sorte vous affichez dans le fichier "resultat.txt" la valeur de 'extent' suivie de la valeur de son 'intent' ?
c'est à dire vous obtenez un fichier "resultat.txt"contenant dans chaque ligne deux champs: la valeur de 'extent' et la valeur de 'intent'

- le Cas 4 : C'est bon
Mais, Comment vous le modifiez de sorte vous affichez dans le fichier "resultat.txt" la valeur de 'extent' suivie de la valeur de son 'intent' ?

c'est à dire vous obtenez un fichier "resultat.txt" contenant dans chaque ligne deux champs: la valeur de 'extent' et la valeur de 'intent'

- le Cas 5 : c'est bon.
Mais, Comment vous le modifiez de sorte vous affichez dans le fichier "resultat.txt" la valeur de 'extent' suivie de la valeur de son 'intent' ?

c'est à dire vous obtenez un fichier "output.txt" contenant dans chaque ligne un seul champ: la valeur de 'intent'


Merci.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
69
voir paramètre ShowExtent de la préocédure DisplayConceptInfos

// showExtent: indique si l'on doit ou non afficher les <Extent>



Renfield - Admin CodeS-SourceS - MVP Visual Basic
Messages postés
393
Date d'inscription
lundi 22 juin 2009
Statut
Membre
Dernière intervention
23 décembre 2011
5
Bonjour,
Pour afficher la valeur 'extent' suivie de valeur 'intent' alors je mis:

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



DisplayConceptInfos(_countCpt-1, 1);



printf("\n");




Soit le de fichier xml suivant:

<Galicia_Document>

<Lattice numberObj="4" numberAtt="2" numberCpt="1">

<Name>lattice(Ctx_0)</Name>

<Object>3</Object>

<Object>2</Object>

<Object>1</Object>

<Object>10</Object>

nom

prenom

<Concept>

 1 

<Extent>

<Object_Ref>3</Object_Ref>

<Object_Ref>2</Object_Ref>

<Object_Ref>1</Object_Ref>

<Object_Ref>10</Object_Ref>

</Extent>



nom

prenom







</Concept>

</Lattice>

</Galicia_Document>



Après la compilation et exécution j'obtiens:
Cas 1, 2 et 3 :
3 2 1 10 : nom prenom


Comment je vais sauvegarder ce résultat dans le fichier "resultat.txt" ?
de manière à obtenir le fichier "resultat.txt":
3 2 1 10 : nom prenom
Est ce que j'utilise deux variables contenant respectivement : "3 2 1 10" et "nom prénom" ?

Je voulais lire après le fichier "resultat.txt" donc je dois savoir le format de chaque ligne de ce fichier

Merci.