blob: d0c08fed3383d33576ce33bad34f21193692b67f [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 Veillardc08a2c61999-09-08 21:35:25 +0000495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496#ifdef DEBUG_SAX
497 fprintf(stderr, "SAX.endDocument()\n");
498#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000499 if (ctxt->validate && ctxt->wellFormed &&
500 ctxt->myDoc && ctxt->myDoc->intSubset)
501 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000502}
503
Daniel Veillard97b58771998-10-20 06:14:16 +0000504/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000505 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000506 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000507 * @name: The attribute name
508 * @value: The attribute value
509 *
510 * Handle an attribute that has been read by the parser.
511 * The default handling is to convert the attribute into an
512 * DOM subtree and past it in a new xmlAttr element added to
513 * the element.
514 */
515void
Daniel Veillard27d88741999-05-29 11:51:49 +0000516attribute(void *ctx, const CHAR *fullname, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000517{
Daniel Veillard27d88741999-05-29 11:51:49 +0000518 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000519 xmlAttrPtr ret;
520 CHAR *name;
521 CHAR *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000522 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000523
524/****************
525#ifdef DEBUG_SAX
526 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
527#endif
528 ****************/
529 /*
530 * Split the full name into a namespace prefix and the tag name
531 */
532 name = xmlSplitQName(fullname, &ns);
533
534 /*
535 * Check whether it's a namespace definition
536 */
537 if ((ns == NULL) &&
538 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
539 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
540 /* a default namespace definition */
541 xmlNewNs(ctxt->node, value, NULL);
542 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000543 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000544 return;
545 }
546 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
547 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
548 /* a standard namespace definition */
549 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000550 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000551 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000552 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000553 return;
554 }
555
Daniel Veillardb96e6431999-08-29 21:02:19 +0000556 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
557 /* !!!!!! <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) {
561 if (ctxt->replaceEntities == 0)
562 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 Veillard27d88741999-05-29 11:51:49 +0000597startElement(void *ctx, const CHAR *fullname, const CHAR **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;
603 CHAR *name;
604 CHAR *prefix;
605 const CHAR *att;
606 const CHAR *value;
607
608 int i;
609
Daniel Veillard260a68f1998-08-13 03:39:55 +0000610#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000611 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000612#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000613 /*
614 * Split the full name into a namespace prefix and the tag name
615 */
616 name = xmlSplitQName(fullname, &prefix);
617
618
619 /*
620 * Note : the namespace resolution is deferred until the end of the
621 * attributes parsing, since local namespace can be defined as
622 * an attribute at this level.
623 */
624 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
625 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000626 if (ctxt->myDoc->root == NULL) {
627#ifdef DEBUG_SAX_TREE
628 fprintf(stderr, "Setting %s as root\n", name);
629#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000630 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000631 } else if (parent == NULL) {
632 parent = ctxt->myDoc->root;
633 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000634
635 /*
636 * We are parsing a new node.
637 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000638#ifdef DEBUG_SAX_TREE
639 fprintf(stderr, "pushing(%s)\n", name);
640#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000641 nodePush(ctxt, ret);
642
643 /*
644 * Link the child element
645 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000646 if (parent != NULL) {
647 if (parent->type == XML_ELEMENT_NODE) {
648#ifdef DEBUG_SAX_TREE
649 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
650#endif
651 xmlAddChild(parent, ret);
652 } else {
653#ifdef DEBUG_SAX_TREE
654 fprintf(stderr, "adding sibling %s to ", name);
655 xmlDebugDumpOneNode(stderr, parent, 0);
656#endif
657 xmlAddSibling(parent, ret);
658 }
659 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000660
661 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000662 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000663 */
664 if (atts != NULL) {
665 i = 0;
666 att = atts[i++];
667 value = atts[i++];
668 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000669 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
670 attribute(ctxt, att, value);
671
672 att = atts[i++];
673 value = atts[i++];
674 }
675 }
676
677 /*
678 * process all the other attributes
679 */
680 if (atts != NULL) {
681 i = 0;
682 att = atts[i++];
683 value = atts[i++];
684 while ((att != NULL) && (value != NULL)) {
685 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
686 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000687
688 /*
689 * Next ones
690 */
691 att = atts[i++];
692 value = atts[i++];
693 }
694 }
695
696 /*
697 * Search the namespace, note that since the attributes have been
698 * processed, the local namespaces are available.
699 */
700 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
701 if ((ns == NULL) && (parent != NULL))
702 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
703 xmlSetNs(ret, ns);
704
705 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000706 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000707 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000708 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000709
Daniel Veillard260a68f1998-08-13 03:39:55 +0000710}
711
Daniel Veillard97b58771998-10-20 06:14:16 +0000712/**
713 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000714 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000715 * @name: The element name
716 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000717 * called when the end of an element has been detected.
718 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000719void
Daniel Veillard27d88741999-05-29 11:51:49 +0000720endElement(void *ctx, const CHAR *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000721{
Daniel Veillard27d88741999-05-29 11:51:49 +0000722 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000723 xmlParserNodeInfo node_info;
724 xmlNodePtr cur = ctxt->node;
725
Daniel Veillard260a68f1998-08-13 03:39:55 +0000726#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000727 if (name == NULL)
728 fprintf(stderr, "SAX.endElement(NULL)\n");
729 else
730 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000731#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000732
733 /* Capture end position and add node */
734 if (cur != NULL && ctxt->record_info) {
735 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
736 node_info.end_line = ctxt->input->line;
737 node_info.node = cur;
738 xmlParserAddNodeInfo(ctxt, &node_info);
739 }
740
Daniel Veillardb05deb71999-08-10 19:04:08 +0000741 if (ctxt->validate && ctxt->wellFormed &&
742 ctxt->myDoc && ctxt->myDoc->intSubset)
743 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
744 cur);
745
746
Daniel Veillard517752b1999-04-05 12:20:10 +0000747 /*
748 * end of parsing of this node.
749 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000750#ifdef DEBUG_SAX_TREE
751 fprintf(stderr, "popping(%s)\n", cur->name);
752#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000753 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000754}
755
Daniel Veillard97b58771998-10-20 06:14:16 +0000756/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000757 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000758 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000759 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000760 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000761 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000762 */
763void
Daniel Veillard27d88741999-05-29 11:51:49 +0000764reference(void *ctx, const CHAR *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000765{
Daniel Veillard27d88741999-05-29 11:51:49 +0000766 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000767 xmlNodePtr ret;
768
Daniel Veillard11e00581998-10-24 18:27:49 +0000769#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000770 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000771#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000772 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000773#ifdef DEBUG_SAX_TREE
774 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
775#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000776 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000777}
778
779/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000780 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000781 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000782 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000783 * @len: the number of CHAR
784 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000785 * receiving some chars from the parser.
786 * Question: how much at a time ???
787 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000788void
Daniel Veillard27d88741999-05-29 11:51:49 +0000789characters(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000790{
Daniel Veillard27d88741999-05-29 11:51:49 +0000791 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000792 xmlNodePtr lastChild;
793
794#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000795 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000796#endif
797 /*
798 * Handle the data if any. If there is no child
799 * add it as content, otherwise if the last child is text,
800 * concatenate it, else create a new node of type text.
801 */
802
803 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000804#ifdef DEBUG_SAX_TREE
805 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
806#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000808 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000809 else {
810 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000811 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000812 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000813 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000814 xmlAddChild(ctxt->node, lastChild);
815 }
816 }
817}
818
Daniel Veillard97b58771998-10-20 06:14:16 +0000819/**
820 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000821 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000822 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000823 * @len: the number of CHAR
824 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000825 * receiving some ignorable whitespaces from the parser.
826 * Question: how much at a time ???
827 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000828void
Daniel Veillard27d88741999-05-29 11:51:49 +0000829ignorableWhitespace(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000830{
Daniel Veillard27d88741999-05-29 11:51:49 +0000831 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000833 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000834#endif
835}
836
Daniel Veillard97b58771998-10-20 06:14:16 +0000837/**
838 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000839 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000840 * @target: the target name
841 * @data: the PI data's
842 * @len: the number of CHAR
843 *
844 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000845 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000846void
Daniel Veillard27d88741999-05-29 11:51:49 +0000847processingInstruction(void *ctx, const CHAR *target,
Daniel Veillard97b58771998-10-20 06:14:16 +0000848 const CHAR *data)
849{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000850 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
851 xmlNodePtr ret;
852 xmlNodePtr parent = ctxt->node;
853
Daniel Veillard260a68f1998-08-13 03:39:55 +0000854#ifdef DEBUG_SAX
855 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
856#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000857
858 ret = xmlNewPI(target, data);
859 if (ret == NULL) return;
860 ret->doc = ctxt->myDoc;
861 if (ctxt->myDoc->root == NULL) {
862#ifdef DEBUG_SAX_TREE
863 fprintf(stderr, "Setting PI %s as root\n", target);
864#endif
865 ctxt->myDoc->root = ret;
866 } else if (parent == NULL) {
867 parent = ctxt->myDoc->root;
868 }
869 if (parent != NULL) {
870 if (parent->type == XML_ELEMENT_NODE) {
871#ifdef DEBUG_SAX_TREE
872 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
873#endif
874 xmlAddChild(parent, ret);
875 } else {
876#ifdef DEBUG_SAX_TREE
877 fprintf(stderr, "adding PI sibling %s to ", target);
878 xmlDebugDumpOneNode(stderr, parent, 0);
879#endif
880 xmlAddSibling(parent, ret);
881 }
882 }
883
Daniel Veillard260a68f1998-08-13 03:39:55 +0000884}
885
Daniel Veillard517752b1999-04-05 12:20:10 +0000886/**
887 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000888 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000889 * @href: the namespace associated URN
890 * @prefix: the namespace prefix
891 *
892 * An old global namespace has been parsed.
893 */
894void
Daniel Veillard27d88741999-05-29 11:51:49 +0000895globalNamespace(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000896{
Daniel Veillard27d88741999-05-29 11:51:49 +0000897 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000898#ifdef DEBUG_SAX
899 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
900#endif
901 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
902}
903
904/**
905 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000906 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000907 * @name: the namespace prefix
908 *
909 * Set the current element namespace.
910 */
911void
Daniel Veillard27d88741999-05-29 11:51:49 +0000912setNamespace(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000913{
Daniel Veillard27d88741999-05-29 11:51:49 +0000914 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000915 xmlNsPtr ns;
916 xmlNodePtr parent;
917
918#ifdef DEBUG_SAX
919 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
920#endif
921 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
922 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
923 if (ctxt->nodeNr >= 2) {
924 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
925 if (parent != NULL)
926 ns = xmlSearchNs(ctxt->myDoc, parent, name);
927 }
928 }
929 xmlSetNs(ctxt->node, ns);
930}
931
932/**
933 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000934 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000935 *
936 * Get the current element namespace.
937 */
938xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000939getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000940{
Daniel Veillard27d88741999-05-29 11:51:49 +0000941 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000942 xmlNsPtr ret;
943
944#ifdef DEBUG_SAX
945 fprintf(stderr, "SAX.getNamespace()\n");
946#endif
947 ret = ctxt->node->ns;
948 return(ret);
949}
950
951/**
952 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000953 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000954 * @namespace: the namespace to check against
955 *
956 * Check that the current element namespace is the same as the
957 * one read upon parsing.
958 */
959int
Daniel Veillard27d88741999-05-29 11:51:49 +0000960checkNamespace(void *ctx, CHAR *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000961{
Daniel Veillard27d88741999-05-29 11:51:49 +0000962 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000963 xmlNodePtr cur = ctxt->node;
964
965#ifdef DEBUG_SAX
966 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
967#endif
968
969 /*
970 * Check that the Name in the ETag is the same as in the STag.
971 */
972 if (namespace == NULL) {
973 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
974 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
975 ctxt->sax->error(ctxt,
976 "End tags for %s don't hold the namespace %s\n",
977 cur->name, cur->ns->prefix);
978 ctxt->wellFormed = 0;
979 }
980 } else {
981 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
982 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
983 ctxt->sax->error(ctxt,
984 "End tags %s holds a prefix %s not used by the open tag\n",
985 cur->name, namespace);
986 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000987 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +0000988 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
989 ctxt->sax->error(ctxt,
990 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
991 cur->name, cur->ns->prefix, namespace);
992 ctxt->wellFormed = 0;
993 } else
994 return(1);
995 }
996 return(0);
997}
998
999/**
1000 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001001 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001002 * @href: the namespace associated URN
1003 * @prefix: the namespace prefix
1004 *
1005 * A namespace has been parsed.
1006 */
1007void
Daniel Veillard27d88741999-05-29 11:51:49 +00001008namespaceDecl(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001009{
Daniel Veillard27d88741999-05-29 11:51:49 +00001010 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001011#ifdef DEBUG_SAX
1012 if (prefix == NULL)
1013 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1014 else
1015 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1016#endif
1017 xmlNewNs(ctxt->node, href, prefix);
1018}
1019
1020/**
1021 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001022 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001023 * @value: the comment content
1024 *
1025 * A comment has been parsed.
1026 */
1027void
Daniel Veillard27d88741999-05-29 11:51:49 +00001028comment(void *ctx, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001029{
Daniel Veillard27d88741999-05-29 11:51:49 +00001030 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001031 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001032 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001033
Daniel Veillard517752b1999-04-05 12:20:10 +00001034#ifdef DEBUG_SAX
1035 fprintf(stderr, "SAX.comment(%s)\n", value);
1036#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001037 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001038 if (ret == NULL) return;
1039
1040 if (ctxt->myDoc->root == NULL) {
1041#ifdef DEBUG_SAX_TREE
1042 fprintf(stderr, "Setting comment as root\n");
1043#endif
1044 ctxt->myDoc->root = ret;
1045 } else if (parent == NULL) {
1046 parent = ctxt->myDoc->root;
1047 }
1048 if (parent != NULL) {
1049 if (parent->type == XML_ELEMENT_NODE) {
1050#ifdef DEBUG_SAX_TREE
1051 fprintf(stderr, "adding comment child to %s\n", parent->name);
1052#endif
1053 xmlAddChild(parent, ret);
1054 } else {
1055#ifdef DEBUG_SAX_TREE
1056 fprintf(stderr, "adding comment sibling to ");
1057 xmlDebugDumpOneNode(stderr, parent, 0);
1058#endif
1059 xmlAddSibling(parent, ret);
1060 }
1061 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001062}
1063
1064/**
1065 * cdataBlock:
1066 * @ctx: the user data (XML parser context)
1067 * @value: The pcdata content
1068 * @len: the block length
1069 *
1070 * called when a pcdata block has been parsed
1071 */
1072void
1073cdataBlock(void *ctx, const CHAR *value, int len)
1074{
1075 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1076 xmlNodePtr ret;
1077
1078#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001079 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001080#endif
1081 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1082 xmlAddChild(ctxt->node, ret);
1083 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001084}
1085
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001086/*
1087 * Default handler for XML, builds the DOM tree
1088 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001089xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001090 internalSubset,
1091 isStandalone,
1092 hasInternalSubset,
1093 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001094 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001095 getEntity,
1096 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001097 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001098 attributeDecl,
1099 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001100 unparsedEntityDecl,
1101 setDocumentLocator,
1102 startDocument,
1103 endDocument,
1104 startElement,
1105 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001106 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001107 characters,
1108 ignorableWhitespace,
1109 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001110 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111 xmlParserWarning,
1112 xmlParserError,
1113 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001114 getParameterEntity,
1115 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001116};
1117
Daniel Veillard97b58771998-10-20 06:14:16 +00001118/**
1119 * xmlDefaultSAXHandlerInit:
1120 *
1121 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001122 */
1123void
1124xmlDefaultSAXHandlerInit(void)
1125{
Daniel Veillard517752b1999-04-05 12:20:10 +00001126 xmlDefaultSAXHandler.internalSubset = internalSubset;
1127 xmlDefaultSAXHandler.isStandalone = isStandalone;
1128 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1129 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001130 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001131 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001132 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001133 xmlDefaultSAXHandler.entityDecl = entityDecl;
1134 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1135 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001136 xmlDefaultSAXHandler.notationDecl = notationDecl;
1137 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1138 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1139 xmlDefaultSAXHandler.startDocument = startDocument;
1140 xmlDefaultSAXHandler.endDocument = endDocument;
1141 xmlDefaultSAXHandler.startElement = startElement;
1142 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001143 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001145 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001146 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1147 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001148 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149 xmlDefaultSAXHandler.warning = xmlParserWarning;
1150 xmlDefaultSAXHandler.error = xmlParserError;
1151 xmlDefaultSAXHandler.fatalError = xmlParserError;
1152}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001153
1154/*
1155 * Default handler for HTML, builds the DOM tree
1156 */
1157xmlSAXHandler htmlDefaultSAXHandler = {
1158 NULL,
1159 NULL,
1160 NULL,
1161 NULL,
1162 NULL,
1163 getEntity,
1164 NULL,
1165 NULL,
1166 NULL,
1167 NULL,
1168 NULL,
1169 setDocumentLocator,
1170 startDocument,
1171 endDocument,
1172 startElement,
1173 endElement,
1174 NULL,
1175 characters,
1176 ignorableWhitespace,
1177 NULL,
1178 comment,
1179 xmlParserWarning,
1180 xmlParserError,
1181 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001182 getParameterEntity,
1183 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001184};
1185
1186/**
1187 * htmlDefaultSAXHandlerInit:
1188 *
1189 * Initialize the default SAX handler
1190 */
1191void
1192htmlDefaultSAXHandlerInit(void)
1193{
1194 htmlDefaultSAXHandler.internalSubset = NULL;
1195 htmlDefaultSAXHandler.isStandalone = NULL;
1196 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1197 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1198 htmlDefaultSAXHandler.resolveEntity = NULL;
1199 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001200 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001201 htmlDefaultSAXHandler.entityDecl = NULL;
1202 htmlDefaultSAXHandler.attributeDecl = NULL;
1203 htmlDefaultSAXHandler.elementDecl = NULL;
1204 htmlDefaultSAXHandler.notationDecl = NULL;
1205 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1206 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1207 htmlDefaultSAXHandler.startDocument = startDocument;
1208 htmlDefaultSAXHandler.endDocument = endDocument;
1209 htmlDefaultSAXHandler.startElement = startElement;
1210 htmlDefaultSAXHandler.endElement = endElement;
1211 htmlDefaultSAXHandler.reference = NULL;
1212 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001213 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001214 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1215 htmlDefaultSAXHandler.processingInstruction = NULL;
1216 htmlDefaultSAXHandler.comment = comment;
1217 htmlDefaultSAXHandler.warning = xmlParserWarning;
1218 htmlDefaultSAXHandler.error = xmlParserError;
1219 htmlDefaultSAXHandler.fatalError = xmlParserError;
1220}