blob: 6d95d44b18beb7bce1e1df6ea938c1b2b2e31b7e [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 Veillard5cb5ab81999-12-21 15:35:29 +0000551 if (ns != NULL)
552 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
553 else {
554 namespace = NULL;
555 }
556
Daniel Veillardb96e6431999-08-29 21:02:19 +0000557 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
558 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000559
Daniel Veillardb96e6431999-08-29 21:02:19 +0000560 if (ret != NULL) {
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000561 if ((ctxt->replaceEntities == 0) && (!ctxt->html))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000562 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
563 else
564 ret->val = xmlNewDocText(ctxt->myDoc, value);
565 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000566
567 if (ctxt->validate && ctxt->wellFormed &&
568 ctxt->myDoc && ctxt->myDoc->intSubset)
569 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
570 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000571 else {
572 /*
573 * when validating, the ID registration is done at the attribute
574 * validation level. Otherwise we have to do specific handling here.
575 */
576 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
577 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000578 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
579 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000580 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000581
Daniel Veillard517752b1999-04-05 12:20:10 +0000582 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000583 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000584 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000585 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000586}
587
588/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000589 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000590 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000591 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000592 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000593 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000594 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000595 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000596void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000597startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000598{
Daniel Veillard27d88741999-05-29 11:51:49 +0000599 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000600 xmlNodePtr ret;
601 xmlNodePtr parent = ctxt->node;
602 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000603 xmlChar *name;
604 xmlChar *prefix;
605 const xmlChar *att;
606 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000607 int i;
608
Daniel Veillard260a68f1998-08-13 03:39:55 +0000609#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000610 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000611#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000612
613 /*
614 * First check on validity:
615 */
616 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
617 ((ctxt->myDoc->intSubset == NULL) ||
618 ((ctxt->myDoc->intSubset->notations == NULL) &&
619 (ctxt->myDoc->intSubset->elements == NULL) &&
620 (ctxt->myDoc->intSubset->attributes == NULL) &&
621 (ctxt->myDoc->intSubset->entities == NULL)))) {
622 if (ctxt->vctxt.error != NULL) {
623 ctxt->vctxt.error(ctxt->vctxt.userData,
624 "Validation failed: no DTD found !\n");
625 }
626 ctxt->validate = 0;
627 }
628
629
Daniel Veillard517752b1999-04-05 12:20:10 +0000630 /*
631 * Split the full name into a namespace prefix and the tag name
632 */
633 name = xmlSplitQName(fullname, &prefix);
634
635
636 /*
637 * Note : the namespace resolution is deferred until the end of the
638 * attributes parsing, since local namespace can be defined as
639 * an attribute at this level.
640 */
641 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
642 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000643 if (ctxt->myDoc->root == NULL) {
644#ifdef DEBUG_SAX_TREE
645 fprintf(stderr, "Setting %s as root\n", name);
646#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000647 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000648 } else if (parent == NULL) {
649 parent = ctxt->myDoc->root;
650 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000651
652 /*
653 * We are parsing a new node.
654 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000655#ifdef DEBUG_SAX_TREE
656 fprintf(stderr, "pushing(%s)\n", name);
657#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000658 nodePush(ctxt, ret);
659
660 /*
661 * Link the child element
662 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000663 if (parent != NULL) {
664 if (parent->type == XML_ELEMENT_NODE) {
665#ifdef DEBUG_SAX_TREE
666 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
667#endif
668 xmlAddChild(parent, ret);
669 } else {
670#ifdef DEBUG_SAX_TREE
671 fprintf(stderr, "adding sibling %s to ", name);
672 xmlDebugDumpOneNode(stderr, parent, 0);
673#endif
674 xmlAddSibling(parent, ret);
675 }
676 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000677
678 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000679 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000680 */
681 if (atts != NULL) {
682 i = 0;
683 att = atts[i++];
684 value = atts[i++];
685 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000686 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
687 attribute(ctxt, att, value);
688
689 att = atts[i++];
690 value = atts[i++];
691 }
692 }
693
694 /*
695 * process all the other attributes
696 */
697 if (atts != NULL) {
698 i = 0;
699 att = atts[i++];
700 value = atts[i++];
701 while ((att != NULL) && (value != NULL)) {
702 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
703 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000704
705 /*
706 * Next ones
707 */
708 att = atts[i++];
709 value = atts[i++];
710 }
711 }
712
713 /*
714 * Search the namespace, note that since the attributes have been
715 * processed, the local namespaces are available.
716 */
717 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
718 if ((ns == NULL) && (parent != NULL))
719 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
720 xmlSetNs(ret, ns);
721
722 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000723 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000724 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000725 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000726
Daniel Veillard260a68f1998-08-13 03:39:55 +0000727}
728
Daniel Veillard97b58771998-10-20 06:14:16 +0000729/**
730 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000731 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000732 * @name: The element name
733 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000734 * called when the end of an element has been detected.
735 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000736void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000737endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000738{
Daniel Veillard27d88741999-05-29 11:51:49 +0000739 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000740 xmlParserNodeInfo node_info;
741 xmlNodePtr cur = ctxt->node;
742
Daniel Veillard260a68f1998-08-13 03:39:55 +0000743#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000744 if (name == NULL)
745 fprintf(stderr, "SAX.endElement(NULL)\n");
746 else
747 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000748#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000749
750 /* Capture end position and add node */
751 if (cur != NULL && ctxt->record_info) {
752 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
753 node_info.end_line = ctxt->input->line;
754 node_info.node = cur;
755 xmlParserAddNodeInfo(ctxt, &node_info);
756 }
757
Daniel Veillardb05deb71999-08-10 19:04:08 +0000758 if (ctxt->validate && ctxt->wellFormed &&
759 ctxt->myDoc && ctxt->myDoc->intSubset)
760 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
761 cur);
762
763
Daniel Veillard517752b1999-04-05 12:20:10 +0000764 /*
765 * end of parsing of this node.
766 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000767#ifdef DEBUG_SAX_TREE
768 fprintf(stderr, "popping(%s)\n", cur->name);
769#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000770 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000771}
772
Daniel Veillard97b58771998-10-20 06:14:16 +0000773/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000774 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000775 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000776 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000777 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000778 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000779 */
780void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000781reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000782{
Daniel Veillard27d88741999-05-29 11:51:49 +0000783 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000784 xmlNodePtr ret;
785
Daniel Veillard11e00581998-10-24 18:27:49 +0000786#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000787 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000788#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000789 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000790#ifdef DEBUG_SAX_TREE
791 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
792#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000793 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000794}
795
796/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000797 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000798 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000799 * @ch: a xmlChar string
800 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000801 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 * receiving some chars from the parser.
803 * Question: how much at a time ???
804 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000805void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000806characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000807{
Daniel Veillard27d88741999-05-29 11:51:49 +0000808 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000809 xmlNodePtr lastChild;
810
811#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000812 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000813#endif
814 /*
815 * Handle the data if any. If there is no child
816 * add it as content, otherwise if the last child is text,
817 * concatenate it, else create a new node of type text.
818 */
819
Daniel Veillard35008381999-10-25 13:15:52 +0000820 if (ctxt->node == NULL) {
821#ifdef DEBUG_SAX_TREE
822 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
823#endif
824 return;
825 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000826 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000827#ifdef DEBUG_SAX_TREE
828 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
829#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000830 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000831 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832 else {
833 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000834 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000835 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000836 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000837 xmlAddChild(ctxt->node, lastChild);
838 }
839 }
840}
841
Daniel Veillard97b58771998-10-20 06:14:16 +0000842/**
843 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000844 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000845 * @ch: a xmlChar string
846 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000847 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000848 * receiving some ignorable whitespaces from the parser.
849 * Question: how much at a time ???
850 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000851void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000852ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000853{
Daniel Veillard27d88741999-05-29 11:51:49 +0000854 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000855#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000856 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000857#endif
858}
859
Daniel Veillard97b58771998-10-20 06:14:16 +0000860/**
861 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000862 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000863 * @target: the target name
864 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000865 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000866 *
867 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000868 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000869void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000870processingInstruction(void *ctx, const xmlChar *target,
871 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +0000872{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000873 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
874 xmlNodePtr ret;
875 xmlNodePtr parent = ctxt->node;
876
Daniel Veillard260a68f1998-08-13 03:39:55 +0000877#ifdef DEBUG_SAX
878 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
879#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000880
881 ret = xmlNewPI(target, data);
882 if (ret == NULL) return;
883 ret->doc = ctxt->myDoc;
884 if (ctxt->myDoc->root == NULL) {
885#ifdef DEBUG_SAX_TREE
886 fprintf(stderr, "Setting PI %s as root\n", target);
887#endif
888 ctxt->myDoc->root = ret;
889 } else if (parent == NULL) {
890 parent = ctxt->myDoc->root;
891 }
892 if (parent != NULL) {
893 if (parent->type == XML_ELEMENT_NODE) {
894#ifdef DEBUG_SAX_TREE
895 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
896#endif
897 xmlAddChild(parent, ret);
898 } else {
899#ifdef DEBUG_SAX_TREE
900 fprintf(stderr, "adding PI sibling %s to ", target);
901 xmlDebugDumpOneNode(stderr, parent, 0);
902#endif
903 xmlAddSibling(parent, ret);
904 }
905 }
906
Daniel Veillard260a68f1998-08-13 03:39:55 +0000907}
908
Daniel Veillard517752b1999-04-05 12:20:10 +0000909/**
910 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000911 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000912 * @href: the namespace associated URN
913 * @prefix: the namespace prefix
914 *
915 * An old global namespace has been parsed.
916 */
917void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000918globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000919{
Daniel Veillard27d88741999-05-29 11:51:49 +0000920 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000921#ifdef DEBUG_SAX
922 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
923#endif
924 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
925}
926
927/**
928 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000929 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000930 * @name: the namespace prefix
931 *
932 * Set the current element namespace.
933 */
934void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000935setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000936{
Daniel Veillard27d88741999-05-29 11:51:49 +0000937 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000938 xmlNsPtr ns;
939 xmlNodePtr parent;
940
941#ifdef DEBUG_SAX
942 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
943#endif
944 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
945 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
946 if (ctxt->nodeNr >= 2) {
947 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
948 if (parent != NULL)
949 ns = xmlSearchNs(ctxt->myDoc, parent, name);
950 }
951 }
952 xmlSetNs(ctxt->node, ns);
953}
954
955/**
956 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000957 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000958 *
959 * Get the current element namespace.
960 */
961xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000962getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000963{
Daniel Veillard27d88741999-05-29 11:51:49 +0000964 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000965 xmlNsPtr ret;
966
967#ifdef DEBUG_SAX
968 fprintf(stderr, "SAX.getNamespace()\n");
969#endif
970 ret = ctxt->node->ns;
971 return(ret);
972}
973
974/**
975 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000976 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000977 * @namespace: the namespace to check against
978 *
979 * Check that the current element namespace is the same as the
980 * one read upon parsing.
981 */
982int
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000983checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000984{
Daniel Veillard27d88741999-05-29 11:51:49 +0000985 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000986 xmlNodePtr cur = ctxt->node;
987
988#ifdef DEBUG_SAX
989 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
990#endif
991
992 /*
993 * Check that the Name in the ETag is the same as in the STag.
994 */
995 if (namespace == NULL) {
996 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
997 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
998 ctxt->sax->error(ctxt,
999 "End tags for %s don't hold the namespace %s\n",
1000 cur->name, cur->ns->prefix);
1001 ctxt->wellFormed = 0;
1002 }
1003 } else {
1004 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1005 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1006 ctxt->sax->error(ctxt,
1007 "End tags %s holds a prefix %s not used by the open tag\n",
1008 cur->name, namespace);
1009 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001010 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001011 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1012 ctxt->sax->error(ctxt,
1013 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1014 cur->name, cur->ns->prefix, namespace);
1015 ctxt->wellFormed = 0;
1016 } else
1017 return(1);
1018 }
1019 return(0);
1020}
1021
1022/**
1023 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001024 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001025 * @href: the namespace associated URN
1026 * @prefix: the namespace prefix
1027 *
1028 * A namespace has been parsed.
1029 */
1030void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001031namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001032{
Daniel Veillard27d88741999-05-29 11:51:49 +00001033 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001034#ifdef DEBUG_SAX
1035 if (prefix == NULL)
1036 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1037 else
1038 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1039#endif
1040 xmlNewNs(ctxt->node, href, prefix);
1041}
1042
1043/**
1044 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001045 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001046 * @value: the comment content
1047 *
1048 * A comment has been parsed.
1049 */
1050void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001051comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001052{
Daniel Veillard27d88741999-05-29 11:51:49 +00001053 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001054 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001055 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001056
Daniel Veillard517752b1999-04-05 12:20:10 +00001057#ifdef DEBUG_SAX
1058 fprintf(stderr, "SAX.comment(%s)\n", value);
1059#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001060 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001061 if (ret == NULL) return;
1062
1063 if (ctxt->myDoc->root == NULL) {
1064#ifdef DEBUG_SAX_TREE
1065 fprintf(stderr, "Setting comment as root\n");
1066#endif
1067 ctxt->myDoc->root = ret;
1068 } else if (parent == NULL) {
1069 parent = ctxt->myDoc->root;
1070 }
1071 if (parent != NULL) {
1072 if (parent->type == XML_ELEMENT_NODE) {
1073#ifdef DEBUG_SAX_TREE
1074 fprintf(stderr, "adding comment child to %s\n", parent->name);
1075#endif
1076 xmlAddChild(parent, ret);
1077 } else {
1078#ifdef DEBUG_SAX_TREE
1079 fprintf(stderr, "adding comment sibling to ");
1080 xmlDebugDumpOneNode(stderr, parent, 0);
1081#endif
1082 xmlAddSibling(parent, ret);
1083 }
1084 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001085}
1086
1087/**
1088 * cdataBlock:
1089 * @ctx: the user data (XML parser context)
1090 * @value: The pcdata content
1091 * @len: the block length
1092 *
1093 * called when a pcdata block has been parsed
1094 */
1095void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001096cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001097{
1098 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1099 xmlNodePtr ret;
1100
1101#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001102 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001103#endif
1104 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1105 xmlAddChild(ctxt->node, ret);
1106 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001107}
1108
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001109/*
1110 * Default handler for XML, builds the DOM tree
1111 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001112xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001113 internalSubset,
1114 isStandalone,
1115 hasInternalSubset,
1116 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001117 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001118 getEntity,
1119 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001120 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001121 attributeDecl,
1122 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001123 unparsedEntityDecl,
1124 setDocumentLocator,
1125 startDocument,
1126 endDocument,
1127 startElement,
1128 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001129 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001130 characters,
1131 ignorableWhitespace,
1132 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001133 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001134 xmlParserWarning,
1135 xmlParserError,
1136 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001137 getParameterEntity,
1138 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001139};
1140
Daniel Veillard97b58771998-10-20 06:14:16 +00001141/**
1142 * xmlDefaultSAXHandlerInit:
1143 *
1144 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001145 */
1146void
1147xmlDefaultSAXHandlerInit(void)
1148{
Daniel Veillard517752b1999-04-05 12:20:10 +00001149 xmlDefaultSAXHandler.internalSubset = internalSubset;
1150 xmlDefaultSAXHandler.isStandalone = isStandalone;
1151 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1152 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001153 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001154 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001155 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001156 xmlDefaultSAXHandler.entityDecl = entityDecl;
1157 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1158 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001159 xmlDefaultSAXHandler.notationDecl = notationDecl;
1160 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1161 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1162 xmlDefaultSAXHandler.startDocument = startDocument;
1163 xmlDefaultSAXHandler.endDocument = endDocument;
1164 xmlDefaultSAXHandler.startElement = startElement;
1165 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001166 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001167 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001168 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001169 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1170 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001171 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001172 xmlDefaultSAXHandler.warning = xmlParserWarning;
1173 xmlDefaultSAXHandler.error = xmlParserError;
1174 xmlDefaultSAXHandler.fatalError = xmlParserError;
1175}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001176
1177/*
1178 * Default handler for HTML, builds the DOM tree
1179 */
1180xmlSAXHandler htmlDefaultSAXHandler = {
1181 NULL,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 getEntity,
1187 NULL,
1188 NULL,
1189 NULL,
1190 NULL,
1191 NULL,
1192 setDocumentLocator,
1193 startDocument,
1194 endDocument,
1195 startElement,
1196 endElement,
1197 NULL,
1198 characters,
1199 ignorableWhitespace,
1200 NULL,
1201 comment,
1202 xmlParserWarning,
1203 xmlParserError,
1204 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001205 getParameterEntity,
1206 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001207};
1208
1209/**
1210 * htmlDefaultSAXHandlerInit:
1211 *
1212 * Initialize the default SAX handler
1213 */
1214void
1215htmlDefaultSAXHandlerInit(void)
1216{
1217 htmlDefaultSAXHandler.internalSubset = NULL;
1218 htmlDefaultSAXHandler.isStandalone = NULL;
1219 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1220 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1221 htmlDefaultSAXHandler.resolveEntity = NULL;
1222 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001223 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001224 htmlDefaultSAXHandler.entityDecl = NULL;
1225 htmlDefaultSAXHandler.attributeDecl = NULL;
1226 htmlDefaultSAXHandler.elementDecl = NULL;
1227 htmlDefaultSAXHandler.notationDecl = NULL;
1228 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1229 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1230 htmlDefaultSAXHandler.startDocument = startDocument;
1231 htmlDefaultSAXHandler.endDocument = endDocument;
1232 htmlDefaultSAXHandler.startElement = startElement;
1233 htmlDefaultSAXHandler.endElement = endElement;
1234 htmlDefaultSAXHandler.reference = NULL;
1235 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001236 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001237 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1238 htmlDefaultSAXHandler.processingInstruction = NULL;
1239 htmlDefaultSAXHandler.comment = comment;
1240 htmlDefaultSAXHandler.warning = xmlParserWarning;
1241 htmlDefaultSAXHandler.error = xmlParserError;
1242 htmlDefaultSAXHandler.fatalError = xmlParserError;
1243}