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 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 277static void 278handleGjob(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 288int 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