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 * [email protected]
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
parsePerson(xmlDocPtr doc,xmlNsPtr ns,xmlNodePtr cur)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
printPerson(personPtr cur)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
parseJob(xmlDocPtr doc,xmlNsPtr ns,xmlNodePtr cur)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
printJob(jobPtr cur)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
parseGjobFile(char * filename)180 parseGjobFile(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 = xmlReadFile(filename, NULL, XML_PARSE_NOBLANKS);
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 cur = cur -> next;
235 }
236 if ( cur == 0 ) {
237 xmlFreeDoc(doc);
238 free(ret);
239 return ( NULL );
240 }
241 if ((xmlStrcmp(cur->name, (const xmlChar *) "Jobs")) || (cur->ns != ns)) {
242 fprintf(stderr,"document of the wrong type, was '%s', Jobs expected",
243 cur->name);
244 fprintf(stderr,"xmlDocDump follows\n");
245 #ifdef LIBXML_OUTPUT_ENABLED
246 xmlDocDump ( stderr, doc );
247 fprintf(stderr,"xmlDocDump finished\n");
248 #endif /* LIBXML_OUTPUT_ENABLED */
249 xmlFreeDoc(doc);
250 free(ret);
251 return(NULL);
252 }
253
254 /* Second level is a list of Job, but be laxist */
255 cur = cur->xmlChildrenNode;
256 while (cur != NULL) {
257 if ((!xmlStrcmp(cur->name, (const xmlChar *) "Job")) &&
258 (cur->ns == ns)) {
259 curjob = parseJob(doc, ns, cur);
260 if (curjob != NULL)
261 ret->jobs[ret->nbJobs++] = curjob;
262 if (ret->nbJobs >= 500) break;
263 }
264 cur = cur->next;
265 }
266
267 return(ret);
268 }
269
270 static void
handleGjob(gJobPtr cur)271 handleGjob(gJobPtr cur) {
272 int i;
273
274 /*
275 * Do whatever you want and free the structure.
276 */
277 printf("%d Jobs registered\n", cur->nbJobs);
278 for (i = 0; i < cur->nbJobs; i++) printJob(cur->jobs[i]);
279 }
280
main(int argc,char ** argv)281 int main(int argc, char **argv) {
282 int i;
283 gJobPtr cur;
284
285 /* COMPAT: Do not generate nodes for formatting spaces */
286 LIBXML_TEST_VERSION
287
288 for (i = 1; i < argc ; i++) {
289 cur = parseGjobFile(argv[i]);
290 if ( cur )
291 handleGjob(cur);
292 else
293 fprintf( stderr, "Error parsing file '%s'\n", argv[i]);
294
295 }
296
297 /* Clean up everything else before quitting. */
298 xmlCleanupParser();
299
300 return(0);
301 }
302