blob: be5a0abdd87598911d38c77525b07cdd0dd6c8e9 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
Daniel Veillard97b58771998-10-20 06:14:16 +00003 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004 * See Copyright for the status of this software.
5 *
Daniel Veillard97b58771998-10-20 06:14:16 +00006 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000016#include <stdlib.h>
Daniel Veillard6454aec1999-09-02 22:04:43 +000017#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000018#include "tree.h"
19#include "parser.h"
Daniel Veillard517752b1999-04-05 12:20:10 +000020#include "parserInternals.h"
21#include "valid.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000022#include "entities.h"
Daniel Veillardd109e371999-03-05 06:26:45 +000023#include "xml-error.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000024#include "debugXML.h"
Daniel Veillard294cbca1999-12-03 13:19:09 +000025#include "SAX.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000026
27/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000028/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000029
Daniel Veillard97b58771998-10-20 06:14:16 +000030/**
31 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000032 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000033 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000034 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000035 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000036 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000037 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000038const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000039getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000040{
Daniel Veillard27d88741999-05-29 11:51:49 +000041 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000042 return(NULL);
43}
44
Daniel Veillard97b58771998-10-20 06:14:16 +000045/**
46 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000047 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000048 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000049 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000050 * http://www.sgmlsource.com/dtds/memo.dtd
51 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000052 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000053 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000054const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000055getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000056{
Daniel Veillard27d88741999-05-29 11:51:49 +000057 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000058 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000059}
60
Daniel Veillard97b58771998-10-20 06:14:16 +000061/**
62 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000063 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000064 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000065 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000066 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000067 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 */
Daniel Veillard97b58771998-10-20 06:14:16 +000069int
Daniel Veillard27d88741999-05-29 11:51:49 +000070getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000071{
Daniel Veillard27d88741999-05-29 11:51:49 +000072 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000073 return(ctxt->input->line);
74}
Daniel Veillard97b58771998-10-20 06:14:16 +000075
76/**
77 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000078 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000079 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000080 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000081 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000082 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000083 */
Daniel Veillard97b58771998-10-20 06:14:16 +000084int
Daniel Veillard27d88741999-05-29 11:51:49 +000085getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000086{
Daniel Veillard27d88741999-05-29 11:51:49 +000087 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000088 return(ctxt->input->col);
89}
90
91/*
92 * The default SAX Locator.
93 */
94
95xmlSAXLocator xmlDefaultSAXLocator = {
96 getPublicId, getSystemId, getLineNumber, getColumnNumber
97};
98
Daniel Veillard97b58771998-10-20 06:14:16 +000099/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000100 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000101 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000102 *
103 * Is this document tagged standalone ?
104 *
105 * Returns 1 if true
106 */
107int
Daniel Veillard27d88741999-05-29 11:51:49 +0000108isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000109{
Daniel Veillard27d88741999-05-29 11:51:49 +0000110 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000111 return(ctxt->myDoc->standalone == 1);
112}
113
114/**
115 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000116 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000117 *
118 * Does this document has an internal subset
119 *
120 * Returns 1 if true
121 */
122int
Daniel Veillard27d88741999-05-29 11:51:49 +0000123hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000124{
Daniel Veillard27d88741999-05-29 11:51:49 +0000125 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000126 return(ctxt->myDoc->intSubset != NULL);
127}
128
129/**
130 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000131 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000132 *
133 * Does this document has an external subset
134 *
135 * Returns 1 if true
136 */
137int
Daniel Veillard27d88741999-05-29 11:51:49 +0000138hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000139{
Daniel Veillard27d88741999-05-29 11:51:49 +0000140 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000141 return(ctxt->myDoc->extSubset != NULL);
142}
143
144/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000145 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000146 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000147 *
148 * Does this document has an internal subset
149 */
150void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000151internalSubset(void *ctx, const xmlChar *name,
152 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000153{
Daniel Veillard27d88741999-05-29 11:51:49 +0000154 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000155#ifdef DEBUG_SAX
156 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
157 name, ExternalID, SystemID);
158#endif
159 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000160 if (((ExternalID != NULL) || (SystemID != NULL)) &&
161 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
162 /*
163 * Try to fetch and parse the external subset.
164 */
165 xmlDtdPtr ret = NULL;
166 xmlParserCtxtPtr dtdCtxt;
167 xmlParserInputPtr input = NULL;
168 xmlCharEncoding enc;
169
170 dtdCtxt = xmlNewParserCtxt();
171 if (dtdCtxt == NULL) return;
172
173 /*
174 * Ask the Entity resolver to load the damn thing
175 */
176 if ((ctxt->directory != NULL) && (dtdCtxt->directory == NULL))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000177 dtdCtxt->directory = (char *) xmlStrdup(BAD_CAST ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000178
179 if ((dtdCtxt->sax != NULL) && (dtdCtxt->sax->resolveEntity != NULL))
180 input = dtdCtxt->sax->resolveEntity(dtdCtxt->userData, ExternalID,
181 SystemID);
182 if (input == NULL) {
183 xmlFreeParserCtxt(dtdCtxt);
184 return;
185 }
186
187 /*
188 * plug some encoding conversion routines here. !!!
189 */
190 xmlPushInput(dtdCtxt, input);
191 enc = xmlDetectCharEncoding(dtdCtxt->input->cur);
192 xmlSwitchEncoding(dtdCtxt, enc);
193
194 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000195 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000196 input->line = 1;
197 input->col = 1;
198 input->base = dtdCtxt->input->cur;
199 input->cur = dtdCtxt->input->cur;
200 input->free = NULL;
201
202 /*
203 * let's parse that entity knowing it's an external subset.
204 */
205 xmlParseExternalSubset(dtdCtxt, ExternalID, SystemID);
206
207 if (dtdCtxt->myDoc != NULL) {
208 if (dtdCtxt->wellFormed) {
209 ret = dtdCtxt->myDoc->intSubset;
210 dtdCtxt->myDoc->intSubset = NULL;
211 } else {
212 ret = NULL;
213 }
214 xmlFreeDoc(dtdCtxt->myDoc);
215 dtdCtxt->myDoc = NULL;
216 }
217 xmlFreeParserCtxt(dtdCtxt);
218
219 ctxt->myDoc->extSubset = ret;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000220 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000221}
222
223/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000224 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000225 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000226 * @publicId: The public ID of the entity
227 * @systemId: The system ID of the entity
228 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 * Special entity resolver, better left to the parser, it has
230 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000231 * The default behaviour is to NOT resolve the entities, in that case
232 * the ENTITY_REF nodes are built in the structure (and the parameter
233 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000234 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000235 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000236 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000237xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000238resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000239{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000240 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000241
242#ifdef DEBUG_SAX
243 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
244#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000245
Daniel Veillard011b63c1999-06-02 17:44:04 +0000246 if (systemId != NULL) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000247 return(xmlNewInputFromFile(ctxt, (char *) systemId));
Daniel Veillard011b63c1999-06-02 17:44:04 +0000248 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 return(NULL);
250}
251
Daniel Veillard97b58771998-10-20 06:14:16 +0000252/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000253 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000254 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000255 * @name: The entity name
256 *
257 * Get an entity by name
258 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000259 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000260 */
261xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000262getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000263{
Daniel Veillard27d88741999-05-29 11:51:49 +0000264 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000265 xmlEntityPtr ret;
266
267#ifdef DEBUG_SAX
268 fprintf(stderr, "SAX.getEntity(%s)\n", name);
269#endif
270
271 ret = xmlGetDocEntity(ctxt->myDoc, name);
272 return(ret);
273}
274
Daniel Veillardb05deb71999-08-10 19:04:08 +0000275/**
276 * getParameterEntity:
277 * @ctx: the user data (XML parser context)
278 * @name: The entity name
279 *
280 * Get a parameter entity by name
281 *
282 * Returns the xmlEntityPtr if found.
283 */
284xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000285getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000286{
287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
288 xmlEntityPtr ret;
289
290#ifdef DEBUG_SAX
291 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
292#endif
293
294 ret = xmlGetParameterEntity(ctxt->myDoc, name);
295 return(ret);
296}
297
Daniel Veillard517752b1999-04-05 12:20:10 +0000298
299/**
300 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000301 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000302 * @name: the entity name
303 * @type: the entity type
304 * @publicId: The public ID of the entity
305 * @systemId: The system ID of the entity
306 * @content: the entity value (without processing).
307 *
308 * An entity definition has been parsed
309 */
310void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000311entityDecl(void *ctx, const xmlChar *name, int type,
312 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000313{
Daniel Veillard27d88741999-05-29 11:51:49 +0000314 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000315
316#ifdef DEBUG_SAX
317 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
318 name, type, publicId, systemId, content);
319#endif
320 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
321}
322
323/**
324 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000325 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000326 * @name: the attribute name
327 * @type: the attribute type
328 * @publicId: The public ID of the attribute
329 * @systemId: The system ID of the attribute
330 * @content: the attribute value (without processing).
331 *
332 * An attribute definition has been parsed
333 */
334void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000335attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *name,
336 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000337 xmlEnumerationPtr tree)
338{
Daniel Veillard27d88741999-05-29 11:51:49 +0000339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000340 xmlAttributePtr attr;
Daniel Veillard517752b1999-04-05 12:20:10 +0000341
342#ifdef DEBUG_SAX
343 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
344 elem, name, type, def, defaultValue);
345#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000346 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
347 name, type, def, defaultValue, tree);
348 if (attr == 0) ctxt->valid = 0;
349 if (ctxt->validate && ctxt->wellFormed &&
350 ctxt->myDoc && ctxt->myDoc->intSubset)
351 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
352 attr);
Daniel Veillard517752b1999-04-05 12:20:10 +0000353}
354
355/**
356 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000357 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000358 * @name: the element name
359 * @type: the element type
360 * @publicId: The public ID of the element
361 * @systemId: The system ID of the element
362 * @content: the element value (without processing).
363 *
364 * An element definition has been parsed
365 */
366void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000367elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000368 xmlElementContentPtr content)
369{
Daniel Veillard27d88741999-05-29 11:51:49 +0000370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000371 xmlElementPtr elem;
Daniel Veillard517752b1999-04-05 12:20:10 +0000372
373#ifdef DEBUG_SAX
374 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
375 name, type);
376#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000377
378 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
379 name, type, content);
380 if (elem == 0) ctxt->valid = 0;
381 if (ctxt->validate && ctxt->wellFormed &&
382 ctxt->myDoc && ctxt->myDoc->intSubset)
383 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000384}
385
386/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000387 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000388 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000389 * @name: The name of the notation
390 * @publicId: The public ID of the entity
391 * @systemId: The system ID of the entity
392 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000395void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000396notationDecl(void *ctx, const xmlChar *name,
397 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000398{
Daniel Veillard27d88741999-05-29 11:51:49 +0000399 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000400 xmlNotationPtr nota;
401
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402#ifdef DEBUG_SAX
403 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
404#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000405
406 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
407 publicId, systemId);
408 if (nota == 0) ctxt->valid = 0;
409 if (ctxt->validate && ctxt->wellFormed &&
410 ctxt->myDoc && ctxt->myDoc->intSubset)
411 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
412 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413}
414
Daniel Veillard97b58771998-10-20 06:14:16 +0000415/**
416 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000417 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000418 * @name: The name of the entity
419 * @publicId: The public ID of the entity
420 * @systemId: The system ID of the entity
421 * @notationName: the name of the notation
422 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000424 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000425void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000426unparsedEntityDecl(void *ctx, const xmlChar *name,
427 const xmlChar *publicId, const xmlChar *systemId,
428 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000429{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000430 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000431#ifdef DEBUG_SAX
432 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
433 name, publicId, systemId, notationName);
434#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000435 if (ctxt->validate && ctxt->wellFormed &&
436 ctxt->myDoc && ctxt->myDoc->intSubset)
437 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
438 notationName);
439 xmlAddDocEntity(ctxt->myDoc, name,
440 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
441 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442}
443
Daniel Veillard97b58771998-10-20 06:14:16 +0000444/**
445 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000446 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000447 * @loc: A SAX Locator
448 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000449 * Receive the document locator at startup, actually xmlDefaultSAXLocator
450 * Everything is available on the context, so this is useless in our case.
451 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000452void
Daniel Veillard27d88741999-05-29 11:51:49 +0000453setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000454{
Daniel Veillard27d88741999-05-29 11:51:49 +0000455 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000456#ifdef DEBUG_SAX
457 fprintf(stderr, "SAX.setDocumentLocator()\n");
458#endif
459}
460
Daniel Veillard97b58771998-10-20 06:14:16 +0000461/**
462 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000463 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000464 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000465 * called when the document start being processed.
466 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000467void
Daniel Veillard27d88741999-05-29 11:51:49 +0000468startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000469{
Daniel Veillard27d88741999-05-29 11:51:49 +0000470 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000471 xmlDocPtr doc;
472
Daniel Veillard260a68f1998-08-13 03:39:55 +0000473#ifdef DEBUG_SAX
474 fprintf(stderr, "SAX.startDocument()\n");
475#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000476 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
477 if (doc != NULL) {
478 if (ctxt->encoding != NULL)
479 doc->encoding = xmlStrdup(ctxt->encoding);
480 else
481 doc->encoding = NULL;
482 doc->standalone = ctxt->standalone;
483 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484}
485
Daniel Veillard97b58771998-10-20 06:14:16 +0000486/**
487 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000488 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000489 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000490 * called when the document end has been detected.
491 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000492void
Daniel Veillard27d88741999-05-29 11:51:49 +0000493endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000494{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496#ifdef DEBUG_SAX
497 fprintf(stderr, "SAX.endDocument()\n");
498#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000499 if (ctxt->validate && ctxt->wellFormed &&
500 ctxt->myDoc && ctxt->myDoc->intSubset)
501 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000502}
503
Daniel Veillard97b58771998-10-20 06:14:16 +0000504/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000505 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000506 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000507 * @name: The attribute name
508 * @value: The attribute value
509 *
510 * Handle an attribute that has been read by the parser.
511 * The default handling is to convert the attribute into an
512 * DOM subtree and past it in a new xmlAttr element added to
513 * the element.
514 */
515void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000516attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000517{
Daniel Veillard27d88741999-05-29 11:51:49 +0000518 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000519 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000520 xmlChar *name;
521 xmlChar *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000522 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000523
524/****************
525#ifdef DEBUG_SAX
526 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
527#endif
528 ****************/
529 /*
530 * Split the full name into a namespace prefix and the tag name
531 */
532 name = xmlSplitQName(fullname, &ns);
533
534 /*
535 * Check whether it's a namespace definition
536 */
537 if ((ns == NULL) &&
538 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
539 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
540 /* a default namespace definition */
541 xmlNewNs(ctxt->node, value, NULL);
542 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000543 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000544 return;
545 }
546 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
547 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
548 /* a standard namespace definition */
549 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000550 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000551 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000552 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000553 return;
554 }
555
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000556 if (ns != NULL)
557 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
558 else {
559 namespace = NULL;
560 }
561
Daniel Veillardb96e6431999-08-29 21:02:19 +0000562 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
563 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000564
Daniel Veillardb96e6431999-08-29 21:02:19 +0000565 if (ret != NULL) {
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000566 if ((ctxt->replaceEntities == 0) && (!ctxt->html))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000567 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
568 else
569 ret->val = xmlNewDocText(ctxt->myDoc, value);
570 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000571
572 if (ctxt->validate && ctxt->wellFormed &&
573 ctxt->myDoc && ctxt->myDoc->intSubset)
574 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
575 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000576 else {
577 /*
578 * when validating, the ID registration is done at the attribute
579 * validation level. Otherwise we have to do specific handling here.
580 */
581 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
582 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000583 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
584 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000585 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000586
Daniel Veillard517752b1999-04-05 12:20:10 +0000587 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000588 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000589 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000590 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000591}
592
593/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000594 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000595 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000596 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000597 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000598 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000599 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000600 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000601void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000602startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000603{
Daniel Veillard27d88741999-05-29 11:51:49 +0000604 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000605 xmlNodePtr ret;
606 xmlNodePtr parent = ctxt->node;
607 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000608 xmlChar *name;
609 xmlChar *prefix;
610 const xmlChar *att;
611 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000612 int i;
613
Daniel Veillard260a68f1998-08-13 03:39:55 +0000614#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000615 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000616#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000617
618 /*
619 * First check on validity:
620 */
621 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
622 ((ctxt->myDoc->intSubset == NULL) ||
623 ((ctxt->myDoc->intSubset->notations == NULL) &&
624 (ctxt->myDoc->intSubset->elements == NULL) &&
625 (ctxt->myDoc->intSubset->attributes == NULL) &&
626 (ctxt->myDoc->intSubset->entities == NULL)))) {
627 if (ctxt->vctxt.error != NULL) {
628 ctxt->vctxt.error(ctxt->vctxt.userData,
629 "Validation failed: no DTD found !\n");
630 }
631 ctxt->validate = 0;
632 }
633
634
Daniel Veillard517752b1999-04-05 12:20:10 +0000635 /*
636 * Split the full name into a namespace prefix and the tag name
637 */
638 name = xmlSplitQName(fullname, &prefix);
639
640
641 /*
642 * Note : the namespace resolution is deferred until the end of the
643 * attributes parsing, since local namespace can be defined as
644 * an attribute at this level.
645 */
646 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
647 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000648 if (ctxt->myDoc->root == NULL) {
649#ifdef DEBUG_SAX_TREE
650 fprintf(stderr, "Setting %s as root\n", name);
651#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000652 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000653 } else if (parent == NULL) {
654 parent = ctxt->myDoc->root;
655 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000656
657 /*
658 * We are parsing a new node.
659 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000660#ifdef DEBUG_SAX_TREE
661 fprintf(stderr, "pushing(%s)\n", name);
662#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000663 nodePush(ctxt, ret);
664
665 /*
666 * Link the child element
667 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000668 if (parent != NULL) {
669 if (parent->type == XML_ELEMENT_NODE) {
670#ifdef DEBUG_SAX_TREE
671 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
672#endif
673 xmlAddChild(parent, ret);
674 } else {
675#ifdef DEBUG_SAX_TREE
676 fprintf(stderr, "adding sibling %s to ", name);
677 xmlDebugDumpOneNode(stderr, parent, 0);
678#endif
679 xmlAddSibling(parent, ret);
680 }
681 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000682
683 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000684 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000685 */
686 if (atts != NULL) {
687 i = 0;
688 att = atts[i++];
689 value = atts[i++];
690 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000691 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
692 attribute(ctxt, att, value);
693
694 att = atts[i++];
695 value = atts[i++];
696 }
697 }
698
699 /*
700 * process all the other attributes
701 */
702 if (atts != NULL) {
703 i = 0;
704 att = atts[i++];
705 value = atts[i++];
706 while ((att != NULL) && (value != NULL)) {
707 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
708 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000709
710 /*
711 * Next ones
712 */
713 att = atts[i++];
714 value = atts[i++];
715 }
716 }
717
718 /*
719 * Search the namespace, note that since the attributes have been
720 * processed, the local namespaces are available.
721 */
722 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
723 if ((ns == NULL) && (parent != NULL))
724 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
725 xmlSetNs(ret, ns);
726
727 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000728 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000729 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000730 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000731
Daniel Veillard260a68f1998-08-13 03:39:55 +0000732}
733
Daniel Veillard97b58771998-10-20 06:14:16 +0000734/**
735 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000736 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000737 * @name: The element name
738 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000739 * called when the end of an element has been detected.
740 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000741void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000742endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000743{
Daniel Veillard27d88741999-05-29 11:51:49 +0000744 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000745 xmlParserNodeInfo node_info;
746 xmlNodePtr cur = ctxt->node;
747
Daniel Veillard260a68f1998-08-13 03:39:55 +0000748#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000749 if (name == NULL)
750 fprintf(stderr, "SAX.endElement(NULL)\n");
751 else
752 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000753#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000754
755 /* Capture end position and add node */
756 if (cur != NULL && ctxt->record_info) {
757 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
758 node_info.end_line = ctxt->input->line;
759 node_info.node = cur;
760 xmlParserAddNodeInfo(ctxt, &node_info);
761 }
762
Daniel Veillardb05deb71999-08-10 19:04:08 +0000763 if (ctxt->validate && ctxt->wellFormed &&
764 ctxt->myDoc && ctxt->myDoc->intSubset)
765 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
766 cur);
767
768
Daniel Veillard517752b1999-04-05 12:20:10 +0000769 /*
770 * end of parsing of this node.
771 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000772#ifdef DEBUG_SAX_TREE
773 fprintf(stderr, "popping(%s)\n", cur->name);
774#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000775 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000776}
777
Daniel Veillard97b58771998-10-20 06:14:16 +0000778/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000779 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000780 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000781 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000782 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000783 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000784 */
785void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000786reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000787{
Daniel Veillard27d88741999-05-29 11:51:49 +0000788 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000789 xmlNodePtr ret;
790
Daniel Veillard11e00581998-10-24 18:27:49 +0000791#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000792 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000793#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000794 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000795#ifdef DEBUG_SAX_TREE
796 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
797#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000798 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000799}
800
801/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000802 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000803 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000804 * @ch: a xmlChar string
805 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000806 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807 * receiving some chars from the parser.
808 * Question: how much at a time ???
809 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000810void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000811characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000812{
Daniel Veillard27d88741999-05-29 11:51:49 +0000813 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000814 xmlNodePtr lastChild;
815
816#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000817 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818#endif
819 /*
820 * Handle the data if any. If there is no child
821 * add it as content, otherwise if the last child is text,
822 * concatenate it, else create a new node of type text.
823 */
824
Daniel Veillard35008381999-10-25 13:15:52 +0000825 if (ctxt->node == NULL) {
826#ifdef DEBUG_SAX_TREE
827 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
828#endif
829 return;
830 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000831 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000832#ifdef DEBUG_SAX_TREE
833 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
834#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000835 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000836 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000837 else {
838 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000839 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000840 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000841 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000842 xmlAddChild(ctxt->node, lastChild);
843 }
844 }
845}
846
Daniel Veillard97b58771998-10-20 06:14:16 +0000847/**
848 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000849 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000850 * @ch: a xmlChar string
851 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000852 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000853 * receiving some ignorable whitespaces from the parser.
854 * Question: how much at a time ???
855 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000856void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000857ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000858{
Daniel Veillard27d88741999-05-29 11:51:49 +0000859 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000860#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000861 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000862#endif
863}
864
Daniel Veillard97b58771998-10-20 06:14:16 +0000865/**
866 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000867 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000868 * @target: the target name
869 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000870 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000871 *
872 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000873 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000874void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000875processingInstruction(void *ctx, const xmlChar *target,
876 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +0000877{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000878 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
879 xmlNodePtr ret;
880 xmlNodePtr parent = ctxt->node;
881
Daniel Veillard260a68f1998-08-13 03:39:55 +0000882#ifdef DEBUG_SAX
883 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
884#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000885
886 ret = xmlNewPI(target, data);
887 if (ret == NULL) return;
888 ret->doc = ctxt->myDoc;
889 if (ctxt->myDoc->root == NULL) {
890#ifdef DEBUG_SAX_TREE
891 fprintf(stderr, "Setting PI %s as root\n", target);
892#endif
893 ctxt->myDoc->root = ret;
894 } else if (parent == NULL) {
895 parent = ctxt->myDoc->root;
896 }
897 if (parent != NULL) {
898 if (parent->type == XML_ELEMENT_NODE) {
899#ifdef DEBUG_SAX_TREE
900 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
901#endif
902 xmlAddChild(parent, ret);
903 } else {
904#ifdef DEBUG_SAX_TREE
905 fprintf(stderr, "adding PI sibling %s to ", target);
906 xmlDebugDumpOneNode(stderr, parent, 0);
907#endif
908 xmlAddSibling(parent, ret);
909 }
910 }
911
Daniel Veillard260a68f1998-08-13 03:39:55 +0000912}
913
Daniel Veillard517752b1999-04-05 12:20:10 +0000914/**
915 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000916 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000917 * @href: the namespace associated URN
918 * @prefix: the namespace prefix
919 *
920 * An old global namespace has been parsed.
921 */
922void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000923globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000924{
Daniel Veillard27d88741999-05-29 11:51:49 +0000925 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000926#ifdef DEBUG_SAX
927 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
928#endif
929 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
930}
931
932/**
933 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000934 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000935 * @name: the namespace prefix
936 *
937 * Set the current element namespace.
938 */
939void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000940setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000941{
Daniel Veillard27d88741999-05-29 11:51:49 +0000942 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000943 xmlNsPtr ns;
944 xmlNodePtr parent;
945
946#ifdef DEBUG_SAX
947 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
948#endif
949 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
950 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
951 if (ctxt->nodeNr >= 2) {
952 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
953 if (parent != NULL)
954 ns = xmlSearchNs(ctxt->myDoc, parent, name);
955 }
956 }
957 xmlSetNs(ctxt->node, ns);
958}
959
960/**
961 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000962 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000963 *
964 * Get the current element namespace.
965 */
966xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000967getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000968{
Daniel Veillard27d88741999-05-29 11:51:49 +0000969 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000970 xmlNsPtr ret;
971
972#ifdef DEBUG_SAX
973 fprintf(stderr, "SAX.getNamespace()\n");
974#endif
975 ret = ctxt->node->ns;
976 return(ret);
977}
978
979/**
980 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000981 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000982 * @namespace: the namespace to check against
983 *
984 * Check that the current element namespace is the same as the
985 * one read upon parsing.
986 */
987int
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000988checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000989{
Daniel Veillard27d88741999-05-29 11:51:49 +0000990 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000991 xmlNodePtr cur = ctxt->node;
992
993#ifdef DEBUG_SAX
994 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
995#endif
996
997 /*
998 * Check that the Name in the ETag is the same as in the STag.
999 */
1000 if (namespace == NULL) {
1001 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1002 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1003 ctxt->sax->error(ctxt,
1004 "End tags for %s don't hold the namespace %s\n",
1005 cur->name, cur->ns->prefix);
1006 ctxt->wellFormed = 0;
1007 }
1008 } else {
1009 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1010 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1011 ctxt->sax->error(ctxt,
1012 "End tags %s holds a prefix %s not used by the open tag\n",
1013 cur->name, namespace);
1014 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001015 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001016 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1017 ctxt->sax->error(ctxt,
1018 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1019 cur->name, cur->ns->prefix, namespace);
1020 ctxt->wellFormed = 0;
1021 } else
1022 return(1);
1023 }
1024 return(0);
1025}
1026
1027/**
1028 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001029 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001030 * @href: the namespace associated URN
1031 * @prefix: the namespace prefix
1032 *
1033 * A namespace has been parsed.
1034 */
1035void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001036namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001037{
Daniel Veillard27d88741999-05-29 11:51:49 +00001038 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001039#ifdef DEBUG_SAX
1040 if (prefix == NULL)
1041 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1042 else
1043 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1044#endif
1045 xmlNewNs(ctxt->node, href, prefix);
1046}
1047
1048/**
1049 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001050 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001051 * @value: the comment content
1052 *
1053 * A comment has been parsed.
1054 */
1055void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001056comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001057{
Daniel Veillard27d88741999-05-29 11:51:49 +00001058 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001059 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001060 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001061
Daniel Veillard517752b1999-04-05 12:20:10 +00001062#ifdef DEBUG_SAX
1063 fprintf(stderr, "SAX.comment(%s)\n", value);
1064#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001065 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001066 if (ret == NULL) return;
1067
1068 if (ctxt->myDoc->root == NULL) {
1069#ifdef DEBUG_SAX_TREE
1070 fprintf(stderr, "Setting comment as root\n");
1071#endif
1072 ctxt->myDoc->root = ret;
1073 } else if (parent == NULL) {
1074 parent = ctxt->myDoc->root;
1075 }
1076 if (parent != NULL) {
1077 if (parent->type == XML_ELEMENT_NODE) {
1078#ifdef DEBUG_SAX_TREE
1079 fprintf(stderr, "adding comment child to %s\n", parent->name);
1080#endif
1081 xmlAddChild(parent, ret);
1082 } else {
1083#ifdef DEBUG_SAX_TREE
1084 fprintf(stderr, "adding comment sibling to ");
1085 xmlDebugDumpOneNode(stderr, parent, 0);
1086#endif
1087 xmlAddSibling(parent, ret);
1088 }
1089 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001090}
1091
1092/**
1093 * cdataBlock:
1094 * @ctx: the user data (XML parser context)
1095 * @value: The pcdata content
1096 * @len: the block length
1097 *
1098 * called when a pcdata block has been parsed
1099 */
1100void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001101cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001102{
1103 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1104 xmlNodePtr ret;
1105
1106#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001107 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001108#endif
1109 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1110 xmlAddChild(ctxt->node, ret);
1111 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001112}
1113
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001114/*
1115 * Default handler for XML, builds the DOM tree
1116 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001117xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001118 internalSubset,
1119 isStandalone,
1120 hasInternalSubset,
1121 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001122 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001123 getEntity,
1124 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001125 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001126 attributeDecl,
1127 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001128 unparsedEntityDecl,
1129 setDocumentLocator,
1130 startDocument,
1131 endDocument,
1132 startElement,
1133 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001134 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001135 characters,
1136 ignorableWhitespace,
1137 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001138 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001139 xmlParserWarning,
1140 xmlParserError,
1141 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001142 getParameterEntity,
1143 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144};
1145
Daniel Veillard97b58771998-10-20 06:14:16 +00001146/**
1147 * xmlDefaultSAXHandlerInit:
1148 *
1149 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001150 */
1151void
1152xmlDefaultSAXHandlerInit(void)
1153{
Daniel Veillard517752b1999-04-05 12:20:10 +00001154 xmlDefaultSAXHandler.internalSubset = internalSubset;
1155 xmlDefaultSAXHandler.isStandalone = isStandalone;
1156 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1157 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001158 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001159 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001160 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001161 xmlDefaultSAXHandler.entityDecl = entityDecl;
1162 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1163 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 xmlDefaultSAXHandler.notationDecl = notationDecl;
1165 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1166 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1167 xmlDefaultSAXHandler.startDocument = startDocument;
1168 xmlDefaultSAXHandler.endDocument = endDocument;
1169 xmlDefaultSAXHandler.startElement = startElement;
1170 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001171 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001173 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001174 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1175 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001176 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001177 xmlDefaultSAXHandler.warning = xmlParserWarning;
1178 xmlDefaultSAXHandler.error = xmlParserError;
1179 xmlDefaultSAXHandler.fatalError = xmlParserError;
1180}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001181
1182/*
1183 * Default handler for HTML, builds the DOM tree
1184 */
1185xmlSAXHandler htmlDefaultSAXHandler = {
1186 NULL,
1187 NULL,
1188 NULL,
1189 NULL,
1190 NULL,
1191 getEntity,
1192 NULL,
1193 NULL,
1194 NULL,
1195 NULL,
1196 NULL,
1197 setDocumentLocator,
1198 startDocument,
1199 endDocument,
1200 startElement,
1201 endElement,
1202 NULL,
1203 characters,
1204 ignorableWhitespace,
1205 NULL,
1206 comment,
1207 xmlParserWarning,
1208 xmlParserError,
1209 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001210 getParameterEntity,
1211 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001212};
1213
1214/**
1215 * htmlDefaultSAXHandlerInit:
1216 *
1217 * Initialize the default SAX handler
1218 */
1219void
1220htmlDefaultSAXHandlerInit(void)
1221{
1222 htmlDefaultSAXHandler.internalSubset = NULL;
1223 htmlDefaultSAXHandler.isStandalone = NULL;
1224 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1225 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1226 htmlDefaultSAXHandler.resolveEntity = NULL;
1227 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001228 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001229 htmlDefaultSAXHandler.entityDecl = NULL;
1230 htmlDefaultSAXHandler.attributeDecl = NULL;
1231 htmlDefaultSAXHandler.elementDecl = NULL;
1232 htmlDefaultSAXHandler.notationDecl = NULL;
1233 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1234 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1235 htmlDefaultSAXHandler.startDocument = startDocument;
1236 htmlDefaultSAXHandler.endDocument = endDocument;
1237 htmlDefaultSAXHandler.startElement = startElement;
1238 htmlDefaultSAXHandler.endElement = endElement;
1239 htmlDefaultSAXHandler.reference = NULL;
1240 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001241 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001242 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1243 htmlDefaultSAXHandler.processingInstruction = NULL;
1244 htmlDefaultSAXHandler.comment = comment;
1245 htmlDefaultSAXHandler.warning = xmlParserWarning;
1246 htmlDefaultSAXHandler.error = xmlParserError;
1247 htmlDefaultSAXHandler.fatalError = xmlParserError;
1248}