/ libxml2 / doc / examples / parse4.c
parse4.c
  1  /**
  2   * section: Parsing
  3   * synopsis: Parse an XML document chunk by chunk to a tree and free it
  4   * purpose: Demonstrate the use of xmlCreatePushParserCtxt() and
  5   *          xmlParseChunk() to read an XML file progressively
  6   *          into a tree and and xmlFreeDoc() to free the resulting tree
  7   * usage: parse4 test3.xml
  8   * test: parse4 test3.xml
  9   * author: Daniel Veillard
 10   * copy: see Copyright for the status of this software.
 11   */
 12  
 13  #include <stdio.h>
 14  #include <libxml/parser.h>
 15  #include <libxml/tree.h>
 16  
 17  #ifdef LIBXML_PUSH_ENABLED
 18  static FILE *desc;
 19  
 20  /**
 21   * readPacket:
 22   * @mem: array to store the packet
 23   * @size: the packet size
 24   *
 25   * read at most @size bytes from the document and store it in @mem
 26   *
 27   * Returns the number of bytes read
 28   */
 29  static int
 30  readPacket(char *mem, int size) {
 31      int res;
 32  
 33      res = fread(mem, 1, size, desc);
 34      return(res);
 35  }
 36  
 37  /**
 38   * example4Func:
 39   * @filename: a filename or an URL
 40   *
 41   * Parse the resource and free the resulting tree
 42   */
 43  static void
 44  example4Func(const char *filename) {
 45      xmlParserCtxtPtr ctxt;
 46      char chars[4];
 47      xmlDocPtr doc; /* the resulting document tree */
 48      int res;
 49  
 50      /*
 51       * Read a few first byte to check the input used for the
 52       * encoding detection at the parser level.
 53       */
 54      res = readPacket(chars, 4);
 55      if (res <= 0) {
 56          fprintf(stderr, "Failed to parse %s\n", filename);
 57  	return;
 58      }
 59  
 60      /*
 61       * Create a progressive parsing context, the 2 first arguments
 62       * are not used since we want to build a tree and not use a SAX
 63       * parsing interface. We also pass the first bytes of the document
 64       * to allow encoding detection when creating the parser but this
 65       * is optional.
 66       */
 67      ctxt = xmlCreatePushParserCtxt(NULL, NULL,
 68                                     chars, res, filename);
 69      if (ctxt == NULL) {
 70          fprintf(stderr, "Failed to create parser context !\n");
 71  	return;
 72      }
 73  
 74      /*
 75       * loop on the input getting the document data, of course 4 bytes
 76       * at a time is not realistic but allows to verify testing on small
 77       * documents.
 78       */
 79      while ((res = readPacket(chars, 4)) > 0) {
 80          xmlParseChunk(ctxt, chars, res, 0);
 81      }
 82  
 83      /*
 84       * there is no more input, indicate the parsing is finished.
 85       */
 86      xmlParseChunk(ctxt, chars, 0, 1);
 87  
 88      /*
 89       * collect the document back and if it was wellformed
 90       * and destroy the parser context.
 91       */
 92      doc = ctxt->myDoc;
 93      res = ctxt->wellFormed;
 94      xmlFreeParserCtxt(ctxt);
 95  
 96      if (!res) {
 97          fprintf(stderr, "Failed to parse %s\n", filename);
 98      }
 99  
100      /*
101       * since we don't use the document, destroy it now.
102       */
103      xmlFreeDoc(doc);
104  }
105  
106  int main(int argc, char **argv) {
107      if (argc != 2)
108          return(1);
109  
110      /*
111       * this initialize the library and check potential ABI mismatches
112       * between the version it was compiled for and the actual shared
113       * library used.
114       */
115      LIBXML_TEST_VERSION
116  
117      /*
118       * simulate a progressive parsing using the input file.
119       */
120      desc = fopen(argv[1], "rb");
121      if (desc != NULL) {
122  	example4Func(argv[1]);
123  	fclose(desc);
124      } else {
125          fprintf(stderr, "Failed to parse %s\n", argv[1]);
126      }
127  
128      /*
129       * Cleanup function for the XML library.
130       */
131      xmlCleanupParser();
132      /*
133       * this is to debug memory for regression tests
134       */
135      xmlMemoryDump();
136      return(0);
137  }
138  #else /* ! LIBXML_PUSH_ENABLED */
139  int main(int argc, char **argv) {
140      fprintf(stderr, "Library not compiled with push parser support\n");
141      return(1);
142  }
143  #endif