blob: 527efc0e75f1ff24524d561bdd5b6e9d5a12c04a [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 Veillard260a68f1998-08-13 03:39:55 +000010#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000011#include <stdlib.h>
Daniel Veillard6454aec1999-09-02 22:04:43 +000012#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000013#include "tree.h"
14#include "parser.h"
Daniel Veillard517752b1999-04-05 12:20:10 +000015#include "parserInternals.h"
16#include "valid.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000017#include "entities.h"
Daniel Veillardd109e371999-03-05 06:26:45 +000018#include "xml-error.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000019#include "debugXML.h"
Daniel Veillard294cbca1999-12-03 13:19:09 +000020#include "SAX.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000021
22/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000023/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000024
Daniel Veillard97b58771998-10-20 06:14:16 +000025/**
26 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000027 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000028 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000029 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000030 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000031 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000032 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000033const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000034getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000035{
Daniel Veillard27d88741999-05-29 11:51:49 +000036 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000037 return(NULL);
38}
39
Daniel Veillard97b58771998-10-20 06:14:16 +000040/**
41 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000042 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000043 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000044 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000045 * http://www.sgmlsource.com/dtds/memo.dtd
46 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000047 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000048 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000049const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000050getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000051{
Daniel Veillard27d88741999-05-29 11:51:49 +000052 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000053 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000054}
55
Daniel Veillard97b58771998-10-20 06:14:16 +000056/**
57 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000058 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000059 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000060 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000061 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000062 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000063 */
Daniel Veillard97b58771998-10-20 06:14:16 +000064int
Daniel Veillard27d88741999-05-29 11:51:49 +000065getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000066{
Daniel Veillard27d88741999-05-29 11:51:49 +000067 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 return(ctxt->input->line);
69}
Daniel Veillard97b58771998-10-20 06:14:16 +000070
71/**
72 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000073 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000074 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000075 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000076 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000077 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000078 */
Daniel Veillard97b58771998-10-20 06:14:16 +000079int
Daniel Veillard27d88741999-05-29 11:51:49 +000080getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000081{
Daniel Veillard27d88741999-05-29 11:51:49 +000082 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000083 return(ctxt->input->col);
84}
85
86/*
87 * The default SAX Locator.
88 */
89
90xmlSAXLocator xmlDefaultSAXLocator = {
91 getPublicId, getSystemId, getLineNumber, getColumnNumber
92};
93
Daniel Veillard97b58771998-10-20 06:14:16 +000094/**
Daniel Veillard517752b1999-04-05 12:20:10 +000095 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +000096 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +000097 *
98 * Is this document tagged standalone ?
99 *
100 * Returns 1 if true
101 */
102int
Daniel Veillard27d88741999-05-29 11:51:49 +0000103isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000104{
Daniel Veillard27d88741999-05-29 11:51:49 +0000105 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000106 return(ctxt->myDoc->standalone == 1);
107}
108
109/**
110 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000111 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000112 *
113 * Does this document has an internal subset
114 *
115 * Returns 1 if true
116 */
117int
Daniel Veillard27d88741999-05-29 11:51:49 +0000118hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000119{
Daniel Veillard27d88741999-05-29 11:51:49 +0000120 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000121 return(ctxt->myDoc->intSubset != NULL);
122}
123
124/**
125 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000126 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000127 *
128 * Does this document has an external subset
129 *
130 * Returns 1 if true
131 */
132int
Daniel Veillard27d88741999-05-29 11:51:49 +0000133hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000134{
Daniel Veillard27d88741999-05-29 11:51:49 +0000135 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000136 return(ctxt->myDoc->extSubset != NULL);
137}
138
139/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000140 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000141 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000142 *
143 * Does this document has an internal subset
144 */
145void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000146internalSubset(void *ctx, const xmlChar *name,
147 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000148{
Daniel Veillard27d88741999-05-29 11:51:49 +0000149 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000150#ifdef DEBUG_SAX
151 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
152 name, ExternalID, SystemID);
153#endif
154 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000155 if (((ExternalID != NULL) || (SystemID != NULL)) &&
156 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
157 /*
158 * Try to fetch and parse the external subset.
159 */
160 xmlDtdPtr ret = NULL;
161 xmlParserCtxtPtr dtdCtxt;
162 xmlParserInputPtr input = NULL;
163 xmlCharEncoding enc;
164
165 dtdCtxt = xmlNewParserCtxt();
166 if (dtdCtxt == NULL) return;
167
168 /*
169 * Ask the Entity resolver to load the damn thing
170 */
171 if ((ctxt->directory != NULL) && (dtdCtxt->directory == NULL))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000172 dtdCtxt->directory = (char *) xmlStrdup(BAD_CAST ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000173
174 if ((dtdCtxt->sax != NULL) && (dtdCtxt->sax->resolveEntity != NULL))
175 input = dtdCtxt->sax->resolveEntity(dtdCtxt->userData, ExternalID,
176 SystemID);
177 if (input == NULL) {
178 xmlFreeParserCtxt(dtdCtxt);
179 return;
180 }
181
182 /*
183 * plug some encoding conversion routines here. !!!
184 */
185 xmlPushInput(dtdCtxt, input);
186 enc = xmlDetectCharEncoding(dtdCtxt->input->cur);
187 xmlSwitchEncoding(dtdCtxt, enc);
188
189 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000190 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000191 input->line = 1;
192 input->col = 1;
193 input->base = dtdCtxt->input->cur;
194 input->cur = dtdCtxt->input->cur;
195 input->free = NULL;
196
197 /*
198 * let's parse that entity knowing it's an external subset.
199 */
200 xmlParseExternalSubset(dtdCtxt, ExternalID, SystemID);
201
202 if (dtdCtxt->myDoc != NULL) {
203 if (dtdCtxt->wellFormed) {
204 ret = dtdCtxt->myDoc->intSubset;
205 dtdCtxt->myDoc->intSubset = NULL;
206 } else {
207 ret = NULL;
208 }
209 xmlFreeDoc(dtdCtxt->myDoc);
210 dtdCtxt->myDoc = NULL;
211 }
212 xmlFreeParserCtxt(dtdCtxt);
213
214 ctxt->myDoc->extSubset = ret;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000215 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000216}
217
218/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000219 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000220 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000221 * @publicId: The public ID of the entity
222 * @systemId: The system ID of the entity
223 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000224 * Special entity resolver, better left to the parser, it has
225 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000226 * The default behaviour is to NOT resolve the entities, in that case
227 * the ENTITY_REF nodes are built in the structure (and the parameter
228 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000229 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000230 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000231 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000232xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000233resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000234{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000235 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000236
237#ifdef DEBUG_SAX
238 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
239#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000240
Daniel Veillard011b63c1999-06-02 17:44:04 +0000241 if (systemId != NULL) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000242 return(xmlNewInputFromFile(ctxt, (char *) systemId));
Daniel Veillard011b63c1999-06-02 17:44:04 +0000243 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000244 return(NULL);
245}
246
Daniel Veillard97b58771998-10-20 06:14:16 +0000247/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000248 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000249 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000250 * @name: The entity name
251 *
252 * Get an entity by name
253 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000254 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000255 */
256xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000257getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000258{
Daniel Veillard27d88741999-05-29 11:51:49 +0000259 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000260 xmlEntityPtr ret;
261
262#ifdef DEBUG_SAX
263 fprintf(stderr, "SAX.getEntity(%s)\n", name);
264#endif
265
266 ret = xmlGetDocEntity(ctxt->myDoc, name);
267 return(ret);
268}
269
Daniel Veillardb05deb71999-08-10 19:04:08 +0000270/**
271 * getParameterEntity:
272 * @ctx: the user data (XML parser context)
273 * @name: The entity name
274 *
275 * Get a parameter entity by name
276 *
277 * Returns the xmlEntityPtr if found.
278 */
279xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000280getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000281{
282 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
283 xmlEntityPtr ret;
284
285#ifdef DEBUG_SAX
286 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
287#endif
288
289 ret = xmlGetParameterEntity(ctxt->myDoc, name);
290 return(ret);
291}
292
Daniel Veillard517752b1999-04-05 12:20:10 +0000293
294/**
295 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000296 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000297 * @name: the entity name
298 * @type: the entity type
299 * @publicId: The public ID of the entity
300 * @systemId: The system ID of the entity
301 * @content: the entity value (without processing).
302 *
303 * An entity definition has been parsed
304 */
305void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000306entityDecl(void *ctx, const xmlChar *name, int type,
307 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000308{
Daniel Veillard27d88741999-05-29 11:51:49 +0000309 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000310
311#ifdef DEBUG_SAX
312 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
313 name, type, publicId, systemId, content);
314#endif
315 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
316}
317
318/**
319 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000320 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000321 * @name: the attribute name
322 * @type: the attribute type
323 * @publicId: The public ID of the attribute
324 * @systemId: The system ID of the attribute
325 * @content: the attribute value (without processing).
326 *
327 * An attribute definition has been parsed
328 */
329void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000330attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *name,
331 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000332 xmlEnumerationPtr tree)
333{
Daniel Veillard27d88741999-05-29 11:51:49 +0000334 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000335 xmlAttributePtr attr;
Daniel Veillard517752b1999-04-05 12:20:10 +0000336
337#ifdef DEBUG_SAX
338 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
339 elem, name, type, def, defaultValue);
340#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000341 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
342 name, type, def, defaultValue, tree);
343 if (attr == 0) ctxt->valid = 0;
344 if (ctxt->validate && ctxt->wellFormed &&
345 ctxt->myDoc && ctxt->myDoc->intSubset)
346 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
347 attr);
Daniel Veillard517752b1999-04-05 12:20:10 +0000348}
349
350/**
351 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000352 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000353 * @name: the element name
354 * @type: the element type
355 * @publicId: The public ID of the element
356 * @systemId: The system ID of the element
357 * @content: the element value (without processing).
358 *
359 * An element definition has been parsed
360 */
361void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000362elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000363 xmlElementContentPtr content)
364{
Daniel Veillard27d88741999-05-29 11:51:49 +0000365 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000366 xmlElementPtr elem;
Daniel Veillard517752b1999-04-05 12:20:10 +0000367
368#ifdef DEBUG_SAX
369 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
370 name, type);
371#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000372
373 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
374 name, type, content);
375 if (elem == 0) ctxt->valid = 0;
376 if (ctxt->validate && ctxt->wellFormed &&
377 ctxt->myDoc && ctxt->myDoc->intSubset)
378 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000379}
380
381/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000382 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000383 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000384 * @name: The name of the notation
385 * @publicId: The public ID of the entity
386 * @systemId: The system ID of the entity
387 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000388 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000389 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000390void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000391notationDecl(void *ctx, const xmlChar *name,
392 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000393{
Daniel Veillard27d88741999-05-29 11:51:49 +0000394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000395 xmlNotationPtr nota;
396
Daniel Veillard260a68f1998-08-13 03:39:55 +0000397#ifdef DEBUG_SAX
398 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
399#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000400
401 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
402 publicId, systemId);
403 if (nota == 0) ctxt->valid = 0;
404 if (ctxt->validate && ctxt->wellFormed &&
405 ctxt->myDoc && ctxt->myDoc->intSubset)
406 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
407 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000408}
409
Daniel Veillard97b58771998-10-20 06:14:16 +0000410/**
411 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000412 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000413 * @name: The name of the entity
414 * @publicId: The public ID of the entity
415 * @systemId: The system ID of the entity
416 * @notationName: the name of the notation
417 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000418 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000419 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000420void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000421unparsedEntityDecl(void *ctx, const xmlChar *name,
422 const xmlChar *publicId, const xmlChar *systemId,
423 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000424{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000425 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000426#ifdef DEBUG_SAX
427 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
428 name, publicId, systemId, notationName);
429#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000430 if (ctxt->validate && ctxt->wellFormed &&
431 ctxt->myDoc && ctxt->myDoc->intSubset)
432 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
433 notationName);
434 xmlAddDocEntity(ctxt->myDoc, name,
435 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
436 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000437}
438
Daniel Veillard97b58771998-10-20 06:14:16 +0000439/**
440 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000441 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000442 * @loc: A SAX Locator
443 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000444 * Receive the document locator at startup, actually xmlDefaultSAXLocator
445 * Everything is available on the context, so this is useless in our case.
446 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000447void
Daniel Veillard27d88741999-05-29 11:51:49 +0000448setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000449{
Daniel Veillard27d88741999-05-29 11:51:49 +0000450 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000451#ifdef DEBUG_SAX
452 fprintf(stderr, "SAX.setDocumentLocator()\n");
453#endif
454}
455
Daniel Veillard97b58771998-10-20 06:14:16 +0000456/**
457 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000458 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000459 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000460 * called when the document start being processed.
461 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000462void
Daniel Veillard27d88741999-05-29 11:51:49 +0000463startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000464{
Daniel Veillard27d88741999-05-29 11:51:49 +0000465 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000466 xmlDocPtr doc;
467
Daniel Veillard260a68f1998-08-13 03:39:55 +0000468#ifdef DEBUG_SAX
469 fprintf(stderr, "SAX.startDocument()\n");
470#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000471 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
472 if (doc != NULL) {
473 if (ctxt->encoding != NULL)
474 doc->encoding = xmlStrdup(ctxt->encoding);
475 else
476 doc->encoding = NULL;
477 doc->standalone = ctxt->standalone;
478 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000479}
480
Daniel Veillard97b58771998-10-20 06:14:16 +0000481/**
482 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000483 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000484 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000485 * called when the document end has been detected.
486 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000487void
Daniel Veillard27d88741999-05-29 11:51:49 +0000488endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000489{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000491#ifdef DEBUG_SAX
492 fprintf(stderr, "SAX.endDocument()\n");
493#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000494 if (ctxt->validate && ctxt->wellFormed &&
495 ctxt->myDoc && ctxt->myDoc->intSubset)
496 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000497}
498
Daniel Veillard97b58771998-10-20 06:14:16 +0000499/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000500 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000501 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000502 * @name: The attribute name
503 * @value: The attribute value
504 *
505 * Handle an attribute that has been read by the parser.
506 * The default handling is to convert the attribute into an
507 * DOM subtree and past it in a new xmlAttr element added to
508 * the element.
509 */
510void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000511attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000512{
Daniel Veillard27d88741999-05-29 11:51:49 +0000513 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000514 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000515 xmlChar *name;
516 xmlChar *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000517 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000518
519/****************
520#ifdef DEBUG_SAX
521 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
522#endif
523 ****************/
524 /*
525 * Split the full name into a namespace prefix and the tag name
526 */
527 name = xmlSplitQName(fullname, &ns);
528
529 /*
530 * Check whether it's a namespace definition
531 */
532 if ((ns == NULL) &&
533 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
534 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
535 /* a default namespace definition */
536 xmlNewNs(ctxt->node, value, NULL);
537 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000538 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000539 return;
540 }
541 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
542 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
543 /* a standard namespace definition */
544 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000545 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000546 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000547 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000548 return;
549 }
550
Daniel Veillardb96e6431999-08-29 21:02:19 +0000551 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
552 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
553 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000554
Daniel Veillardb96e6431999-08-29 21:02:19 +0000555 if (ret != NULL) {
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000556 if ((ctxt->replaceEntities == 0) && (!ctxt->html))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000557 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
558 else
559 ret->val = xmlNewDocText(ctxt->myDoc, value);
560 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000561
562 if (ctxt->validate && ctxt->wellFormed &&
563 ctxt->myDoc && ctxt->myDoc->intSubset)
564 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
565 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000566 else {
567 /*
568 * when validating, the ID registration is done at the attribute
569 * validation level. Otherwise we have to do specific handling here.
570 */
571 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
572 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000573 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
574 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000575 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000576
Daniel Veillard517752b1999-04-05 12:20:10 +0000577 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000578 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000579 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000580 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000581}
582
583/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000584 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000585 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000586 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000587 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000588 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000589 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000590 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000591void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000592startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000593{
Daniel Veillard27d88741999-05-29 11:51:49 +0000594 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000595 xmlNodePtr ret;
596 xmlNodePtr parent = ctxt->node;
597 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000598 xmlChar *name;
599 xmlChar *prefix;
600 const xmlChar *att;
601 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000602 int i;
603
Daniel Veillard260a68f1998-08-13 03:39:55 +0000604#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000605 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000606#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000607
608 /*
609 * First check on validity:
610 */
611 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
612 ((ctxt->myDoc->intSubset == NULL) ||
613 ((ctxt->myDoc->intSubset->notations == NULL) &&
614 (ctxt->myDoc->intSubset->elements == NULL) &&
615 (ctxt->myDoc->intSubset->attributes == NULL) &&
616 (ctxt->myDoc->intSubset->entities == NULL)))) {
617 if (ctxt->vctxt.error != NULL) {
618 ctxt->vctxt.error(ctxt->vctxt.userData,
619 "Validation failed: no DTD found !\n");
620 }
621 ctxt->validate = 0;
622 }
623
624
Daniel Veillard517752b1999-04-05 12:20:10 +0000625 /*
626 * Split the full name into a namespace prefix and the tag name
627 */
628 name = xmlSplitQName(fullname, &prefix);
629
630
631 /*
632 * Note : the namespace resolution is deferred until the end of the
633 * attributes parsing, since local namespace can be defined as
634 * an attribute at this level.
635 */
636 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
637 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000638 if (ctxt->myDoc->root == NULL) {
639#ifdef DEBUG_SAX_TREE
640 fprintf(stderr, "Setting %s as root\n", name);
641#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000642 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000643 } else if (parent == NULL) {
644 parent = ctxt->myDoc->root;
645 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000646
647 /*
648 * We are parsing a new node.
649 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000650#ifdef DEBUG_SAX_TREE
651 fprintf(stderr, "pushing(%s)\n", name);
652#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000653 nodePush(ctxt, ret);
654
655 /*
656 * Link the child element
657 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000658 if (parent != NULL) {
659 if (parent->type == XML_ELEMENT_NODE) {
660#ifdef DEBUG_SAX_TREE
661 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
662#endif
663 xmlAddChild(parent, ret);
664 } else {
665#ifdef DEBUG_SAX_TREE
666 fprintf(stderr, "adding sibling %s to ", name);
667 xmlDebugDumpOneNode(stderr, parent, 0);
668#endif
669 xmlAddSibling(parent, ret);
670 }
671 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000672
673 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000674 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000675 */
676 if (atts != NULL) {
677 i = 0;
678 att = atts[i++];
679 value = atts[i++];
680 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000681 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
682 attribute(ctxt, att, value);
683
684 att = atts[i++];
685 value = atts[i++];
686 }
687 }
688
689 /*
690 * process all the other attributes
691 */
692 if (atts != NULL) {
693 i = 0;
694 att = atts[i++];
695 value = atts[i++];
696 while ((att != NULL) && (value != NULL)) {
697 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
698 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000699
700 /*
701 * Next ones
702 */
703 att = atts[i++];
704 value = atts[i++];
705 }
706 }
707
708 /*
709 * Search the namespace, note that since the attributes have been
710 * processed, the local namespaces are available.
711 */
712 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
713 if ((ns == NULL) && (parent != NULL))
714 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
715 xmlSetNs(ret, ns);
716
717 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000718 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000719 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000720 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000721
Daniel Veillard260a68f1998-08-13 03:39:55 +0000722}
723
Daniel Veillard97b58771998-10-20 06:14:16 +0000724/**
725 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000726 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000727 * @name: The element name
728 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000729 * called when the end of an element has been detected.
730 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000731void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000732endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000733{
Daniel Veillard27d88741999-05-29 11:51:49 +0000734 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000735 xmlParserNodeInfo node_info;
736 xmlNodePtr cur = ctxt->node;
737
Daniel Veillard260a68f1998-08-13 03:39:55 +0000738#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000739 if (name == NULL)
740 fprintf(stderr, "SAX.endElement(NULL)\n");
741 else
742 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000743#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000744
745 /* Capture end position and add node */
746 if (cur != NULL && ctxt->record_info) {
747 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
748 node_info.end_line = ctxt->input->line;
749 node_info.node = cur;
750 xmlParserAddNodeInfo(ctxt, &node_info);
751 }
752
Daniel Veillardb05deb71999-08-10 19:04:08 +0000753 if (ctxt->validate && ctxt->wellFormed &&
754 ctxt->myDoc && ctxt->myDoc->intSubset)
755 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
756 cur);
757
758
Daniel Veillard517752b1999-04-05 12:20:10 +0000759 /*
760 * end of parsing of this node.
761 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000762#ifdef DEBUG_SAX_TREE
763 fprintf(stderr, "popping(%s)\n", cur->name);
764#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000765 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000766}
767
Daniel Veillard97b58771998-10-20 06:14:16 +0000768/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000769 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000770 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000771 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000772 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000773 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000774 */
775void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000776reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000777{
Daniel Veillard27d88741999-05-29 11:51:49 +0000778 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000779 xmlNodePtr ret;
780
Daniel Veillard11e00581998-10-24 18:27:49 +0000781#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000782 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000783#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000784 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000785#ifdef DEBUG_SAX_TREE
786 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
787#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000788 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000789}
790
791/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000792 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000793 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000794 * @ch: a xmlChar string
795 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000796 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000797 * receiving some chars from the parser.
798 * Question: how much at a time ???
799 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000800void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000801characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000802{
Daniel Veillard27d88741999-05-29 11:51:49 +0000803 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000804 xmlNodePtr lastChild;
805
806#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000807 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000808#endif
809 /*
810 * Handle the data if any. If there is no child
811 * add it as content, otherwise if the last child is text,
812 * concatenate it, else create a new node of type text.
813 */
814
Daniel Veillard35008381999-10-25 13:15:52 +0000815 if (ctxt->node == NULL) {
816#ifdef DEBUG_SAX_TREE
817 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
818#endif
819 return;
820 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000821 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000822#ifdef DEBUG_SAX_TREE
823 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
824#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000825 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000826 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000827 else {
828 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000829 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000830 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000831 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832 xmlAddChild(ctxt->node, lastChild);
833 }
834 }
835}
836
Daniel Veillard97b58771998-10-20 06:14:16 +0000837/**
838 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000839 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000840 * @ch: a xmlChar string
841 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000842 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000843 * receiving some ignorable whitespaces from the parser.
844 * Question: how much at a time ???
845 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000846void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000847ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000848{
Daniel Veillard27d88741999-05-29 11:51:49 +0000849 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000850#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000851 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000852#endif
853}
854
Daniel Veillard97b58771998-10-20 06:14:16 +0000855/**
856 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000857 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000858 * @target: the target name
859 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000860 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000861 *
862 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000863 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000864void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000865processingInstruction(void *ctx, const xmlChar *target,
866 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +0000867{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000868 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
869 xmlNodePtr ret;
870 xmlNodePtr parent = ctxt->node;
871
Daniel Veillard260a68f1998-08-13 03:39:55 +0000872#ifdef DEBUG_SAX
873 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
874#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000875
876 ret = xmlNewPI(target, data);
877 if (ret == NULL) return;
878 ret->doc = ctxt->myDoc;
879 if (ctxt->myDoc->root == NULL) {
880#ifdef DEBUG_SAX_TREE
881 fprintf(stderr, "Setting PI %s as root\n", target);
882#endif
883 ctxt->myDoc->root = ret;
884 } else if (parent == NULL) {
885 parent = ctxt->myDoc->root;
886 }
887 if (parent != NULL) {
888 if (parent->type == XML_ELEMENT_NODE) {
889#ifdef DEBUG_SAX_TREE
890 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
891#endif
892 xmlAddChild(parent, ret);
893 } else {
894#ifdef DEBUG_SAX_TREE
895 fprintf(stderr, "adding PI sibling %s to ", target);
896 xmlDebugDumpOneNode(stderr, parent, 0);
897#endif
898 xmlAddSibling(parent, ret);
899 }
900 }
901
Daniel Veillard260a68f1998-08-13 03:39:55 +0000902}
903
Daniel Veillard517752b1999-04-05 12:20:10 +0000904/**
905 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000906 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000907 * @href: the namespace associated URN
908 * @prefix: the namespace prefix
909 *
910 * An old global namespace has been parsed.
911 */
912void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000913globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000914{
Daniel Veillard27d88741999-05-29 11:51:49 +0000915 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000916#ifdef DEBUG_SAX
917 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
918#endif
919 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
920}
921
922/**
923 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000924 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000925 * @name: the namespace prefix
926 *
927 * Set the current element namespace.
928 */
929void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000930setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000931{
Daniel Veillard27d88741999-05-29 11:51:49 +0000932 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000933 xmlNsPtr ns;
934 xmlNodePtr parent;
935
936#ifdef DEBUG_SAX
937 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
938#endif
939 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
940 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
941 if (ctxt->nodeNr >= 2) {
942 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
943 if (parent != NULL)
944 ns = xmlSearchNs(ctxt->myDoc, parent, name);
945 }
946 }
947 xmlSetNs(ctxt->node, ns);
948}
949
950/**
951 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000952 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000953 *
954 * Get the current element namespace.
955 */
956xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000957getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000958{
Daniel Veillard27d88741999-05-29 11:51:49 +0000959 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000960 xmlNsPtr ret;
961
962#ifdef DEBUG_SAX
963 fprintf(stderr, "SAX.getNamespace()\n");
964#endif
965 ret = ctxt->node->ns;
966 return(ret);
967}
968
969/**
970 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000971 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000972 * @namespace: the namespace to check against
973 *
974 * Check that the current element namespace is the same as the
975 * one read upon parsing.
976 */
977int
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000978checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000979{
Daniel Veillard27d88741999-05-29 11:51:49 +0000980 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000981 xmlNodePtr cur = ctxt->node;
982
983#ifdef DEBUG_SAX
984 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
985#endif
986
987 /*
988 * Check that the Name in the ETag is the same as in the STag.
989 */
990 if (namespace == NULL) {
991 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
992 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
993 ctxt->sax->error(ctxt,
994 "End tags for %s don't hold the namespace %s\n",
995 cur->name, cur->ns->prefix);
996 ctxt->wellFormed = 0;
997 }
998 } else {
999 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1000 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1001 ctxt->sax->error(ctxt,
1002 "End tags %s holds a prefix %s not used by the open tag\n",
1003 cur->name, namespace);
1004 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001005 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001006 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1007 ctxt->sax->error(ctxt,
1008 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1009 cur->name, cur->ns->prefix, namespace);
1010 ctxt->wellFormed = 0;
1011 } else
1012 return(1);
1013 }
1014 return(0);
1015}
1016
1017/**
1018 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001019 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001020 * @href: the namespace associated URN
1021 * @prefix: the namespace prefix
1022 *
1023 * A namespace has been parsed.
1024 */
1025void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001026namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001027{
Daniel Veillard27d88741999-05-29 11:51:49 +00001028 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001029#ifdef DEBUG_SAX
1030 if (prefix == NULL)
1031 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1032 else
1033 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1034#endif
1035 xmlNewNs(ctxt->node, href, prefix);
1036}
1037
1038/**
1039 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001040 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001041 * @value: the comment content
1042 *
1043 * A comment has been parsed.
1044 */
1045void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001046comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001047{
Daniel Veillard27d88741999-05-29 11:51:49 +00001048 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001049 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001050 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001051
Daniel Veillard517752b1999-04-05 12:20:10 +00001052#ifdef DEBUG_SAX
1053 fprintf(stderr, "SAX.comment(%s)\n", value);
1054#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001055 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001056 if (ret == NULL) return;
1057
1058 if (ctxt->myDoc->root == NULL) {
1059#ifdef DEBUG_SAX_TREE
1060 fprintf(stderr, "Setting comment as root\n");
1061#endif
1062 ctxt->myDoc->root = ret;
1063 } else if (parent == NULL) {
1064 parent = ctxt->myDoc->root;
1065 }
1066 if (parent != NULL) {
1067 if (parent->type == XML_ELEMENT_NODE) {
1068#ifdef DEBUG_SAX_TREE
1069 fprintf(stderr, "adding comment child to %s\n", parent->name);
1070#endif
1071 xmlAddChild(parent, ret);
1072 } else {
1073#ifdef DEBUG_SAX_TREE
1074 fprintf(stderr, "adding comment sibling to ");
1075 xmlDebugDumpOneNode(stderr, parent, 0);
1076#endif
1077 xmlAddSibling(parent, ret);
1078 }
1079 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001080}
1081
1082/**
1083 * cdataBlock:
1084 * @ctx: the user data (XML parser context)
1085 * @value: The pcdata content
1086 * @len: the block length
1087 *
1088 * called when a pcdata block has been parsed
1089 */
1090void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001091cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001092{
1093 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1094 xmlNodePtr ret;
1095
1096#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001097 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001098#endif
1099 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1100 xmlAddChild(ctxt->node, ret);
1101 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001102}
1103
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001104/*
1105 * Default handler for XML, builds the DOM tree
1106 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001107xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001108 internalSubset,
1109 isStandalone,
1110 hasInternalSubset,
1111 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001112 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001113 getEntity,
1114 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001115 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001116 attributeDecl,
1117 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001118 unparsedEntityDecl,
1119 setDocumentLocator,
1120 startDocument,
1121 endDocument,
1122 startElement,
1123 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001124 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001125 characters,
1126 ignorableWhitespace,
1127 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001128 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001129 xmlParserWarning,
1130 xmlParserError,
1131 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001132 getParameterEntity,
1133 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001134};
1135
Daniel Veillard97b58771998-10-20 06:14:16 +00001136/**
1137 * xmlDefaultSAXHandlerInit:
1138 *
1139 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001140 */
1141void
1142xmlDefaultSAXHandlerInit(void)
1143{
Daniel Veillard517752b1999-04-05 12:20:10 +00001144 xmlDefaultSAXHandler.internalSubset = internalSubset;
1145 xmlDefaultSAXHandler.isStandalone = isStandalone;
1146 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1147 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001148 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001149 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001150 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001151 xmlDefaultSAXHandler.entityDecl = entityDecl;
1152 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1153 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 xmlDefaultSAXHandler.notationDecl = notationDecl;
1155 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1156 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1157 xmlDefaultSAXHandler.startDocument = startDocument;
1158 xmlDefaultSAXHandler.endDocument = endDocument;
1159 xmlDefaultSAXHandler.startElement = startElement;
1160 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001161 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001162 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001163 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1165 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001166 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 xmlDefaultSAXHandler.warning = xmlParserWarning;
1168 xmlDefaultSAXHandler.error = xmlParserError;
1169 xmlDefaultSAXHandler.fatalError = xmlParserError;
1170}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001171
1172/*
1173 * Default handler for HTML, builds the DOM tree
1174 */
1175xmlSAXHandler htmlDefaultSAXHandler = {
1176 NULL,
1177 NULL,
1178 NULL,
1179 NULL,
1180 NULL,
1181 getEntity,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 NULL,
1187 setDocumentLocator,
1188 startDocument,
1189 endDocument,
1190 startElement,
1191 endElement,
1192 NULL,
1193 characters,
1194 ignorableWhitespace,
1195 NULL,
1196 comment,
1197 xmlParserWarning,
1198 xmlParserError,
1199 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001200 getParameterEntity,
1201 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001202};
1203
1204/**
1205 * htmlDefaultSAXHandlerInit:
1206 *
1207 * Initialize the default SAX handler
1208 */
1209void
1210htmlDefaultSAXHandlerInit(void)
1211{
1212 htmlDefaultSAXHandler.internalSubset = NULL;
1213 htmlDefaultSAXHandler.isStandalone = NULL;
1214 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1215 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1216 htmlDefaultSAXHandler.resolveEntity = NULL;
1217 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001218 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001219 htmlDefaultSAXHandler.entityDecl = NULL;
1220 htmlDefaultSAXHandler.attributeDecl = NULL;
1221 htmlDefaultSAXHandler.elementDecl = NULL;
1222 htmlDefaultSAXHandler.notationDecl = NULL;
1223 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1224 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1225 htmlDefaultSAXHandler.startDocument = startDocument;
1226 htmlDefaultSAXHandler.endDocument = endDocument;
1227 htmlDefaultSAXHandler.startElement = startElement;
1228 htmlDefaultSAXHandler.endElement = endElement;
1229 htmlDefaultSAXHandler.reference = NULL;
1230 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001231 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001232 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1233 htmlDefaultSAXHandler.processingInstruction = NULL;
1234 htmlDefaultSAXHandler.comment = comment;
1235 htmlDefaultSAXHandler.warning = xmlParserWarning;
1236 htmlDefaultSAXHandler.error = xmlParserError;
1237 htmlDefaultSAXHandler.fatalError = xmlParserError;
1238}