blob: e41517397b8c00a7a38087b386f5632b0e4152dc [file] [log] [blame]
Daniel Veillardbb2da581999-06-13 14:37:07 +00001/*
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
Daniel Veillardbe803962000-06-28 23:40:59 +000013/*
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>
Daniel Veillardf3029822000-05-06 08:11:19 +000024#include <libxml/parser.h>
Daniel Veillardbb2da581999-06-13 14:37:07 +000025
26#define DEBUG(x) printf(x)
27
28/*
29 * A person record
Daniel Veillardf17e09b2001-01-25 13:55:35 +000030 * an xmlChar * is really an UTF8 encoded char string (0 terminated)
Daniel Veillardbb2da581999-06-13 14:37:07 +000031 */
32typedef struct person {
Daniel Veillardf17e09b2001-01-25 13:55:35 +000033 xmlChar *name;
34 xmlChar *email;
35 xmlChar *company;
36 xmlChar *organisation;
37 xmlChar *smail;
38 xmlChar *webPage;
39 xmlChar *phone;
Daniel Veillardbb2da581999-06-13 14:37:07 +000040} person, *personPtr;
41
42/*
43 * And the code needed to parse it
44 */
45personPtr parsePerson(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
46 personPtr ret = NULL;
47
48DEBUG("parsePerson\n");
49 /*
50 * allocate the struct
51 */
52 ret = (personPtr) malloc(sizeof(person));
53 if (ret == NULL) {
54 fprintf(stderr,"out of memory\n");
55 return(NULL);
56 }
57 memset(ret, 0, sizeof(person));
58
59 /* We don't care what the top level element name is */
Daniel Veillardbe803962000-06-28 23:40:59 +000060 /* COMPAT xmlChildrenNode is a macro unifying libxml1 and libxml2 names */
61 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +000062 while (cur != NULL) {
Daniel Veillardf17e09b2001-01-25 13:55:35 +000063 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Person")) &&
64 (cur->ns == ns))
Daniel Veillardbe803962000-06-28 23:40:59 +000065 ret->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
Daniel Veillardf17e09b2001-01-25 13:55:35 +000066 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Email")) &&
67 (cur->ns == ns))
Daniel Veillardbe803962000-06-28 23:40:59 +000068 ret->email = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
Daniel Veillardbb2da581999-06-13 14:37:07 +000069 cur = cur->next;
70 }
71
72 return(ret);
73}
74
75/*
76 * and to print it
77 */
78void printPerson(personPtr cur) {
79 if (cur == NULL) return;
80 printf("------ Person\n");
81 if (cur->name) printf(" name: %s\n", cur->name);
82 if (cur->email) printf(" email: %s\n", cur->email);
83 if (cur->company) printf(" company: %s\n", cur->company);
84 if (cur->organisation) printf(" organisation: %s\n", cur->organisation);
85 if (cur->smail) printf(" smail: %s\n", cur->smail);
86 if (cur->webPage) printf(" Web: %s\n", cur->webPage);
87 if (cur->phone) printf(" phone: %s\n", cur->phone);
88 printf("------\n");
89}
90
91/*
92 * a Description for a Job
93 */
94typedef struct job {
Daniel Veillardf17e09b2001-01-25 13:55:35 +000095 xmlChar *projectID;
96 xmlChar *application;
97 xmlChar *category;
Daniel Veillardbb2da581999-06-13 14:37:07 +000098 personPtr contact;
99 int nbDevelopers;
100 personPtr developers[100]; /* using dynamic alloc is left as an exercise */
101} job, *jobPtr;
102
103/*
104 * And the code needed to parse it
105 */
106jobPtr parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
107 jobPtr ret = NULL;
108
109DEBUG("parseJob\n");
110 /*
111 * allocate the struct
112 */
113 ret = (jobPtr) malloc(sizeof(job));
114 if (ret == NULL) {
115 fprintf(stderr,"out of memory\n");
116 return(NULL);
117 }
118 memset(ret, 0, sizeof(job));
119
120 /* We don't care what the top level element name is */
Daniel Veillardbe803962000-06-28 23:40:59 +0000121 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000122 while (cur != NULL) {
123
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000124 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Project")) &&
125 (cur->ns == ns)) {
126 ret->projectID = xmlGetProp(cur, (const xmlChar *) "ID");
Daniel Veillardbb2da581999-06-13 14:37:07 +0000127 if (ret->projectID == NULL) {
128 fprintf(stderr, "Project has no ID\n");
129 }
130 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000131 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Application")) &&
132 (cur->ns == ns))
133 ret->application =
134 xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
135 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Category")) &&
136 (cur->ns == ns))
137 ret->category =
138 xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
139 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Contact")) &&
140 (cur->ns == ns))
Daniel Veillardbb2da581999-06-13 14:37:07 +0000141 ret->contact = parsePerson(doc, ns, cur);
142 cur = cur->next;
143 }
144
145 return(ret);
146}
147
148/*
149 * and to print it
150 */
151void printJob(jobPtr cur) {
152 int i;
153
154 if (cur == NULL) return;
155 printf("======= Job\n");
156 if (cur->projectID != NULL) printf("projectID: %s\n", cur->projectID);
157 if (cur->application != NULL) printf("application: %s\n", cur->application);
158 if (cur->category != NULL) printf("category: %s\n", cur->category);
159 if (cur->contact != NULL) printPerson(cur->contact);
160 printf("%d developers\n", cur->nbDevelopers);
161
162 for (i = 0;i < cur->nbDevelopers;i++) printPerson(cur->developers[i]);
163 printf("======= \n");
164}
165
166/*
167 * A pool of Gnome Jobs
168 */
169typedef struct gjob {
170 int nbJobs;
171 jobPtr jobs[500]; /* using dynamic alloc is left as an exercise */
172} gJob, *gJobPtr;
173
174
175gJobPtr parseGjobFile(char *filename) {
176 xmlDocPtr doc;
177 gJobPtr ret;
178 jobPtr job;
179 xmlNsPtr ns;
180 xmlNodePtr cur;
181
182 /*
183 * build an XML tree from a the file;
184 */
185 doc = xmlParseFile(filename);
186 if (doc == NULL) return(NULL);
187
188 /*
189 * Check the document is of the right kind
190 */
Daniel Veillardf3029822000-05-06 08:11:19 +0000191
Daniel Veillardf3029822000-05-06 08:11:19 +0000192 cur = xmlDocGetRootElement(doc);
Daniel Veillardbb2da581999-06-13 14:37:07 +0000193 if (cur == NULL) {
194 fprintf(stderr,"empty document\n");
195 xmlFreeDoc(doc);
196 return(NULL);
197 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000198 ns = xmlSearchNsByHref(doc, cur,
199 (const xmlChar *) "http://www.gnome.org/some-location");
Daniel Veillardbb2da581999-06-13 14:37:07 +0000200 if (ns == NULL) {
201 fprintf(stderr,
202 "document of the wrong type, GJob Namespace not found\n");
203 xmlFreeDoc(doc);
204 return(NULL);
205 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000206 if (xmlStrcmp(cur->name, (const xmlChar *) "Helping")) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000207 fprintf(stderr,"document of the wrong type, root node != Helping");
208 xmlFreeDoc(doc);
209 return(NULL);
210 }
211
212 /*
213 * Allocate the structure to be returned.
214 */
215 ret = (gJobPtr) malloc(sizeof(gJob));
216 if (ret == NULL) {
217 fprintf(stderr,"out of memory\n");
218 xmlFreeDoc(doc);
219 return(NULL);
220 }
221 memset(ret, 0, sizeof(gJob));
222
223 /*
224 * Now, walk the tree.
225 */
226 /* First level we expect just Jobs */
Daniel Veillardbe803962000-06-28 23:40:59 +0000227 cur = cur->xmlChildrenNode;
Daniel Veillardf3029822000-05-06 08:11:19 +0000228 while ( cur && xmlIsBlankNode ( cur ) )
229 {
230 cur = cur -> next;
231 }
232 if ( cur == 0 )
233 return ( NULL );
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000234 if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) {
Daniel Veillardf3029822000-05-06 08:11:19 +0000235 fprintf(stderr,"document of the wrong type, was '%s', Jobs expected",
236 cur->name);
237 fprintf(stderr,"xmlDocDump follows\n");
238 xmlDocDump ( stderr, doc );
239 fprintf(stderr,"xmlDocDump finished\n");
Daniel Veillardbb2da581999-06-13 14:37:07 +0000240 xmlFreeDoc(doc);
241 free(ret);
242 return(NULL);
243 }
244
245 /* Second level is a list of Job, but be laxist */
Daniel Veillardbe803962000-06-28 23:40:59 +0000246 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000247 while (cur != NULL) {
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000248 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) &&
249 (cur->ns == ns)) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000250 job = parseJob(doc, ns, cur);
251 if (job != NULL)
252 ret->jobs[ret->nbJobs++] = job;
253 if (ret->nbJobs >= 500) break;
254 }
255 cur = cur->next;
256 }
257
258 return(ret);
259}
260
261void handleGjob(gJobPtr cur) {
262 int i;
263
264 /*
265 * Do whatever you want and free the structure.
266 */
267 printf("%d Jobs registered\n", cur->nbJobs);
268 for (i = 0; i < cur->nbJobs; i++) printJob(cur->jobs[i]);
269}
270
271int main(int argc, char **argv) {
272 int i;
273 gJobPtr cur;
274
Daniel Veillardbe803962000-06-28 23:40:59 +0000275 /* COMPAT: Do not genrate nodes for formatting spaces */
Daniel Veillardc2304102000-06-29 00:43:27 +0000276 LIBXML_TEST_VERSION
Daniel Veillardbe803962000-06-28 23:40:59 +0000277 xmlKeepBlanksDefault(0);
278
Daniel Veillardbb2da581999-06-13 14:37:07 +0000279 for (i = 1; i < argc ; i++) {
280 cur = parseGjobFile(argv[i]);
Daniel Veillardf3029822000-05-06 08:11:19 +0000281 if ( cur )
282 handleGjob(cur);
283 else
284 fprintf( stderr, "Error parsing file '%s'\n", argv[i]);
285
Daniel Veillardbb2da581999-06-13 14:37:07 +0000286 }
287 return(0);
288}