blob: d3f6d57d66e0788be5aac9612031c4d5c36b0aa2 [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 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000045static personPtr
46parsePerson(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
Daniel Veillardbb2da581999-06-13 14:37:07 +000047 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 */
Daniel Veillardbe803962000-06-28 23:40:59 +000061 /* COMPAT xmlChildrenNode is a macro unifying libxml1 and libxml2 names */
62 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +000063 while (cur != NULL) {
Daniel Veillardf17e09b2001-01-25 13:55:35 +000064 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Person")) &&
65 (cur->ns == ns))
Daniel Veillardbe803962000-06-28 23:40:59 +000066 ret->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
Daniel Veillardf17e09b2001-01-25 13:55:35 +000067 if ((!xmlStrcmp(cur->name, (const xmlChar *)"Email")) &&
68 (cur->ns == ns))
Daniel Veillardbe803962000-06-28 23:40:59 +000069 ret->email = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
Daniel Veillardbb2da581999-06-13 14:37:07 +000070 cur = cur->next;
71 }
72
73 return(ret);
74}
75
76/*
77 * and to print it
78 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +000079static void
80printPerson(personPtr cur) {
Daniel Veillardbb2da581999-06-13 14:37:07 +000081 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 {
Daniel Veillardf17e09b2001-01-25 13:55:35 +000097 xmlChar *projectID;
98 xmlChar *application;
99 xmlChar *category;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000100 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 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000108static jobPtr
109parseJob(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000110 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 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000124 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000125 while (cur != NULL) {
126
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000127 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Project")) &&
128 (cur->ns == ns)) {
129 ret->projectID = xmlGetProp(cur, (const xmlChar *) "ID");
Daniel Veillardbb2da581999-06-13 14:37:07 +0000130 if (ret->projectID == NULL) {
131 fprintf(stderr, "Project has no ID\n");
132 }
133 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000134 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))
Daniel Veillardbb2da581999-06-13 14:37:07 +0000144 ret->contact = parsePerson(doc, ns, cur);
145 cur = cur->next;
146 }
147
148 return(ret);
149}
150
151/*
152 * and to print it
153 */
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000154static void
155printJob(jobPtr cur) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000156 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
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000179static gJobPtr
180parseGjobFile(char *filename) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000181 xmlDocPtr doc;
182 gJobPtr ret;
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000183 jobPtr curjob;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000184 xmlNsPtr ns;
185 xmlNodePtr cur;
186
Daniel Veillard81273902003-09-30 00:43:48 +0000187#ifdef LIBXML_SAX1_ENABLED
Daniel Veillardbb2da581999-06-13 14:37:07 +0000188 /*
189 * build an XML tree from a the file;
190 */
191 doc = xmlParseFile(filename);
192 if (doc == NULL) return(NULL);
Daniel Veillard81273902003-09-30 00:43:48 +0000193#else
194 /*
195 * the library has been compiled without some of the old interfaces
196 */
197 return(NULL);
198#endif /* LIBXML_SAX1_ENABLED */
Daniel Veillardbb2da581999-06-13 14:37:07 +0000199
200 /*
201 * Check the document is of the right kind
202 */
Daniel Veillardf3029822000-05-06 08:11:19 +0000203
Daniel Veillardf3029822000-05-06 08:11:19 +0000204 cur = xmlDocGetRootElement(doc);
Daniel Veillardbb2da581999-06-13 14:37:07 +0000205 if (cur == NULL) {
206 fprintf(stderr,"empty document\n");
207 xmlFreeDoc(doc);
208 return(NULL);
209 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000210 ns = xmlSearchNsByHref(doc, cur,
211 (const xmlChar *) "http://www.gnome.org/some-location");
Daniel Veillardbb2da581999-06-13 14:37:07 +0000212 if (ns == NULL) {
213 fprintf(stderr,
214 "document of the wrong type, GJob Namespace not found\n");
215 xmlFreeDoc(doc);
216 return(NULL);
217 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000218 if (xmlStrcmp(cur->name, (const xmlChar *) "Helping")) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000219 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 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000239 cur = cur->xmlChildrenNode;
Daniel Veillard2728f842006-03-09 16:49:24 +0000240 while ( cur && xmlIsBlankNode ( cur ) ) {
Daniel Veillardf3029822000-05-06 08:11:19 +0000241 cur = cur -> next;
Daniel Veillard2728f842006-03-09 16:49:24 +0000242 }
243 if ( cur == 0 ) {
244 xmlFreeDoc(doc);
245 free(ret);
246 return ( NULL );
247 }
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000248 if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) {
Daniel Veillardf3029822000-05-06 08:11:19 +0000249 fprintf(stderr,"document of the wrong type, was '%s', Jobs expected",
250 cur->name);
251 fprintf(stderr,"xmlDocDump follows\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000252#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardf3029822000-05-06 08:11:19 +0000253 xmlDocDump ( stderr, doc );
254 fprintf(stderr,"xmlDocDump finished\n");
Daniel Veillarda9cce9c2003-09-29 13:20:24 +0000255#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillardbb2da581999-06-13 14:37:07 +0000256 xmlFreeDoc(doc);
257 free(ret);
258 return(NULL);
259 }
260
261 /* Second level is a list of Job, but be laxist */
Daniel Veillardbe803962000-06-28 23:40:59 +0000262 cur = cur->xmlChildrenNode;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000263 while (cur != NULL) {
Daniel Veillardf17e09b2001-01-25 13:55:35 +0000264 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) &&
265 (cur->ns == ns)) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000266 curjob = parseJob(doc, ns, cur);
267 if (curjob != NULL)
268 ret->jobs[ret->nbJobs++] = curjob;
Daniel Veillardbb2da581999-06-13 14:37:07 +0000269 if (ret->nbJobs >= 500) break;
270 }
271 cur = cur->next;
272 }
273
274 return(ret);
275}
276
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000277static void
278handleGjob(gJobPtr cur) {
Daniel Veillardbb2da581999-06-13 14:37:07 +0000279 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
Daniel Veillardbe803962000-06-28 23:40:59 +0000292 /* COMPAT: Do not genrate nodes for formatting spaces */
Daniel Veillardc2304102000-06-29 00:43:27 +0000293 LIBXML_TEST_VERSION
Daniel Veillardbe803962000-06-28 23:40:59 +0000294 xmlKeepBlanksDefault(0);
295
Daniel Veillardbb2da581999-06-13 14:37:07 +0000296 for (i = 1; i < argc ; i++) {
297 cur = parseGjobFile(argv[i]);
Daniel Veillardf3029822000-05-06 08:11:19 +0000298 if ( cur )
299 handleGjob(cur);
300 else
301 fprintf( stderr, "Error parsing file '%s'\n", argv[i]);
302
Daniel Veillardbb2da581999-06-13 14:37:07 +0000303 }
Daniel Veillard5aac4e42001-08-15 20:46:57 +0000304
305 /* Clean up everything else before quitting. */
306 xmlCleanupParser();
307
Daniel Veillardbb2da581999-06-13 14:37:07 +0000308 return(0);
309}