summaryrefslogtreecommitdiff
path: root/doc/examples/parse4.c
blob: 49191d5b9718ac5cef7bc3d4b4a16a5d0a3cd498 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * 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 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(0);
}
#endif