/ libxml2 / example / gjobread.c
gjobread.c
  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 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  
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  }