/** * 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 #include #include #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