OLD | NEW |
(Empty) | |
| 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 */ |
| 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) { |
| 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 } |
OLD | NEW |