Home | History | Annotate | Download | only in example
      1 /*
      2  * gjobread.c : a small test program for gnome jobs XML format
      3  *
      4  * See Copyright for the status of this software.
      5  *
      6  * Daniel.Veillard (at) w3.org
      7  */
      8 
      9 #include <stdio.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 
     13 /*
     14  * This example should compile and run indifferently with libxml-1.8.8 +
     15  * and libxml2-2.1.0 +
     16  * Check the COMPAT comments below
     17  */
     18 
     19 /*
     20  * COMPAT using xml-config --cflags to get the include path this will
     21  * work with both
     22  */
     23 #include <libxml/xmlmemory.h>
     24 #include <libxml/parser.h>
     25 
     26 #define DEBUG(x) printf(x)
     27 
     28 /*
     29  * A person record
     30  * an xmlChar * is really an UTF8 encoded char string (0 terminated)
     31  */
     32 typedef struct person {
     33     xmlChar *name;
     34     xmlChar *email;
     35     xmlChar *company;
     36     xmlChar *organisation;
     37     xmlChar *smail;
     38     xmlChar *webPage;
     39     xmlChar *phone;
     40 } person, *personPtr;
     41 
     42 /*
     43  * And the code needed to parse it
     44  */
     45 static personPtr
     46 parsePerson(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
     47     personPtr ret = NULL;
     48 
     49 DEBUG("parsePerson\n");
     50     /*
     51      * allocate the struct
     52      */
     53     ret = (personPtr) malloc(sizeof(person));
     54     if (ret == NULL) {
     55         fprintf(stderr,"out of memory\n");
     56 	return(NULL);
     57     }
     58     memset(ret, 0, sizeof(person));
     59 
     60     /* We don't care what the top level element name is */
     61     /* COMPAT xmlChildrenNode is a macro unifying libxml1 and libxml2 names */
     62     cur = cur->xmlChildrenNode;
     63     while (cur != NULL) {
     64         if ((!xmlStrcmp(cur->name, (const xmlChar *)"Person")) &&
     65 	    (cur->ns == ns))
     66 	    ret->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
     67         if ((!xmlStrcmp(cur->name, (const xmlChar *)"Email")) &&
     68 	    (cur->ns == ns))
     69 	    ret->email = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
     70 	cur = cur->next;
     71     }
     72 
     73     return(ret);
     74 }
     75 
     76 /*
     77  * and to print it
     78  */
     79 static void
     80 printPerson(personPtr cur) {
     81     if (cur == NULL) return;
     82     printf("------ Person\n");
     83     if (cur->name) printf("	name: %s\n", cur->name);
     84     if (cur->email) printf("	email: %s\n", cur->email);
     85     if (cur->company) printf("	company: %s\n", cur->company);
     86     if (cur->organisation) printf("	organisation: %s\n", cur->organisation);
     87     if (cur->smail) printf("	smail: %s\n", cur->smail);
     88     if (cur->webPage) printf("	Web: %s\n", cur->webPage);
     89     if (cur->phone) printf("	phone: %s\n", cur->phone);
     90     printf("------\n");
     91 }
     92 
     93 /*
     94  * a Description for a Job
     95  */
     96 typedef struct job {
     97     xmlChar *projectID;
     98     xmlChar *application;
     99     xmlChar *category;
    100     personPtr contact;
    101     int nbDevelopers;
    102     personPtr developers[100]; /* using dynamic alloc is left as an exercise */
    103 } job, *jobPtr;
    104 
    105 /*
    106  * And the code needed to parse it
    107  */
    108 static jobPtr
    109 parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
    110     jobPtr ret = NULL;
    111 
    112 DEBUG("parseJob\n");
    113     /*
    114      * allocate the struct
    115      */
    116     ret = (jobPtr) malloc(sizeof(job));
    117     if (ret == NULL) {
    118         fprintf(stderr,"out of memory\n");
    119 	return(NULL);
    120     }
    121     memset(ret, 0, sizeof(job));
    122 
    123     /* We don't care what the top level element name is */
    124     cur = cur->xmlChildrenNode;
    125     while (cur != NULL) {
    126 
    127         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Project")) &&
    128 	    (cur->ns == ns)) {
    129 	    ret->projectID = xmlGetProp(cur, (const xmlChar *) "ID");
    130 	    if (ret->projectID == NULL) {
    131 		fprintf(stderr, "Project has no ID\n");
    132 	    }
    133 	}
    134         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Application")) &&
    135             (cur->ns == ns))
    136 	    ret->application =
    137 		xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
    138         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Category")) &&
    139 	    (cur->ns == ns))
    140 	    ret->category =
    141 		xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
    142         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Contact")) &&
    143 	    (cur->ns == ns))
    144 	    ret->contact = parsePerson(doc, ns, cur);
    145 	cur = cur->next;
    146     }
    147 
    148     return(ret);
    149 }
    150 
    151 /*
    152  * and to print it
    153  */
    154 static void
    155 printJob(jobPtr cur) {
    156     int i;
    157 
    158     if (cur == NULL) return;
    159     printf("=======  Job\n");
    160     if (cur->projectID != NULL) printf("projectID: %s\n", cur->projectID);
    161     if (cur->application != NULL) printf("application: %s\n", cur->application);
    162     if (cur->category != NULL) printf("category: %s\n", cur->category);
    163     if (cur->contact != NULL) printPerson(cur->contact);
    164     printf("%d developers\n", cur->nbDevelopers);
    165 
    166     for (i = 0;i < cur->nbDevelopers;i++) printPerson(cur->developers[i]);
    167     printf("======= \n");
    168 }
    169 
    170 /*
    171  * A pool of Gnome Jobs
    172  */
    173 typedef struct gjob {
    174     int nbJobs;
    175     jobPtr jobs[500]; /* using dynamic alloc is left as an exercise */
    176 } gJob, *gJobPtr;
    177 
    178 
    179 static gJobPtr
    180 parseGjobFile(char *filename ATTRIBUTE_UNUSED) {
    181     xmlDocPtr doc;
    182     gJobPtr ret;
    183     jobPtr curjob;
    184     xmlNsPtr ns;
    185     xmlNodePtr cur;
    186 
    187 #ifdef LIBXML_SAX1_ENABLED
    188     /*
    189      * build an XML tree from a the file;
    190      */
    191     doc = xmlParseFile(filename);
    192     if (doc == NULL) return(NULL);
    193 #else
    194     /*
    195      * the library has been compiled without some of the old interfaces
    196      */
    197     return(NULL);
    198 #endif /* LIBXML_SAX1_ENABLED */
    199 
    200     /*
    201      * Check the document is of the right kind
    202      */
    203 
    204     cur = xmlDocGetRootElement(doc);
    205     if (cur == NULL) {
    206         fprintf(stderr,"empty document\n");
    207 	xmlFreeDoc(doc);
    208 	return(NULL);
    209     }
    210     ns = xmlSearchNsByHref(doc, cur,
    211 	    (const xmlChar *) "http://www.gnome.org/some-location");
    212     if (ns == NULL) {
    213         fprintf(stderr,
    214 	        "document of the wrong type, GJob Namespace not found\n");
    215 	xmlFreeDoc(doc);
    216 	return(NULL);
    217     }
    218     if (xmlStrcmp(cur->name, (const xmlChar *) "Helping")) {
    219         fprintf(stderr,"document of the wrong type, root node != Helping");
    220 	xmlFreeDoc(doc);
    221 	return(NULL);
    222     }
    223 
    224     /*
    225      * Allocate the structure to be returned.
    226      */
    227     ret = (gJobPtr) malloc(sizeof(gJob));
    228     if (ret == NULL) {
    229         fprintf(stderr,"out of memory\n");
    230 	xmlFreeDoc(doc);
    231 	return(NULL);
    232     }
    233     memset(ret, 0, sizeof(gJob));
    234 
    235     /*
    236      * Now, walk the tree.
    237      */
    238     /* First level we expect just Jobs */
    239     cur = cur->xmlChildrenNode;
    240     while ( cur && xmlIsBlankNode ( cur ) ) {
    241 	cur = cur -> next;
    242     }
    243     if ( cur == 0 ) {
    244 	xmlFreeDoc(doc);
    245 	free(ret);
    246 	return ( NULL );
    247     }
    248     if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) {
    249         fprintf(stderr,"document of the wrong type, was '%s', Jobs expected",
    250 		cur->name);
    251 	fprintf(stderr,"xmlDocDump follows\n");
    252 #ifdef LIBXML_OUTPUT_ENABLED
    253 	xmlDocDump ( stderr, doc );
    254 	fprintf(stderr,"xmlDocDump finished\n");
    255 #endif /* LIBXML_OUTPUT_ENABLED */
    256 	xmlFreeDoc(doc);
    257 	free(ret);
    258 	return(NULL);
    259     }
    260 
    261     /* Second level is a list of Job, but be laxist */
    262     cur = cur->xmlChildrenNode;
    263     while (cur != NULL) {
    264         if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) &&
    265 	    (cur->ns == ns)) {
    266 	    curjob = parseJob(doc, ns, cur);
    267 	    if (curjob != NULL)
    268 	        ret->jobs[ret->nbJobs++] = curjob;
    269             if (ret->nbJobs >= 500) break;
    270 	}
    271 	cur = cur->next;
    272     }
    273 
    274     return(ret);
    275 }
    276 
    277 static void
    278 handleGjob(gJobPtr cur) {
    279     int i;
    280 
    281     /*
    282      * Do whatever you want and free the structure.
    283      */
    284     printf("%d Jobs registered\n", cur->nbJobs);
    285     for (i = 0; i < cur->nbJobs; i++) printJob(cur->jobs[i]);
    286 }
    287 
    288 int main(int argc, char **argv) {
    289     int i;
    290     gJobPtr cur;
    291 
    292     /* COMPAT: Do not genrate nodes for formatting spaces */
    293     LIBXML_TEST_VERSION
    294     xmlKeepBlanksDefault(0);
    295 
    296     for (i = 1; i < argc ; i++) {
    297 	cur = parseGjobFile(argv[i]);
    298 	if ( cur )
    299 	  handleGjob(cur);
    300 	else
    301 	  fprintf( stderr, "Error parsing file '%s'\n", argv[i]);
    302 
    303     }
    304 
    305     /* Clean up everything else before quitting. */
    306     xmlCleanupParser();
    307 
    308     return(0);
    309 }
    310