IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XSL/XSLT/XPATH XML Discussion :

Erreur de segmentation sur une requête programmée en C avec libxml2 [XPATH 1.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2015
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Erreur de segmentation sur une requête programmée en C avec libxml2
    Bonjour, je suis débutant en XML (j'ai commencé avant-hier ), j'ai fait des recherches et j'ai trouvé quelques tutos et la bibliothèques libxml2.
    Je code sur Linux un petit programme (plus précisement sur Raspbian mais passons).

    J'ai donc un fichier actionToMidi.xml écrit à partir d'un petit programme fait par mes soins.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <action mouvement="jump">60</action>
      <action mouvement="corps a corps">61</action>
      <action mouvement="roulade">62</action>
      <action mouvement="monter/descendre d'un vehicule">63</action>
      <action mouvement="menu pause">64</action>
      <action mouvement="map">65</action>
      <action mouvement="PS menu">66</action>
      <action mouvement="shoot">67</action>
      <action mouvement="viser">68</action>
      <action mouvement="reload">69</action>
      <action mouvement="grenade">70</action>
      <action mouvement="second">71</action>
      <action mouvement="sprint">72</action>
      <action mouvement="phone">73</action>
      <action mouvement="vision nocturne">74</action>
      <action mouvement="take a photo">75</action>
      <action mouvement="swim">76</action>
      <action mouvement="camera">77</action>
      <action mouvement="move">78</action>
    </root>
    Voici le code de mon programme (just un petit init, le main et la fonction qui fait la requête) que je compile avec la commande:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc rechercheNote.c -lxml2 -I/usr/include/libxml2 -o test
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <libxml/parser.h>
    #include <libxml/xpath.h>
     
     
    xmlXPathContextPtr ctxt_actionToMidi = NULL;
    xmlDocPtr doc_actionToMidi = NULL;
     
    //Initialisation pour la lecture des fichiers XML
    void init_XMLRead(){
    	// Création de l'arbre DOM à partir des fichiers XML
     
    	doc_actionToMidi = xmlParseFile("actionToMidi.xml");
       if (doc_actionToMidi == NULL) {
            fprintf(stderr, "Document XML invalide\n");
            exit(EXIT_FAILURE);
        }
     
    	// Récupération de la racine
    	xmlNodePtr racine = xmlDocGetRootElement(doc_actionToMidi);
        if (racine == NULL) {
            fprintf(stderr, "Document XML vierge\n");
            xmlFreeDoc(doc_actionToMidi);
            exit(EXIT_FAILURE);
        }
     
    	xmlXPathInit();
    	ctxt_actionToMidi = xmlXPathNewContext(doc_actionToMidi);
    	if (ctxt_actionToMidi == NULL) {
    		fprintf(stderr, "Erreur lors de la création du contexte XPath\n");
    		exit(EXIT_FAILURE);
    	}
    }
     
    char* rechercheNote(char* bouton){
    	char *requete = malloc(200*sizeof(char));
     
    	strcpy(requete,"/root/action[@=\"");
    	strcat(requete,bouton);
    	strcat(requete,"\"]");
    	xmlXPathObjectPtr xpathRes_midi = xmlXPathEvalExpression(BAD_CAST requete, ctxt_actionToMidi);
    	if (xpathRes_midi == NULL) {
      	 fprintf(stderr, "Erreur sur l'expression XPath\n");
      	 exit(-1);
    	}
    	printf("Pre-Manipulation du résultat\n");
    	// Manipulation du résultat
    	if (xpathRes_midi->type == XPATH_NODESET) {
    			printf("Pre nodeTab[0]\n");
    			xmlNodePtr n = xpathRes_midi->nodesetval->nodeTab[0];
    			printf("Pre return xmlNodeGetContent(n)\n");
    			return xmlNodeGetContent(n);
    	}
    	return "";
    }
     
    int main ()
    {	
    	char* buffernote=NULL;
     
    	init_XMLRead();
     
    	printf("Avant recherche note\n");
    	buffernote=rechercheNote("map");
    	printf("Après recherche note\n");
    	printf("buffernot: %s\n",buffernote);
     
    	return 0;
    }
    Ca fonctionne bien, si on recherche map, on reçoit bien 65 .

    Par contre, ma question et mon problème sont:
    Si je modifie le mot root par racine, cube ou je ne sais quoi dans le fichier .xml, mon programme plante et j'ai une erreur de segmentation.
    Le programme plante dans la fonction char* rechercheNote(char* bouton) à la ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    xmlNodePtr n = xpathRes_midi->nodesetval->nodeTab[0];
    Et j'ai pas trouvé le moyen de blinder, je ne sais pas comment protéger mon pauvre petit programme...

    Donc j'en appel à votre connaissance, merci

  2. #2
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Si le nom de la racine d'arborescent des éléments se prend la liberté de rester indéterminé, on peut s'y servir avec la notion *, qui veut dire un noeud du type d'élément tout court; et /* effectivement représente l'élément comme enfant direct de la 'racine' (abstracte, faut de mieux et par abus un peu du langage, et de ne pas confondu avec le concret root en place là) du document, donc, forcément unique, c'est-à-dire, soit nommé root là, soit nommé par quelque nom comme on entend à y placer.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //strcpy(requete,"/root/action[@=\"");   //@mouvement, n'est-ce pas?
    strcpy(requete,"/*/action[@mouvement=\"");

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2015
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci d'avoir pris le temps de lire et de répondre.
    Je vais repréciser ma question, je ne me suis pas exprimé assez clairement. Je veux parer mon programme à toute éventualité (à un maximum en tout cas).

    Je voudrais me mettre dans le cas où un utilisateur externe viendrait modifier le ficher .xml en insérant/modifiant des valeurs.

    Par exemple, si je modifie la ligne du fichier xml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <action mouvement="jump">60</action>
    par: (je supprime le contenu de jump, contenu que je cherche à retourner)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <action mouvement="jump"></action>
    ou par (je supprime le mouvement jump, alors que je cherche le contenu d'un mouvement jump)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <action mouvement="sauter">60</action>
    J'ai le droit à une erreur de segmentation.
    Ce que j'aimerais, c'est pouvoir au niveau de la requête retourner un élément (char*) NULL ou " ". Pour pouvoir traiter ce résultat par la suite, au lieu d'avoir une recherche qui plante bêtement

    La fonction recherche est celle-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    char* rechercheNote(char* bouton){
    	char *requete = malloc(200*sizeof(char));
     
    	strcpy(requete,"/root/action[@=\"");
    	strcat(requete,bouton);
    	strcat(requete,"\"]");
    	xmlXPathObjectPtr xpathRes_midi = xmlXPathEvalExpression(BAD_CAST requete, ctxt_actionToMidi);
    	if (xpathRes_midi == NULL) {
      	 fprintf(stderr, "Erreur sur l'expression XPath\n");
      	 exit(-1);
    	}
    	printf("Pre-Manipulation du résultat\n");
    	// Manipulation du résultat
    	if (xpathRes_midi->type == XPATH_NODESET) {
    			printf("Pre nodeTab[0]\n");
    			xmlNodePtr n = xpathRes_midi->nodesetval->nodeTab[0];
    			printf("Pre return xmlNodeGetContent(n)\n");
    			return xmlNodeGetContent(n);
    	}
    	return "";
    }

  4. #4
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    A vrai dire, pas encore trop saissir les problèmes ce que vous entendez à résoudre; mais bien entendu il y en a pleine à désirer.
    [1] Si vous voulez laisser les clients tout liberté à la recherche des valeurs avec un xpath comme ils entendent à faire, vous passez le xpath entier à la fonction rechercheNote (ou rechercheNode ?) au lieu de ne passer que la valeur d'attribut mouvement ...
    [2] Si vous entendez dire que la fonction elle-même soit défective et qu'elle n'ait pas suffisamment capturé toutes erreurs possibles, je dirais ceci : le résultat d'évaluation d'expression xpath n'est pas toujours null même si elle ne trouve aucun noeud, il faut contrôller sa taille aussi pour s'en servir.

    edition : J'ai l'occasion de regarder de plus près les types d'objets et leur membres et je me corrige les imprécisions et rajoute les expansions nécessaires de contrôles. Voici la révision du bloc correspondant. Et bien entendu, on peut consolider un peu les retournes et les valeurs retournées comme on voit plus souhaîtable ou plus simple.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    if (xpathRes_midi->type == XPATH_NODESET) {
        if(xmlXPathNodeSetIsEmpty(xpathRes_midi->nodesetval)){
            xmlXPathFreeObject(xpathRes_midi);
            printf("Pre return Empty\n");
            return "";
        } else if (xpathRes_midi->nodesetval->nodeNr == 0) {
            xmlXPathFreeObject(xpathRes_midi);
            printf("Pre return None\n");
            return 0;
        } else {
            printf("Pre nodeTab[0]\n");
            xmlNodePtr n = xpathRes_midi->nodesetval->nodeTab[0];
            printf("Pre return xmlNodeGetContent(n)\n");
            return xmlNodeGetContent(n);
        }
    }
    Voilà !

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2015
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Bonjour, je n'ai pas répondu plus tôt car je voulais tester et travailler un peu le code avant de dire quoi que ce soit.

    C'est donc le cas n°2 que je voulais résoudre et grâce à vous, j'ai enfin réussi.

    Merci beaucoup ! D'autant plus que vous n'êtes pas francophone (en tout cas ce n'est pas votre langue maternelle), c'est donc un travail remarquable que vous faîtes.

    Merci pour tout et bonne continuation !!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Erreur de syntaxe sur une requête
    Par nO_life dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 06/03/2009, 12h34
  2. Erreur de syntaxe sur une requête d'insertion
    Par Moustic74 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 19/12/2008, 17h34
  3. Erreur de segmentation sur une File
    Par hugo1992 dans le forum C
    Réponses: 2
    Dernier message: 22/10/2007, 08h49
  4. Erreur de syntaxe sur une requête paramétrée
    Par deglingo37 dans le forum Access
    Réponses: 5
    Dernier message: 16/05/2006, 22h21
  5. Erreur de segmentation sur une chaine en récursif...
    Par laurent_ifips dans le forum C
    Réponses: 12
    Dernier message: 13/12/2005, 16h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo