blob: 57443edf0be0a83004f98cf82e4d768c4ef41ae2 [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
9#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000010#include <stdlib.h>
Daniel Veillard6454aec1999-09-02 22:04:43 +000011#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000012#include "tree.h"
13#include "parser.h"
Daniel Veillard517752b1999-04-05 12:20:10 +000014#include "parserInternals.h"
15#include "valid.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000016#include "entities.h"
Daniel Veillardd109e371999-03-05 06:26:45 +000017#include "xml-error.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000018#include "debugXML.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000019
20/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000021/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000022
Daniel Veillard97b58771998-10-20 06:14:16 +000023/**
24 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000025 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000026 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000027 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000028 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000029 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000030 */
Daniel Veillard97b58771998-10-20 06:14:16 +000031const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000032getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000033{
Daniel Veillard27d88741999-05-29 11:51:49 +000034 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000035 return(NULL);
36}
37
Daniel Veillard97b58771998-10-20 06:14:16 +000038/**
39 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000040 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000041 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000042 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000043 * http://www.sgmlsource.com/dtds/memo.dtd
44 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000045 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000046 */
Daniel Veillard97b58771998-10-20 06:14:16 +000047const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000048getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000049{
Daniel Veillard27d88741999-05-29 11:51:49 +000050 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000051 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000052}
53
Daniel Veillard97b58771998-10-20 06:14:16 +000054/**
55 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000056 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000057 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000058 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000059 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000060 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000061 */
Daniel Veillard97b58771998-10-20 06:14:16 +000062int
Daniel Veillard27d88741999-05-29 11:51:49 +000063getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000064{
Daniel Veillard27d88741999-05-29 11:51:49 +000065 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000066 return(ctxt->input->line);
67}
Daniel Veillard97b58771998-10-20 06:14:16 +000068
69/**
70 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000071 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000072 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000073 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000074 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000075 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000076 */
Daniel Veillard97b58771998-10-20 06:14:16 +000077int
Daniel Veillard27d88741999-05-29 11:51:49 +000078getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000079{
Daniel Veillard27d88741999-05-29 11:51:49 +000080 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000081 return(ctxt->input->col);
82}
83
84/*
85 * The default SAX Locator.
86 */
87
88xmlSAXLocator xmlDefaultSAXLocator = {
89 getPublicId, getSystemId, getLineNumber, getColumnNumber
90};
91
Daniel Veillard97b58771998-10-20 06:14:16 +000092/**
Daniel Veillard517752b1999-04-05 12:20:10 +000093 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +000094 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +000095 *
96 * Is this document tagged standalone ?
97 *
98 * Returns 1 if true
99 */
100int
Daniel Veillard27d88741999-05-29 11:51:49 +0000101isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000102{
Daniel Veillard27d88741999-05-29 11:51:49 +0000103 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000104 return(ctxt->myDoc->standalone == 1);
105}
106
107/**
108 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000109 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000110 *
111 * Does this document has an internal subset
112 *
113 * Returns 1 if true
114 */
115int
Daniel Veillard27d88741999-05-29 11:51:49 +0000116hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000117{
Daniel Veillard27d88741999-05-29 11:51:49 +0000118 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000119 return(ctxt->myDoc->intSubset != NULL);
120}
121
122/**
123 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000124 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000125 *
126 * Does this document has an external subset
127 *
128 * Returns 1 if true
129 */
130int
Daniel Veillard27d88741999-05-29 11:51:49 +0000131hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000132{
Daniel Veillard27d88741999-05-29 11:51:49 +0000133 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000134 return(ctxt->myDoc->extSubset != NULL);
135}
136
137/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000138 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000139 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000140 *
141 * Does this document has an internal subset
142 */
143void
Daniel Veillard27d88741999-05-29 11:51:49 +0000144internalSubset(void *ctx, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000145 const CHAR *ExternalID, const CHAR *SystemID)
146{
Daniel Veillard27d88741999-05-29 11:51:49 +0000147 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000148#ifdef DEBUG_SAX
149 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
150 name, ExternalID, SystemID);
151#endif
152 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000153 if (((ExternalID != NULL) || (SystemID != NULL)) &&
154 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
155 /*
156 * Try to fetch and parse the external subset.
157 */
158 xmlDtdPtr ret = NULL;
159 xmlParserCtxtPtr dtdCtxt;
160 xmlParserInputPtr input = NULL;
161 xmlCharEncoding enc;
162
163 dtdCtxt = xmlNewParserCtxt();
164 if (dtdCtxt == NULL) return;
165
166 /*
167 * Ask the Entity resolver to load the damn thing
168 */
169 if ((ctxt->directory != NULL) && (dtdCtxt->directory == NULL))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000170 dtdCtxt->directory = (char *) xmlStrdup(BAD_CAST ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000171
172 if ((dtdCtxt->sax != NULL) && (dtdCtxt->sax->resolveEntity != NULL))
173 input = dtdCtxt->sax->resolveEntity(dtdCtxt->userData, ExternalID,
174 SystemID);
175 if (input == NULL) {
176 xmlFreeParserCtxt(dtdCtxt);
177 return;
178 }
179
180 /*
181 * plug some encoding conversion routines here. !!!
182 */
183 xmlPushInput(dtdCtxt, input);
184 enc = xmlDetectCharEncoding(dtdCtxt->input->cur);
185 xmlSwitchEncoding(dtdCtxt, enc);
186
187 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000188 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000189 input->line = 1;
190 input->col = 1;
191 input->base = dtdCtxt->input->cur;
192 input->cur = dtdCtxt->input->cur;
193 input->free = NULL;
194
195 /*
196 * let's parse that entity knowing it's an external subset.
197 */
198 xmlParseExternalSubset(dtdCtxt, ExternalID, SystemID);
199
200 if (dtdCtxt->myDoc != NULL) {
201 if (dtdCtxt->wellFormed) {
202 ret = dtdCtxt->myDoc->intSubset;
203 dtdCtxt->myDoc->intSubset = NULL;
204 } else {
205 ret = NULL;
206 }
207 xmlFreeDoc(dtdCtxt->myDoc);
208 dtdCtxt->myDoc = NULL;
209 }
210 xmlFreeParserCtxt(dtdCtxt);
211
212 ctxt->myDoc->extSubset = ret;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000213 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000214}
215
216/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000217 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000218 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000219 * @publicId: The public ID of the entity
220 * @systemId: The system ID of the entity
221 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000222 * Special entity resolver, better left to the parser, it has
223 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000224 * The default behaviour is to NOT resolve the entities, in that case
225 * the ENTITY_REF nodes are built in the structure (and the parameter
226 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000227 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000228 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000230xmlParserInputPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000231resolveEntity(void *ctx, const CHAR *publicId, const CHAR *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000232{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000233 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000234
235#ifdef DEBUG_SAX
236 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
237#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000238
Daniel Veillard517752b1999-04-05 12:20:10 +0000239 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000240 * TODO : resolveEntity, handling of http://.. or ftp://..
Daniel Veillard517752b1999-04-05 12:20:10 +0000241 */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000242 if (systemId != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000243 if (!xmlStrncmp(systemId, BAD_CAST "http://", 7)) {
244 } else if (!xmlStrncmp(systemId, BAD_CAST "ftp://", 6)) {
Daniel Veillard5233ffc1999-07-06 22:25:25 +0000245 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000246 return(xmlNewInputFromFile(ctxt, (char *) systemId));
Daniel Veillard5233ffc1999-07-06 22:25:25 +0000247 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000248 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 return(NULL);
250}
251
Daniel Veillard97b58771998-10-20 06:14:16 +0000252/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000253 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000254 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000255 * @name: The entity name
256 *
257 * Get an entity by name
258 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000259 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000260 */
261xmlEntityPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000262getEntity(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000263{
Daniel Veillard27d88741999-05-29 11:51:49 +0000264 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000265 xmlEntityPtr ret;
266
267#ifdef DEBUG_SAX
268 fprintf(stderr, "SAX.getEntity(%s)\n", name);
269#endif
270
271 ret = xmlGetDocEntity(ctxt->myDoc, name);
272 return(ret);
273}
274
Daniel Veillardb05deb71999-08-10 19:04:08 +0000275/**
276 * getParameterEntity:
277 * @ctx: the user data (XML parser context)
278 * @name: The entity name
279 *
280 * Get a parameter entity by name
281 *
282 * Returns the xmlEntityPtr if found.
283 */
284xmlEntityPtr
285getParameterEntity(void *ctx, const CHAR *name)
286{
287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
288 xmlEntityPtr ret;
289
290#ifdef DEBUG_SAX
291 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
292#endif
293
294 ret = xmlGetParameterEntity(ctxt->myDoc, name);
295 return(ret);
296}
297
Daniel Veillard517752b1999-04-05 12:20:10 +0000298
299/**
300 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000301 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000302 * @name: the entity name
303 * @type: the entity type
304 * @publicId: The public ID of the entity
305 * @systemId: The system ID of the entity
306 * @content: the entity value (without processing).
307 *
308 * An entity definition has been parsed
309 */
310void
Daniel Veillard27d88741999-05-29 11:51:49 +0000311entityDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000312 const CHAR *publicId, const CHAR *systemId, CHAR *content)
313{
Daniel Veillard27d88741999-05-29 11:51:49 +0000314 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000315
316#ifdef DEBUG_SAX
317 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
318 name, type, publicId, systemId, content);
319#endif
320 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
321}
322
323/**
324 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000325 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000326 * @name: the attribute name
327 * @type: the attribute type
328 * @publicId: The public ID of the attribute
329 * @systemId: The system ID of the attribute
330 * @content: the attribute value (without processing).
331 *
332 * An attribute definition has been parsed
333 */
334void
Daniel Veillard27d88741999-05-29 11:51:49 +0000335attributeDecl(void *ctx, const CHAR *elem, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000336 int type, int def, const CHAR *defaultValue,
337 xmlEnumerationPtr tree)
338{
Daniel Veillard27d88741999-05-29 11:51:49 +0000339 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000340 xmlAttributePtr attr;
Daniel Veillard517752b1999-04-05 12:20:10 +0000341
342#ifdef DEBUG_SAX
343 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
344 elem, name, type, def, defaultValue);
345#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000346 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
347 name, type, def, defaultValue, tree);
348 if (attr == 0) ctxt->valid = 0;
349 if (ctxt->validate && ctxt->wellFormed &&
350 ctxt->myDoc && ctxt->myDoc->intSubset)
351 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
352 attr);
Daniel Veillard517752b1999-04-05 12:20:10 +0000353}
354
355/**
356 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000357 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000358 * @name: the element name
359 * @type: the element type
360 * @publicId: The public ID of the element
361 * @systemId: The system ID of the element
362 * @content: the element value (without processing).
363 *
364 * An element definition has been parsed
365 */
366void
Daniel Veillard27d88741999-05-29 11:51:49 +0000367elementDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000368 xmlElementContentPtr content)
369{
Daniel Veillard27d88741999-05-29 11:51:49 +0000370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000371 xmlElementPtr elem;
Daniel Veillard517752b1999-04-05 12:20:10 +0000372
373#ifdef DEBUG_SAX
374 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
375 name, type);
376#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000377
378 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
379 name, type, content);
380 if (elem == 0) ctxt->valid = 0;
381 if (ctxt->validate && ctxt->wellFormed &&
382 ctxt->myDoc && ctxt->myDoc->intSubset)
383 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000384}
385
386/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000387 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000388 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000389 * @name: The name of the notation
390 * @publicId: The public ID of the entity
391 * @systemId: The system ID of the entity
392 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000394 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000395void
Daniel Veillard27d88741999-05-29 11:51:49 +0000396notationDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000397 const CHAR *publicId, const CHAR *systemId)
398{
Daniel Veillard27d88741999-05-29 11:51:49 +0000399 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000400 xmlNotationPtr nota;
401
Daniel Veillard260a68f1998-08-13 03:39:55 +0000402#ifdef DEBUG_SAX
403 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
404#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000405
406 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
407 publicId, systemId);
408 if (nota == 0) ctxt->valid = 0;
409 if (ctxt->validate && ctxt->wellFormed &&
410 ctxt->myDoc && ctxt->myDoc->intSubset)
411 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
412 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000413}
414
Daniel Veillard97b58771998-10-20 06:14:16 +0000415/**
416 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000417 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000418 * @name: The name of the entity
419 * @publicId: The public ID of the entity
420 * @systemId: The system ID of the entity
421 * @notationName: the name of the notation
422 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000424 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000425void
Daniel Veillard27d88741999-05-29 11:51:49 +0000426unparsedEntityDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000427 const CHAR *publicId, const CHAR *systemId,
428 const CHAR *notationName)
429{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000430 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000431#ifdef DEBUG_SAX
432 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
433 name, publicId, systemId, notationName);
434#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000435 if (ctxt->validate && ctxt->wellFormed &&
436 ctxt->myDoc && ctxt->myDoc->intSubset)
437 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
438 notationName);
439 xmlAddDocEntity(ctxt->myDoc, name,
440 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
441 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000442}
443
Daniel Veillard97b58771998-10-20 06:14:16 +0000444/**
445 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000446 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000447 * @loc: A SAX Locator
448 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000449 * Receive the document locator at startup, actually xmlDefaultSAXLocator
450 * Everything is available on the context, so this is useless in our case.
451 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000452void
Daniel Veillard27d88741999-05-29 11:51:49 +0000453setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000454{
Daniel Veillard27d88741999-05-29 11:51:49 +0000455 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000456#ifdef DEBUG_SAX
457 fprintf(stderr, "SAX.setDocumentLocator()\n");
458#endif
459}
460
Daniel Veillard97b58771998-10-20 06:14:16 +0000461/**
462 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000463 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000464 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000465 * called when the document start being processed.
466 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000467void
Daniel Veillard27d88741999-05-29 11:51:49 +0000468startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000469{
Daniel Veillard27d88741999-05-29 11:51:49 +0000470 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000471 xmlDocPtr doc;
472
Daniel Veillard260a68f1998-08-13 03:39:55 +0000473#ifdef DEBUG_SAX
474 fprintf(stderr, "SAX.startDocument()\n");
475#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000476 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
477 if (doc != NULL) {
478 if (ctxt->encoding != NULL)
479 doc->encoding = xmlStrdup(ctxt->encoding);
480 else
481 doc->encoding = NULL;
482 doc->standalone = ctxt->standalone;
483 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484}
485
Daniel Veillard97b58771998-10-20 06:14:16 +0000486/**
487 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000488 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000489 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000490 * called when the document end has been detected.
491 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000492void
Daniel Veillard27d88741999-05-29 11:51:49 +0000493endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000494{
Daniel Veillard27d88741999-05-29 11:51:49 +0000495 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496#ifdef DEBUG_SAX
497 fprintf(stderr, "SAX.endDocument()\n");
498#endif
499}
500
Daniel Veillard97b58771998-10-20 06:14:16 +0000501/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000502 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000503 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000504 * @name: The attribute name
505 * @value: The attribute value
506 *
507 * Handle an attribute that has been read by the parser.
508 * The default handling is to convert the attribute into an
509 * DOM subtree and past it in a new xmlAttr element added to
510 * the element.
511 */
512void
Daniel Veillard27d88741999-05-29 11:51:49 +0000513attribute(void *ctx, const CHAR *fullname, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000514{
Daniel Veillard27d88741999-05-29 11:51:49 +0000515 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000516 xmlAttrPtr ret;
517 CHAR *name;
518 CHAR *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000519 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000520
521/****************
522#ifdef DEBUG_SAX
523 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
524#endif
525 ****************/
526 /*
527 * Split the full name into a namespace prefix and the tag name
528 */
529 name = xmlSplitQName(fullname, &ns);
530
531 /*
532 * Check whether it's a namespace definition
533 */
534 if ((ns == NULL) &&
535 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
536 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
537 /* a default namespace definition */
538 xmlNewNs(ctxt->node, value, NULL);
539 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000540 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000541 return;
542 }
543 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
544 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
545 /* a standard namespace definition */
546 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000547 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000548 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000549 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000550 return;
551 }
552
Daniel Veillardb96e6431999-08-29 21:02:19 +0000553 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
554 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
555 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000556
Daniel Veillardb96e6431999-08-29 21:02:19 +0000557 if (ret != NULL) {
558 if (ctxt->replaceEntities == 0)
559 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
560 else
561 ret->val = xmlNewDocText(ctxt->myDoc, value);
562 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000563
564 if (ctxt->validate && ctxt->wellFormed &&
565 ctxt->myDoc && ctxt->myDoc->intSubset)
566 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
567 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000568 else {
569 /*
570 * when validating, the ID registration is done at the attribute
571 * validation level. Otherwise we have to do specific handling here.
572 */
573 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
574 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
575 }
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 Veillard27d88741999-05-29 11:51:49 +0000592startElement(void *ctx, const CHAR *fullname, const CHAR **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;
598 CHAR *name;
599 CHAR *prefix;
600 const CHAR *att;
601 const CHAR *value;
602
603 int i;
604
Daniel Veillard260a68f1998-08-13 03:39:55 +0000605#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000606 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000607#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000608 /*
609 * Split the full name into a namespace prefix and the tag name
610 */
611 name = xmlSplitQName(fullname, &prefix);
612
613
614 /*
615 * Note : the namespace resolution is deferred until the end of the
616 * attributes parsing, since local namespace can be defined as
617 * an attribute at this level.
618 */
619 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
620 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000621 if (ctxt->myDoc->root == NULL) {
622#ifdef DEBUG_SAX_TREE
623 fprintf(stderr, "Setting %s as root\n", name);
624#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000625 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000626 } else if (parent == NULL) {
627 parent = ctxt->myDoc->root;
628 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000629
630 /*
631 * We are parsing a new node.
632 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000633#ifdef DEBUG_SAX_TREE
634 fprintf(stderr, "pushing(%s)\n", name);
635#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000636 nodePush(ctxt, ret);
637
638 /*
639 * Link the child element
640 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000641 if (parent != NULL) {
642 if (parent->type == XML_ELEMENT_NODE) {
643#ifdef DEBUG_SAX_TREE
644 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
645#endif
646 xmlAddChild(parent, ret);
647 } else {
648#ifdef DEBUG_SAX_TREE
649 fprintf(stderr, "adding sibling %s to ", name);
650 xmlDebugDumpOneNode(stderr, parent, 0);
651#endif
652 xmlAddSibling(parent, ret);
653 }
654 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000655
656 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000657 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000658 */
659 if (atts != NULL) {
660 i = 0;
661 att = atts[i++];
662 value = atts[i++];
663 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000664 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
665 attribute(ctxt, att, value);
666
667 att = atts[i++];
668 value = atts[i++];
669 }
670 }
671
672 /*
673 * process all the other attributes
674 */
675 if (atts != NULL) {
676 i = 0;
677 att = atts[i++];
678 value = atts[i++];
679 while ((att != NULL) && (value != NULL)) {
680 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
681 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000682
683 /*
684 * Next ones
685 */
686 att = atts[i++];
687 value = atts[i++];
688 }
689 }
690
691 /*
692 * Search the namespace, note that since the attributes have been
693 * processed, the local namespaces are available.
694 */
695 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
696 if ((ns == NULL) && (parent != NULL))
697 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
698 xmlSetNs(ret, ns);
699
700 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000701 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000702 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000703 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000704
Daniel Veillard260a68f1998-08-13 03:39:55 +0000705}
706
Daniel Veillard97b58771998-10-20 06:14:16 +0000707/**
708 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000709 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000710 * @name: The element name
711 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000712 * called when the end of an element has been detected.
713 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000714void
Daniel Veillard27d88741999-05-29 11:51:49 +0000715endElement(void *ctx, const CHAR *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000716{
Daniel Veillard27d88741999-05-29 11:51:49 +0000717 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000718 xmlParserNodeInfo node_info;
719 xmlNodePtr cur = ctxt->node;
720
Daniel Veillard260a68f1998-08-13 03:39:55 +0000721#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000722 if (name == NULL)
723 fprintf(stderr, "SAX.endElement(NULL)\n");
724 else
725 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000726#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000727
728 /* Capture end position and add node */
729 if (cur != NULL && ctxt->record_info) {
730 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
731 node_info.end_line = ctxt->input->line;
732 node_info.node = cur;
733 xmlParserAddNodeInfo(ctxt, &node_info);
734 }
735
Daniel Veillardb05deb71999-08-10 19:04:08 +0000736 if (ctxt->validate && ctxt->wellFormed &&
737 ctxt->myDoc && ctxt->myDoc->intSubset)
738 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
739 cur);
740
741
Daniel Veillard517752b1999-04-05 12:20:10 +0000742 /*
743 * end of parsing of this node.
744 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000745#ifdef DEBUG_SAX_TREE
746 fprintf(stderr, "popping(%s)\n", cur->name);
747#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000748 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000749}
750
Daniel Veillard97b58771998-10-20 06:14:16 +0000751/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000752 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000753 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000754 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000755 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000756 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000757 */
758void
Daniel Veillard27d88741999-05-29 11:51:49 +0000759reference(void *ctx, const CHAR *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000760{
Daniel Veillard27d88741999-05-29 11:51:49 +0000761 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000762 xmlNodePtr ret;
763
Daniel Veillard11e00581998-10-24 18:27:49 +0000764#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000765 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000766#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000767 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000768#ifdef DEBUG_SAX_TREE
769 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
770#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000771 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000772}
773
774/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000775 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000776 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000777 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000778 * @len: the number of CHAR
779 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000780 * receiving some chars from the parser.
781 * Question: how much at a time ???
782 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000783void
Daniel Veillard27d88741999-05-29 11:51:49 +0000784characters(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000785{
Daniel Veillard27d88741999-05-29 11:51:49 +0000786 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000787 xmlNodePtr lastChild;
788
789#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000790 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000791#endif
792 /*
793 * Handle the data if any. If there is no child
794 * add it as content, otherwise if the last child is text,
795 * concatenate it, else create a new node of type text.
796 */
797
798 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000799#ifdef DEBUG_SAX_TREE
800 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
801#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000803 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000804 else {
805 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000806 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000808 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000809 xmlAddChild(ctxt->node, lastChild);
810 }
811 }
812}
813
Daniel Veillard97b58771998-10-20 06:14:16 +0000814/**
815 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000816 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000817 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000818 * @len: the number of CHAR
819 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000820 * receiving some ignorable whitespaces from the parser.
821 * Question: how much at a time ???
822 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000823void
Daniel Veillard27d88741999-05-29 11:51:49 +0000824ignorableWhitespace(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000825{
Daniel Veillard27d88741999-05-29 11:51:49 +0000826 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000827#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000828 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000829#endif
830}
831
Daniel Veillard97b58771998-10-20 06:14:16 +0000832/**
833 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000834 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000835 * @target: the target name
836 * @data: the PI data's
837 * @len: the number of CHAR
838 *
839 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000840 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000841void
Daniel Veillard27d88741999-05-29 11:51:49 +0000842processingInstruction(void *ctx, const CHAR *target,
Daniel Veillard97b58771998-10-20 06:14:16 +0000843 const CHAR *data)
844{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000845 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
846 xmlNodePtr ret;
847 xmlNodePtr parent = ctxt->node;
848
Daniel Veillard260a68f1998-08-13 03:39:55 +0000849#ifdef DEBUG_SAX
850 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
851#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000852
853 ret = xmlNewPI(target, data);
854 if (ret == NULL) return;
855 ret->doc = ctxt->myDoc;
856 if (ctxt->myDoc->root == NULL) {
857#ifdef DEBUG_SAX_TREE
858 fprintf(stderr, "Setting PI %s as root\n", target);
859#endif
860 ctxt->myDoc->root = ret;
861 } else if (parent == NULL) {
862 parent = ctxt->myDoc->root;
863 }
864 if (parent != NULL) {
865 if (parent->type == XML_ELEMENT_NODE) {
866#ifdef DEBUG_SAX_TREE
867 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
868#endif
869 xmlAddChild(parent, ret);
870 } else {
871#ifdef DEBUG_SAX_TREE
872 fprintf(stderr, "adding PI sibling %s to ", target);
873 xmlDebugDumpOneNode(stderr, parent, 0);
874#endif
875 xmlAddSibling(parent, ret);
876 }
877 }
878
Daniel Veillard260a68f1998-08-13 03:39:55 +0000879}
880
Daniel Veillard517752b1999-04-05 12:20:10 +0000881/**
882 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000883 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000884 * @href: the namespace associated URN
885 * @prefix: the namespace prefix
886 *
887 * An old global namespace has been parsed.
888 */
889void
Daniel Veillard27d88741999-05-29 11:51:49 +0000890globalNamespace(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000891{
Daniel Veillard27d88741999-05-29 11:51:49 +0000892 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000893#ifdef DEBUG_SAX
894 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
895#endif
896 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
897}
898
899/**
900 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000901 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000902 * @name: the namespace prefix
903 *
904 * Set the current element namespace.
905 */
906void
Daniel Veillard27d88741999-05-29 11:51:49 +0000907setNamespace(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000908{
Daniel Veillard27d88741999-05-29 11:51:49 +0000909 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000910 xmlNsPtr ns;
911 xmlNodePtr parent;
912
913#ifdef DEBUG_SAX
914 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
915#endif
916 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
917 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
918 if (ctxt->nodeNr >= 2) {
919 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
920 if (parent != NULL)
921 ns = xmlSearchNs(ctxt->myDoc, parent, name);
922 }
923 }
924 xmlSetNs(ctxt->node, ns);
925}
926
927/**
928 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000929 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000930 *
931 * Get the current element namespace.
932 */
933xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000934getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000935{
Daniel Veillard27d88741999-05-29 11:51:49 +0000936 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000937 xmlNsPtr ret;
938
939#ifdef DEBUG_SAX
940 fprintf(stderr, "SAX.getNamespace()\n");
941#endif
942 ret = ctxt->node->ns;
943 return(ret);
944}
945
946/**
947 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000948 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000949 * @namespace: the namespace to check against
950 *
951 * Check that the current element namespace is the same as the
952 * one read upon parsing.
953 */
954int
Daniel Veillard27d88741999-05-29 11:51:49 +0000955checkNamespace(void *ctx, CHAR *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000956{
Daniel Veillard27d88741999-05-29 11:51:49 +0000957 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000958 xmlNodePtr cur = ctxt->node;
959
960#ifdef DEBUG_SAX
961 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
962#endif
963
964 /*
965 * Check that the Name in the ETag is the same as in the STag.
966 */
967 if (namespace == NULL) {
968 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
969 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
970 ctxt->sax->error(ctxt,
971 "End tags for %s don't hold the namespace %s\n",
972 cur->name, cur->ns->prefix);
973 ctxt->wellFormed = 0;
974 }
975 } else {
976 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
977 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
978 ctxt->sax->error(ctxt,
979 "End tags %s holds a prefix %s not used by the open tag\n",
980 cur->name, namespace);
981 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000982 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +0000983 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
984 ctxt->sax->error(ctxt,
985 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
986 cur->name, cur->ns->prefix, namespace);
987 ctxt->wellFormed = 0;
988 } else
989 return(1);
990 }
991 return(0);
992}
993
994/**
995 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000996 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000997 * @href: the namespace associated URN
998 * @prefix: the namespace prefix
999 *
1000 * A namespace has been parsed.
1001 */
1002void
Daniel Veillard27d88741999-05-29 11:51:49 +00001003namespaceDecl(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001004{
Daniel Veillard27d88741999-05-29 11:51:49 +00001005 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001006#ifdef DEBUG_SAX
1007 if (prefix == NULL)
1008 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1009 else
1010 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1011#endif
1012 xmlNewNs(ctxt->node, href, prefix);
1013}
1014
1015/**
1016 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001017 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001018 * @value: the comment content
1019 *
1020 * A comment has been parsed.
1021 */
1022void
Daniel Veillard27d88741999-05-29 11:51:49 +00001023comment(void *ctx, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001024{
Daniel Veillard27d88741999-05-29 11:51:49 +00001025 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001026 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001027 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001028
Daniel Veillard517752b1999-04-05 12:20:10 +00001029#ifdef DEBUG_SAX
1030 fprintf(stderr, "SAX.comment(%s)\n", value);
1031#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001032 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001033 if (ret == NULL) return;
1034
1035 if (ctxt->myDoc->root == NULL) {
1036#ifdef DEBUG_SAX_TREE
1037 fprintf(stderr, "Setting comment as root\n");
1038#endif
1039 ctxt->myDoc->root = ret;
1040 } else if (parent == NULL) {
1041 parent = ctxt->myDoc->root;
1042 }
1043 if (parent != NULL) {
1044 if (parent->type == XML_ELEMENT_NODE) {
1045#ifdef DEBUG_SAX_TREE
1046 fprintf(stderr, "adding comment child to %s\n", parent->name);
1047#endif
1048 xmlAddChild(parent, ret);
1049 } else {
1050#ifdef DEBUG_SAX_TREE
1051 fprintf(stderr, "adding comment sibling to ");
1052 xmlDebugDumpOneNode(stderr, parent, 0);
1053#endif
1054 xmlAddSibling(parent, ret);
1055 }
1056 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001057}
1058
1059/**
1060 * cdataBlock:
1061 * @ctx: the user data (XML parser context)
1062 * @value: The pcdata content
1063 * @len: the block length
1064 *
1065 * called when a pcdata block has been parsed
1066 */
1067void
1068cdataBlock(void *ctx, const CHAR *value, int len)
1069{
1070 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1071 xmlNodePtr ret;
1072
1073#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001074 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001075#endif
1076 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1077 xmlAddChild(ctxt->node, ret);
1078 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001079}
1080
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001081/*
1082 * Default handler for XML, builds the DOM tree
1083 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001084xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001085 internalSubset,
1086 isStandalone,
1087 hasInternalSubset,
1088 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001089 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001090 getEntity,
1091 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001092 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001093 attributeDecl,
1094 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001095 unparsedEntityDecl,
1096 setDocumentLocator,
1097 startDocument,
1098 endDocument,
1099 startElement,
1100 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001101 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001102 characters,
1103 ignorableWhitespace,
1104 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001105 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001106 xmlParserWarning,
1107 xmlParserError,
1108 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001109 getParameterEntity,
1110 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111};
1112
Daniel Veillard97b58771998-10-20 06:14:16 +00001113/**
1114 * xmlDefaultSAXHandlerInit:
1115 *
1116 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001117 */
1118void
1119xmlDefaultSAXHandlerInit(void)
1120{
Daniel Veillard517752b1999-04-05 12:20:10 +00001121 xmlDefaultSAXHandler.internalSubset = internalSubset;
1122 xmlDefaultSAXHandler.isStandalone = isStandalone;
1123 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1124 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001125 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001126 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001127 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001128 xmlDefaultSAXHandler.entityDecl = entityDecl;
1129 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1130 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001131 xmlDefaultSAXHandler.notationDecl = notationDecl;
1132 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1133 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1134 xmlDefaultSAXHandler.startDocument = startDocument;
1135 xmlDefaultSAXHandler.endDocument = endDocument;
1136 xmlDefaultSAXHandler.startElement = startElement;
1137 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001138 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001139 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001140 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001141 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1142 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001143 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144 xmlDefaultSAXHandler.warning = xmlParserWarning;
1145 xmlDefaultSAXHandler.error = xmlParserError;
1146 xmlDefaultSAXHandler.fatalError = xmlParserError;
1147}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001148
1149/*
1150 * Default handler for HTML, builds the DOM tree
1151 */
1152xmlSAXHandler htmlDefaultSAXHandler = {
1153 NULL,
1154 NULL,
1155 NULL,
1156 NULL,
1157 NULL,
1158 getEntity,
1159 NULL,
1160 NULL,
1161 NULL,
1162 NULL,
1163 NULL,
1164 setDocumentLocator,
1165 startDocument,
1166 endDocument,
1167 startElement,
1168 endElement,
1169 NULL,
1170 characters,
1171 ignorableWhitespace,
1172 NULL,
1173 comment,
1174 xmlParserWarning,
1175 xmlParserError,
1176 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001177 getParameterEntity,
1178 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001179};
1180
1181/**
1182 * htmlDefaultSAXHandlerInit:
1183 *
1184 * Initialize the default SAX handler
1185 */
1186void
1187htmlDefaultSAXHandlerInit(void)
1188{
1189 htmlDefaultSAXHandler.internalSubset = NULL;
1190 htmlDefaultSAXHandler.isStandalone = NULL;
1191 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1192 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1193 htmlDefaultSAXHandler.resolveEntity = NULL;
1194 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001195 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001196 htmlDefaultSAXHandler.entityDecl = NULL;
1197 htmlDefaultSAXHandler.attributeDecl = NULL;
1198 htmlDefaultSAXHandler.elementDecl = NULL;
1199 htmlDefaultSAXHandler.notationDecl = NULL;
1200 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1201 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1202 htmlDefaultSAXHandler.startDocument = startDocument;
1203 htmlDefaultSAXHandler.endDocument = endDocument;
1204 htmlDefaultSAXHandler.startElement = startElement;
1205 htmlDefaultSAXHandler.endElement = endElement;
1206 htmlDefaultSAXHandler.reference = NULL;
1207 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001208 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001209 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1210 htmlDefaultSAXHandler.processingInstruction = NULL;
1211 htmlDefaultSAXHandler.comment = comment;
1212 htmlDefaultSAXHandler.warning = xmlParserWarning;
1213 htmlDefaultSAXHandler.error = xmlParserError;
1214 htmlDefaultSAXHandler.fatalError = xmlParserError;
1215}