gjobread.c revision a9cce9cd0d7aff3ec318b5d8d376da131b6aaad4
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@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 */ 32typedef 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 */ 45static personPtr 46parsePerson(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { 47 personPtr ret = NULL; 48 49DEBUG("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 */ 79static void 80printPerson(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 */ 96typedef 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 */ 108static jobPtr 109parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) { 110 jobPtr ret = NULL; 111 112DEBUG("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 */ 154static void 155printJob(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 */ 173typedef struct gjob { 174 int nbJobs; 175 jobPtr jobs[500]; /* using dynamic alloc is left as an exercise */ 176} gJob, *gJobPtr; 177 178 179static gJobPtr 180parseGjobFile(char *filename) { 181 xmlDocPtr doc; 182 gJobPtr ret; 183 jobPtr curjob; 184 xmlNsPtr ns; 185 xmlNodePtr cur; 186 187 /* 188 * build an XML tree from a the file; 189 */ 190 doc = xmlParseFile(filename); 191 if (doc == NULL) return(NULL); 192 193 /* 194 * Check the document is of the right kind 195 */ 196 197 cur = xmlDocGetRootElement(doc); 198 if (cur == NULL) { 199 fprintf(stderr,"empty document\n"); 200 xmlFreeDoc(doc); 201 return(NULL); 202 } 203 ns = xmlSearchNsByHref(doc, cur, 204 (const xmlChar *) "http://www.gnome.org/some-location"); 205 if (ns == NULL) { 206 fprintf(stderr, 207 "document of the wrong type, GJob Namespace not found\n"); 208 xmlFreeDoc(doc); 209 return(NULL); 210 } 211 if (xmlStrcmp(cur->name, (const xmlChar *) "Helping")) { 212 fprintf(stderr,"document of the wrong type, root node != Helping"); 213 xmlFreeDoc(doc); 214 return(NULL); 215 } 216 217 /* 218 * Allocate the structure to be returned. 219 */ 220 ret = (gJobPtr) malloc(sizeof(gJob)); 221 if (ret == NULL) { 222 fprintf(stderr,"out of memory\n"); 223 xmlFreeDoc(doc); 224 return(NULL); 225 } 226 memset(ret, 0, sizeof(gJob)); 227 228 /* 229 * Now, walk the tree. 230 */ 231 /* First level we expect just Jobs */ 232 cur = cur->xmlChildrenNode; 233 while ( cur && xmlIsBlankNode ( cur ) ) 234 { 235 cur = cur -> next; 236 } 237 if ( cur == 0 ) 238 return ( NULL ); 239 if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) { 240 fprintf(stderr,"document of the wrong type, was '%s', Jobs expected", 241 cur->name); 242 fprintf(stderr,"xmlDocDump follows\n"); 243#ifdef LIBXML_OUTPUT_ENABLED 244 xmlDocDump ( stderr, doc ); 245 fprintf(stderr,"xmlDocDump finished\n"); 246#endif /* LIBXML_OUTPUT_ENABLED */ 247 xmlFreeDoc(doc); 248 free(ret); 249 return(NULL); 250 } 251 252 /* Second level is a list of Job, but be laxist */ 253 cur = cur->xmlChildrenNode; 254 while (cur != NULL) { 255 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) && 256 (cur->ns == ns)) { 257 curjob = parseJob(doc, ns, cur); 258 if (curjob != NULL) 259 ret->jobs[ret->nbJobs++] = curjob; 260 if (ret->nbJobs >= 500) break; 261 } 262 cur = cur->next; 263 } 264 265 return(ret); 266} 267 268static void 269handleGjob(gJobPtr cur) { 270 int i; 271 272 /* 273 * Do whatever you want and free the structure. 274 */ 275 printf("%d Jobs registered\n", cur->nbJobs); 276 for (i = 0; i < cur->nbJobs; i++) printJob(cur->jobs[i]); 277} 278 279int main(int argc, char **argv) { 280 int i; 281 gJobPtr cur; 282 283 /* COMPAT: Do not genrate nodes for formatting spaces */ 284 LIBXML_TEST_VERSION 285 xmlKeepBlanksDefault(0); 286 287 for (i = 1; i < argc ; i++) { 288 cur = parseGjobFile(argv[i]); 289 if ( cur ) 290 handleGjob(cur); 291 else 292 fprintf( stderr, "Error parsing file '%s'\n", argv[i]); 293 294 } 295 296 /* Clean up everything else before quitting. */ 297 xmlCleanupParser(); 298 299 return(0); 300} 301