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
readPacket(char * mem,int size)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
example4Func(const char * filename)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
main(int argc,char ** argv)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 */
main(int argc,char ** argv)139 int main(int argc, char **argv) {
140 fprintf(stderr, "Library not compiled with push parser support\n");
141 return(1);
142 }
143 #endif
144