| /** |
| * section: Parsing |
| * synopsis: Parse an XML document chunk by chunk to a tree and free it |
| * purpose: Demonstrate the use of xmlCreatePushParserCtxt() and |
| * xmlParseChunk() to read an XML file progressively |
| * into a tree and and xmlFreeDoc() to free the resulting tree |
| * usage: parse4 test3.xml |
| * test: parse4 test3.xml |
| * author: Daniel Veillard |
| * copy: see Copyright for the status of this software. |
| */ |
| |
| #include <stdio.h> |
| #include <libxml/parser.h> |
| #include <libxml/tree.h> |
| |
| #ifdef LIBXML_PUSH_ENABLED |
| static FILE *desc; |
| |
| /** |
| * readPacket: |
| * @mem: array to store the packet |
| * @size: the packet size |
| * |
| * read at most @size bytes from the document and store it in @mem |
| * |
| * Returns the number of bytes read |
| */ |
| static int |
| readPacket(char *mem, int size) { |
| int res; |
| |
| res = fread(mem, 1, size, desc); |
| return(res); |
| } |
| |
| /** |
| * example4Func: |
| * @filename: a filename or an URL |
| * |
| * Parse the resource and free the resulting tree |
| */ |
| static void |
| example4Func(const char *filename) { |
| xmlParserCtxtPtr ctxt; |
| char chars[4]; |
| xmlDocPtr doc; /* the resulting document tree */ |
| int res; |
| |
| /* |
| * Read a few first byte to check the input used for the |
| * encoding detection at the parser level. |
| */ |
| res = readPacket(chars, 4); |
| if (res <= 0) { |
| fprintf(stderr, "Failed to parse %s\n", filename); |
| return; |
| } |
| |
| /* |
| * Create a progressive parsing context, the 2 first arguments |
| * are not used since we want to build a tree and not use a SAX |
| * parsing interface. We also pass the first bytes of the document |
| * to allow encoding detection when creating the parser but this |
| * is optional. |
| */ |
| ctxt = xmlCreatePushParserCtxt(NULL, NULL, |
| chars, res, filename); |
| if (ctxt == NULL) { |
| fprintf(stderr, "Failed to create parser context !\n"); |
| return; |
| } |
| |
| /* |
| * loop on the input getting the document data, of course 4 bytes |
| * at a time is not realistic but allows to verify testing on small |
| * documents. |
| */ |
| while ((res = readPacket(chars, 4)) > 0) { |
| xmlParseChunk(ctxt, chars, res, 0); |
| } |
| |
| /* |
| * there is no more input, indicate the parsing is finished. |
| */ |
| xmlParseChunk(ctxt, chars, 0, 1); |
| |
| /* |
| * collect the document back and if it was wellformed |
| * and destroy the parser context. |
| */ |
| doc = ctxt->myDoc; |
| res = ctxt->wellFormed; |
| xmlFreeParserCtxt(ctxt); |
| |
| if (!res) { |
| fprintf(stderr, "Failed to parse %s\n", filename); |
| } |
| |
| /* |
| * since we don't use the document, destroy it now. |
| */ |
| xmlFreeDoc(doc); |
| } |
| |
| int main(int argc, char **argv) { |
| if (argc != 2) |
| return(1); |
| |
| /* |
| * this initialize the library and check potential ABI mismatches |
| * between the version it was compiled for and the actual shared |
| * library used. |
| */ |
| LIBXML_TEST_VERSION |
| |
| /* |
| * simulate a progressive parsing using the input file. |
| */ |
| desc = fopen(argv[1], "rb"); |
| if (desc != NULL) { |
| example4Func(argv[1]); |
| fclose(desc); |
| } else { |
| fprintf(stderr, "Failed to parse %s\n", argv[1]); |
| } |
| |
| /* |
| * Cleanup function for the XML library. |
| */ |
| xmlCleanupParser(); |
| /* |
| * this is to debug memory for regression tests |
| */ |
| xmlMemoryDump(); |
| return(0); |
| } |
| #else /* ! LIBXML_PUSH_ENABLED */ |
| int main(int argc, char **argv) { |
| fprintf(stderr, "Library not compiled with push parser support\n"); |
| return(1); |
| } |
| #endif |