blob: cfc23f1aa847336ba6ed76e00cc59d06bf891480 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
Daniel Veillard97b58771998-10-20 06:14:16 +00003 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004 * See Copyright for the status of this software.
5 *
Daniel Veillard97b58771998-10-20 06:14:16 +00006 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009
Daniel Veillard260a68f1998-08-13 03:39:55 +000010#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000011#include <stdlib.h>
Daniel Veillard6454aec1999-09-02 22:04:43 +000012#include "xmlmemory.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000013#include "tree.h"
14#include "parser.h"
Daniel Veillard517752b1999-04-05 12:20:10 +000015#include "parserInternals.h"
16#include "valid.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000017#include "entities.h"
Daniel Veillardd109e371999-03-05 06:26:45 +000018#include "xml-error.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000019#include "debugXML.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000020
21/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000022/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000023
Daniel Veillard97b58771998-10-20 06:14:16 +000024/**
25 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000026 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000027 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000028 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000029 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000030 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000031 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000032const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000033getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000034{
Daniel Veillard27d88741999-05-29 11:51:49 +000035 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000036 return(NULL);
37}
38
Daniel Veillard97b58771998-10-20 06:14:16 +000039/**
40 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000041 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000042 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000043 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000044 * http://www.sgmlsource.com/dtds/memo.dtd
45 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000046 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000047 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000048const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000049getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000050{
Daniel Veillard27d88741999-05-29 11:51:49 +000051 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000052 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000053}
54
Daniel Veillard97b58771998-10-20 06:14:16 +000055/**
56 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000057 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000058 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000059 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000060 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000061 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000062 */
Daniel Veillard97b58771998-10-20 06:14:16 +000063int
Daniel Veillard27d88741999-05-29 11:51:49 +000064getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000065{
Daniel Veillard27d88741999-05-29 11:51:49 +000066 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000067 return(ctxt->input->line);
68}
Daniel Veillard97b58771998-10-20 06:14:16 +000069
70/**
71 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000072 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000073 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000074 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000075 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000076 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000077 */
Daniel Veillard97b58771998-10-20 06:14:16 +000078int
Daniel Veillard27d88741999-05-29 11:51:49 +000079getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000080{
Daniel Veillard27d88741999-05-29 11:51:49 +000081 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000082 return(ctxt->input->col);
83}
84
85/*
86 * The default SAX Locator.
87 */
88
89xmlSAXLocator xmlDefaultSAXLocator = {
90 getPublicId, getSystemId, getLineNumber, getColumnNumber
91};
92
Daniel Veillard97b58771998-10-20 06:14:16 +000093/**
Daniel Veillard517752b1999-04-05 12:20:10 +000094 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +000095 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +000096 *
97 * Is this document tagged standalone ?
98 *
99 * Returns 1 if true
100 */
101int
Daniel Veillard27d88741999-05-29 11:51:49 +0000102isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000103{
Daniel Veillard27d88741999-05-29 11:51:49 +0000104 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000105 return(ctxt->myDoc->standalone == 1);
106}
107
108/**
109 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000110 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000111 *
112 * Does this document has an internal subset
113 *
114 * Returns 1 if true
115 */
116int
Daniel Veillard27d88741999-05-29 11:51:49 +0000117hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000118{
Daniel Veillard27d88741999-05-29 11:51:49 +0000119 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000120 return(ctxt->myDoc->intSubset != NULL);
121}
122
123/**
124 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000125 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000126 *
127 * Does this document has an external subset
128 *
129 * Returns 1 if true
130 */
131int
Daniel Veillard27d88741999-05-29 11:51:49 +0000132hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000133{
Daniel Veillard27d88741999-05-29 11:51:49 +0000134 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000135 return(ctxt->myDoc->extSubset != NULL);
136}
137
138/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000139 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000140 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000141 *
142 * Does this document has an internal subset
143 */
144void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000145internalSubset(void *ctx, const xmlChar *name,
146 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000147{
Daniel Veillard27d88741999-05-29 11:51:49 +0000148 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000149#ifdef DEBUG_SAX
150 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
151 name, ExternalID, SystemID);
152#endif
153 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000154 if (((ExternalID != NULL) || (SystemID != NULL)) &&
155 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
156 /*
157 * Try to fetch and parse the external subset.
158 */
159 xmlDtdPtr ret = NULL;
160 xmlParserCtxtPtr dtdCtxt;
161 xmlParserInputPtr input = NULL;
162 xmlCharEncoding enc;
163
164 dtdCtxt = xmlNewParserCtxt();
165 if (dtdCtxt == NULL) return;
166
167 /*
168 * Ask the Entity resolver to load the damn thing
169 */
170 if ((ctxt->directory != NULL) && (dtdCtxt->directory == NULL))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000171 dtdCtxt->directory = (char *) xmlStrdup(BAD_CAST ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000172
173 if ((dtdCtxt->sax != NULL) && (dtdCtxt->sax->resolveEntity != NULL))
174 input = dtdCtxt->sax->resolveEntity(dtdCtxt->userData, ExternalID,
175 SystemID);
176 if (input == NULL) {
177 xmlFreeParserCtxt(dtdCtxt);
178 return;
179 }
180
181 /*
182 * plug some encoding conversion routines here. !!!
183 */
184 xmlPushInput(dtdCtxt, input);
185 enc = xmlDetectCharEncoding(dtdCtxt->input->cur);
186 xmlSwitchEncoding(dtdCtxt, enc);
187
188 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000189 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000190 input->line = 1;
191 input->col = 1;
192 input->base = dtdCtxt->input->cur;
193 input->cur = dtdCtxt->input->cur;
194 input->free = NULL;
195
196 /*
197 * let's parse that entity knowing it's an external subset.
198 */
199 xmlParseExternalSubset(dtdCtxt, ExternalID, SystemID);
200
201 if (dtdCtxt->myDoc != NULL) {
202 if (dtdCtxt->wellFormed) {
203 ret = dtdCtxt->myDoc->intSubset;
204 dtdCtxt->myDoc->intSubset = NULL;
205 } else {
206 ret = NULL;
207 }
208 xmlFreeDoc(dtdCtxt->myDoc);
209 dtdCtxt->myDoc = NULL;
210 }
211 xmlFreeParserCtxt(dtdCtxt);
212
213 ctxt->myDoc->extSubset = ret;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000214 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000215}
216
217/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000218 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000219 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000220 * @publicId: The public ID of the entity
221 * @systemId: The system ID of the entity
222 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000223 * Special entity resolver, better left to the parser, it has
224 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000225 * The default behaviour is to NOT resolve the entities, in that case
226 * the ENTITY_REF nodes are built in the structure (and the parameter
227 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000228 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000229 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000230 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000231xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000232resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000233{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000234 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000235
236#ifdef DEBUG_SAX
237 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
238#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000239
Daniel Veillard011b63c1999-06-02 17:44:04 +0000240 if (systemId != NULL) {
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000241 return(xmlNewInputFromFile(ctxt, (char *) systemId));
Daniel Veillard011b63c1999-06-02 17:44:04 +0000242 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000243 return(NULL);
244}
245
Daniel Veillard97b58771998-10-20 06:14:16 +0000246/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000247 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000248 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000249 * @name: The entity name
250 *
251 * Get an entity by name
252 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000253 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000254 */
255xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000256getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000257{
Daniel Veillard27d88741999-05-29 11:51:49 +0000258 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000259 xmlEntityPtr ret;
260
261#ifdef DEBUG_SAX
262 fprintf(stderr, "SAX.getEntity(%s)\n", name);
263#endif
264
265 ret = xmlGetDocEntity(ctxt->myDoc, name);
266 return(ret);
267}
268
Daniel Veillardb05deb71999-08-10 19:04:08 +0000269/**
270 * getParameterEntity:
271 * @ctx: the user data (XML parser context)
272 * @name: The entity name
273 *
274 * Get a parameter entity by name
275 *
276 * Returns the xmlEntityPtr if found.
277 */
278xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000279getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000280{
281 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
282 xmlEntityPtr ret;
283
284#ifdef DEBUG_SAX
285 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
286#endif
287
288 ret = xmlGetParameterEntity(ctxt->myDoc, name);
289 return(ret);
290}
291
Daniel Veillard517752b1999-04-05 12:20:10 +0000292
293/**
294 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000295 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000296 * @name: the entity name
297 * @type: the entity type
298 * @publicId: The public ID of the entity
299 * @systemId: The system ID of the entity
300 * @content: the entity value (without processing).
301 *
302 * An entity definition has been parsed
303 */
304void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000305entityDecl(void *ctx, const xmlChar *name, int type,
306 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000307{
Daniel Veillard27d88741999-05-29 11:51:49 +0000308 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000309
310#ifdef DEBUG_SAX
311 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
312 name, type, publicId, systemId, content);
313#endif
314 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
315}
316
317/**
318 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000319 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000320 * @name: the attribute name
321 * @type: the attribute type
322 * @publicId: The public ID of the attribute
323 * @systemId: The system ID of the attribute
324 * @content: the attribute value (without processing).
325 *
326 * An attribute definition has been parsed
327 */
328void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000329attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *name,
330 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000331 xmlEnumerationPtr tree)
332{
Daniel Veillard27d88741999-05-29 11:51:49 +0000333 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000334 xmlAttributePtr attr;
Daniel Veillard517752b1999-04-05 12:20:10 +0000335
336#ifdef DEBUG_SAX
337 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
338 elem, name, type, def, defaultValue);
339#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000340 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
341 name, type, def, defaultValue, tree);
342 if (attr == 0) ctxt->valid = 0;
343 if (ctxt->validate && ctxt->wellFormed &&
344 ctxt->myDoc && ctxt->myDoc->intSubset)
345 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
346 attr);
Daniel Veillard517752b1999-04-05 12:20:10 +0000347}
348
349/**
350 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000351 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000352 * @name: the element name
353 * @type: the element type
354 * @publicId: The public ID of the element
355 * @systemId: The system ID of the element
356 * @content: the element value (without processing).
357 *
358 * An element definition has been parsed
359 */
360void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000361elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000362 xmlElementContentPtr content)
363{
Daniel Veillard27d88741999-05-29 11:51:49 +0000364 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000365 xmlElementPtr elem;
Daniel Veillard517752b1999-04-05 12:20:10 +0000366
367#ifdef DEBUG_SAX
368 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
369 name, type);
370#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000371
372 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
373 name, type, content);
374 if (elem == 0) ctxt->valid = 0;
375 if (ctxt->validate && ctxt->wellFormed &&
376 ctxt->myDoc && ctxt->myDoc->intSubset)
377 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000378}
379
380/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000381 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000382 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000383 * @name: The name of the notation
384 * @publicId: The public ID of the entity
385 * @systemId: The system ID of the entity
386 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000387 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000388 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000389void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000390notationDecl(void *ctx, const xmlChar *name,
391 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000392{
Daniel Veillard27d88741999-05-29 11:51:49 +0000393 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000394 xmlNotationPtr nota;
395
Daniel Veillard260a68f1998-08-13 03:39:55 +0000396#ifdef DEBUG_SAX
397 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
398#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000399
400 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
401 publicId, systemId);
402 if (nota == 0) ctxt->valid = 0;
403 if (ctxt->validate && ctxt->wellFormed &&
404 ctxt->myDoc && ctxt->myDoc->intSubset)
405 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
406 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000407}
408
Daniel Veillard97b58771998-10-20 06:14:16 +0000409/**
410 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000411 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000412 * @name: The name of the entity
413 * @publicId: The public ID of the entity
414 * @systemId: The system ID of the entity
415 * @notationName: the name of the notation
416 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000417 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000418 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000419void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000420unparsedEntityDecl(void *ctx, const xmlChar *name,
421 const xmlChar *publicId, const xmlChar *systemId,
422 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000423{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000424 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000425#ifdef DEBUG_SAX
426 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
427 name, publicId, systemId, notationName);
428#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000429 if (ctxt->validate && ctxt->wellFormed &&
430 ctxt->myDoc && ctxt->myDoc->intSubset)
431 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
432 notationName);
433 xmlAddDocEntity(ctxt->myDoc, name,
434 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
435 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000436}
437
Daniel Veillard97b58771998-10-20 06:14:16 +0000438/**
439 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000440 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000441 * @loc: A SAX Locator
442 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000443 * Receive the document locator at startup, actually xmlDefaultSAXLocator
444 * Everything is available on the context, so this is useless in our case.
445 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000446void
Daniel Veillard27d88741999-05-29 11:51:49 +0000447setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000448{
Daniel Veillard27d88741999-05-29 11:51:49 +0000449 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000450#ifdef DEBUG_SAX
451 fprintf(stderr, "SAX.setDocumentLocator()\n");
452#endif
453}
454
Daniel Veillard97b58771998-10-20 06:14:16 +0000455/**
456 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000457 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000458 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000459 * called when the document start being processed.
460 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000461void
Daniel Veillard27d88741999-05-29 11:51:49 +0000462startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000463{
Daniel Veillard27d88741999-05-29 11:51:49 +0000464 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000465 xmlDocPtr doc;
466
Daniel Veillard260a68f1998-08-13 03:39:55 +0000467#ifdef DEBUG_SAX
468 fprintf(stderr, "SAX.startDocument()\n");
469#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000470 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
471 if (doc != NULL) {
472 if (ctxt->encoding != NULL)
473 doc->encoding = xmlStrdup(ctxt->encoding);
474 else
475 doc->encoding = NULL;
476 doc->standalone = ctxt->standalone;
477 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000478}
479
Daniel Veillard97b58771998-10-20 06:14:16 +0000480/**
481 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000482 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000483 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484 * called when the document end has been detected.
485 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000486void
Daniel Veillard27d88741999-05-29 11:51:49 +0000487endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000488{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000489 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000490#ifdef DEBUG_SAX
491 fprintf(stderr, "SAX.endDocument()\n");
492#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000493 if (ctxt->validate && ctxt->wellFormed &&
494 ctxt->myDoc && ctxt->myDoc->intSubset)
495 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496}
497
Daniel Veillard97b58771998-10-20 06:14:16 +0000498/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000499 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000500 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000501 * @name: The attribute name
502 * @value: The attribute value
503 *
504 * Handle an attribute that has been read by the parser.
505 * The default handling is to convert the attribute into an
506 * DOM subtree and past it in a new xmlAttr element added to
507 * the element.
508 */
509void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000510attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000511{
Daniel Veillard27d88741999-05-29 11:51:49 +0000512 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000513 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000514 xmlChar *name;
515 xmlChar *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000516 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000517
518/****************
519#ifdef DEBUG_SAX
520 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
521#endif
522 ****************/
523 /*
524 * Split the full name into a namespace prefix and the tag name
525 */
526 name = xmlSplitQName(fullname, &ns);
527
528 /*
529 * Check whether it's a namespace definition
530 */
531 if ((ns == NULL) &&
532 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
533 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
534 /* a default namespace definition */
535 xmlNewNs(ctxt->node, value, NULL);
536 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000537 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000538 return;
539 }
540 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
541 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
542 /* a standard namespace definition */
543 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000544 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000545 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000546 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000547 return;
548 }
549
Daniel Veillardb96e6431999-08-29 21:02:19 +0000550 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
551 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
552 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000553
Daniel Veillardb96e6431999-08-29 21:02:19 +0000554 if (ret != NULL) {
Daniel Veillard7c1206f1999-10-14 09:10:25 +0000555 if ((ctxt->replaceEntities == 0) && (!ctxt->html))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000556 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
557 else
558 ret->val = xmlNewDocText(ctxt->myDoc, value);
559 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000560
561 if (ctxt->validate && ctxt->wellFormed &&
562 ctxt->myDoc && ctxt->myDoc->intSubset)
563 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
564 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000565 else {
566 /*
567 * when validating, the ID registration is done at the attribute
568 * validation level. Otherwise we have to do specific handling here.
569 */
570 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
571 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000572 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
573 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000574 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000575
Daniel Veillard517752b1999-04-05 12:20:10 +0000576 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000577 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000578 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000579 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000580}
581
582/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000583 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000584 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000585 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000586 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000587 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000588 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000589 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000590void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000591startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000592{
Daniel Veillard27d88741999-05-29 11:51:49 +0000593 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000594 xmlNodePtr ret;
595 xmlNodePtr parent = ctxt->node;
596 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000597 xmlChar *name;
598 xmlChar *prefix;
599 const xmlChar *att;
600 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000601 int i;
602
Daniel Veillard260a68f1998-08-13 03:39:55 +0000603#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000604 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000605#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000606
607 /*
608 * First check on validity:
609 */
610 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
611 ((ctxt->myDoc->intSubset == NULL) ||
612 ((ctxt->myDoc->intSubset->notations == NULL) &&
613 (ctxt->myDoc->intSubset->elements == NULL) &&
614 (ctxt->myDoc->intSubset->attributes == NULL) &&
615 (ctxt->myDoc->intSubset->entities == NULL)))) {
616 if (ctxt->vctxt.error != NULL) {
617 ctxt->vctxt.error(ctxt->vctxt.userData,
618 "Validation failed: no DTD found !\n");
619 }
620 ctxt->validate = 0;
621 }
622
623
Daniel Veillard517752b1999-04-05 12:20:10 +0000624 /*
625 * Split the full name into a namespace prefix and the tag name
626 */
627 name = xmlSplitQName(fullname, &prefix);
628
629
630 /*
631 * Note : the namespace resolution is deferred until the end of the
632 * attributes parsing, since local namespace can be defined as
633 * an attribute at this level.
634 */
635 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
636 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000637 if (ctxt->myDoc->root == NULL) {
638#ifdef DEBUG_SAX_TREE
639 fprintf(stderr, "Setting %s as root\n", name);
640#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000641 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000642 } else if (parent == NULL) {
643 parent = ctxt->myDoc->root;
644 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000645
646 /*
647 * We are parsing a new node.
648 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000649#ifdef DEBUG_SAX_TREE
650 fprintf(stderr, "pushing(%s)\n", name);
651#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000652 nodePush(ctxt, ret);
653
654 /*
655 * Link the child element
656 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000657 if (parent != NULL) {
658 if (parent->type == XML_ELEMENT_NODE) {
659#ifdef DEBUG_SAX_TREE
660 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
661#endif
662 xmlAddChild(parent, ret);
663 } else {
664#ifdef DEBUG_SAX_TREE
665 fprintf(stderr, "adding sibling %s to ", name);
666 xmlDebugDumpOneNode(stderr, parent, 0);
667#endif
668 xmlAddSibling(parent, ret);
669 }
670 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000671
672 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000673 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000674 */
675 if (atts != NULL) {
676 i = 0;
677 att = atts[i++];
678 value = atts[i++];
679 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000680 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
681 attribute(ctxt, att, value);
682
683 att = atts[i++];
684 value = atts[i++];
685 }
686 }
687
688 /*
689 * process all the other attributes
690 */
691 if (atts != NULL) {
692 i = 0;
693 att = atts[i++];
694 value = atts[i++];
695 while ((att != NULL) && (value != NULL)) {
696 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
697 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000698
699 /*
700 * Next ones
701 */
702 att = atts[i++];
703 value = atts[i++];
704 }
705 }
706
707 /*
708 * Search the namespace, note that since the attributes have been
709 * processed, the local namespaces are available.
710 */
711 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
712 if ((ns == NULL) && (parent != NULL))
713 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
714 xmlSetNs(ret, ns);
715
716 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000717 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000718 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000719 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000720
Daniel Veillard260a68f1998-08-13 03:39:55 +0000721}
722
Daniel Veillard97b58771998-10-20 06:14:16 +0000723/**
724 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000725 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000726 * @name: The element name
727 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000728 * called when the end of an element has been detected.
729 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000730void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000731endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000732{
Daniel Veillard27d88741999-05-29 11:51:49 +0000733 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000734 xmlParserNodeInfo node_info;
735 xmlNodePtr cur = ctxt->node;
736
Daniel Veillard260a68f1998-08-13 03:39:55 +0000737#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000738 if (name == NULL)
739 fprintf(stderr, "SAX.endElement(NULL)\n");
740 else
741 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000742#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000743
744 /* Capture end position and add node */
745 if (cur != NULL && ctxt->record_info) {
746 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
747 node_info.end_line = ctxt->input->line;
748 node_info.node = cur;
749 xmlParserAddNodeInfo(ctxt, &node_info);
750 }
751
Daniel Veillardb05deb71999-08-10 19:04:08 +0000752 if (ctxt->validate && ctxt->wellFormed &&
753 ctxt->myDoc && ctxt->myDoc->intSubset)
754 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
755 cur);
756
757
Daniel Veillard517752b1999-04-05 12:20:10 +0000758 /*
759 * end of parsing of this node.
760 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000761#ifdef DEBUG_SAX_TREE
762 fprintf(stderr, "popping(%s)\n", cur->name);
763#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000764 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000765}
766
Daniel Veillard97b58771998-10-20 06:14:16 +0000767/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000768 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000769 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000770 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000771 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000772 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000773 */
774void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000775reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000776{
Daniel Veillard27d88741999-05-29 11:51:49 +0000777 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000778 xmlNodePtr ret;
779
Daniel Veillard11e00581998-10-24 18:27:49 +0000780#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000781 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000782#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000783 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000784#ifdef DEBUG_SAX_TREE
785 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
786#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000787 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000788}
789
790/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000791 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000792 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000793 * @ch: a xmlChar string
794 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000795 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000796 * receiving some chars from the parser.
797 * Question: how much at a time ???
798 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000799void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000800characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000801{
Daniel Veillard27d88741999-05-29 11:51:49 +0000802 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000803 xmlNodePtr lastChild;
804
805#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000806 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000807#endif
808 /*
809 * Handle the data if any. If there is no child
810 * add it as content, otherwise if the last child is text,
811 * concatenate it, else create a new node of type text.
812 */
813
Daniel Veillard35008381999-10-25 13:15:52 +0000814 if (ctxt->node == NULL) {
815#ifdef DEBUG_SAX_TREE
816 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
817#endif
818 return;
819 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000820 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000821#ifdef DEBUG_SAX_TREE
822 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
823#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000824 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000825 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000826 else {
827 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000828 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000829 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000830 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000831 xmlAddChild(ctxt->node, lastChild);
832 }
833 }
834}
835
Daniel Veillard97b58771998-10-20 06:14:16 +0000836/**
837 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000838 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000839 * @ch: a xmlChar string
840 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000841 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000842 * receiving some ignorable whitespaces from the parser.
843 * Question: how much at a time ???
844 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000845void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000846ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000847{
Daniel Veillard27d88741999-05-29 11:51:49 +0000848 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000849#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000850 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000851#endif
852}
853
Daniel Veillard97b58771998-10-20 06:14:16 +0000854/**
855 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000856 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000857 * @target: the target name
858 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000859 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000860 *
861 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000862 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000863void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000864processingInstruction(void *ctx, const xmlChar *target,
865 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +0000866{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000867 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
868 xmlNodePtr ret;
869 xmlNodePtr parent = ctxt->node;
870
Daniel Veillard260a68f1998-08-13 03:39:55 +0000871#ifdef DEBUG_SAX
872 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
873#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000874
875 ret = xmlNewPI(target, data);
876 if (ret == NULL) return;
877 ret->doc = ctxt->myDoc;
878 if (ctxt->myDoc->root == NULL) {
879#ifdef DEBUG_SAX_TREE
880 fprintf(stderr, "Setting PI %s as root\n", target);
881#endif
882 ctxt->myDoc->root = ret;
883 } else if (parent == NULL) {
884 parent = ctxt->myDoc->root;
885 }
886 if (parent != NULL) {
887 if (parent->type == XML_ELEMENT_NODE) {
888#ifdef DEBUG_SAX_TREE
889 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
890#endif
891 xmlAddChild(parent, ret);
892 } else {
893#ifdef DEBUG_SAX_TREE
894 fprintf(stderr, "adding PI sibling %s to ", target);
895 xmlDebugDumpOneNode(stderr, parent, 0);
896#endif
897 xmlAddSibling(parent, ret);
898 }
899 }
900
Daniel Veillard260a68f1998-08-13 03:39:55 +0000901}
902
Daniel Veillard517752b1999-04-05 12:20:10 +0000903/**
904 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000905 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000906 * @href: the namespace associated URN
907 * @prefix: the namespace prefix
908 *
909 * An old global namespace has been parsed.
910 */
911void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000912globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
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#ifdef DEBUG_SAX
916 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
917#endif
918 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
919}
920
921/**
922 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000923 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000924 * @name: the namespace prefix
925 *
926 * Set the current element namespace.
927 */
928void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000929setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000930{
Daniel Veillard27d88741999-05-29 11:51:49 +0000931 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000932 xmlNsPtr ns;
933 xmlNodePtr parent;
934
935#ifdef DEBUG_SAX
936 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
937#endif
938 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
939 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
940 if (ctxt->nodeNr >= 2) {
941 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
942 if (parent != NULL)
943 ns = xmlSearchNs(ctxt->myDoc, parent, name);
944 }
945 }
946 xmlSetNs(ctxt->node, ns);
947}
948
949/**
950 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000951 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000952 *
953 * Get the current element namespace.
954 */
955xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000956getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000957{
Daniel Veillard27d88741999-05-29 11:51:49 +0000958 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000959 xmlNsPtr ret;
960
961#ifdef DEBUG_SAX
962 fprintf(stderr, "SAX.getNamespace()\n");
963#endif
964 ret = ctxt->node->ns;
965 return(ret);
966}
967
968/**
969 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000970 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000971 * @namespace: the namespace to check against
972 *
973 * Check that the current element namespace is the same as the
974 * one read upon parsing.
975 */
976int
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000977checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000978{
Daniel Veillard27d88741999-05-29 11:51:49 +0000979 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000980 xmlNodePtr cur = ctxt->node;
981
982#ifdef DEBUG_SAX
983 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
984#endif
985
986 /*
987 * Check that the Name in the ETag is the same as in the STag.
988 */
989 if (namespace == NULL) {
990 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
991 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
992 ctxt->sax->error(ctxt,
993 "End tags for %s don't hold the namespace %s\n",
994 cur->name, cur->ns->prefix);
995 ctxt->wellFormed = 0;
996 }
997 } else {
998 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
999 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1000 ctxt->sax->error(ctxt,
1001 "End tags %s holds a prefix %s not used by the open tag\n",
1002 cur->name, namespace);
1003 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001004 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001005 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1006 ctxt->sax->error(ctxt,
1007 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1008 cur->name, cur->ns->prefix, namespace);
1009 ctxt->wellFormed = 0;
1010 } else
1011 return(1);
1012 }
1013 return(0);
1014}
1015
1016/**
1017 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001018 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001019 * @href: the namespace associated URN
1020 * @prefix: the namespace prefix
1021 *
1022 * A namespace has been parsed.
1023 */
1024void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001025namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001026{
Daniel Veillard27d88741999-05-29 11:51:49 +00001027 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001028#ifdef DEBUG_SAX
1029 if (prefix == NULL)
1030 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1031 else
1032 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1033#endif
1034 xmlNewNs(ctxt->node, href, prefix);
1035}
1036
1037/**
1038 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001039 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001040 * @value: the comment content
1041 *
1042 * A comment has been parsed.
1043 */
1044void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001045comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001046{
Daniel Veillard27d88741999-05-29 11:51:49 +00001047 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001048 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001049 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001050
Daniel Veillard517752b1999-04-05 12:20:10 +00001051#ifdef DEBUG_SAX
1052 fprintf(stderr, "SAX.comment(%s)\n", value);
1053#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001054 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001055 if (ret == NULL) return;
1056
1057 if (ctxt->myDoc->root == NULL) {
1058#ifdef DEBUG_SAX_TREE
1059 fprintf(stderr, "Setting comment as root\n");
1060#endif
1061 ctxt->myDoc->root = ret;
1062 } else if (parent == NULL) {
1063 parent = ctxt->myDoc->root;
1064 }
1065 if (parent != NULL) {
1066 if (parent->type == XML_ELEMENT_NODE) {
1067#ifdef DEBUG_SAX_TREE
1068 fprintf(stderr, "adding comment child to %s\n", parent->name);
1069#endif
1070 xmlAddChild(parent, ret);
1071 } else {
1072#ifdef DEBUG_SAX_TREE
1073 fprintf(stderr, "adding comment sibling to ");
1074 xmlDebugDumpOneNode(stderr, parent, 0);
1075#endif
1076 xmlAddSibling(parent, ret);
1077 }
1078 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001079}
1080
1081/**
1082 * cdataBlock:
1083 * @ctx: the user data (XML parser context)
1084 * @value: The pcdata content
1085 * @len: the block length
1086 *
1087 * called when a pcdata block has been parsed
1088 */
1089void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001090cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001091{
1092 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1093 xmlNodePtr ret;
1094
1095#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001096 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001097#endif
1098 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1099 xmlAddChild(ctxt->node, ret);
1100 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001101}
1102
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001103/*
1104 * Default handler for XML, builds the DOM tree
1105 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001106xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001107 internalSubset,
1108 isStandalone,
1109 hasInternalSubset,
1110 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001112 getEntity,
1113 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001114 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001115 attributeDecl,
1116 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001117 unparsedEntityDecl,
1118 setDocumentLocator,
1119 startDocument,
1120 endDocument,
1121 startElement,
1122 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001123 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001124 characters,
1125 ignorableWhitespace,
1126 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001127 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001128 xmlParserWarning,
1129 xmlParserError,
1130 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001131 getParameterEntity,
1132 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001133};
1134
Daniel Veillard97b58771998-10-20 06:14:16 +00001135/**
1136 * xmlDefaultSAXHandlerInit:
1137 *
1138 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001139 */
1140void
1141xmlDefaultSAXHandlerInit(void)
1142{
Daniel Veillard517752b1999-04-05 12:20:10 +00001143 xmlDefaultSAXHandler.internalSubset = internalSubset;
1144 xmlDefaultSAXHandler.isStandalone = isStandalone;
1145 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1146 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001148 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001149 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001150 xmlDefaultSAXHandler.entityDecl = entityDecl;
1151 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1152 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001153 xmlDefaultSAXHandler.notationDecl = notationDecl;
1154 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1155 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1156 xmlDefaultSAXHandler.startDocument = startDocument;
1157 xmlDefaultSAXHandler.endDocument = endDocument;
1158 xmlDefaultSAXHandler.startElement = startElement;
1159 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001160 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001161 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001162 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001163 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1164 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001165 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001166 xmlDefaultSAXHandler.warning = xmlParserWarning;
1167 xmlDefaultSAXHandler.error = xmlParserError;
1168 xmlDefaultSAXHandler.fatalError = xmlParserError;
1169}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001170
1171/*
1172 * Default handler for HTML, builds the DOM tree
1173 */
1174xmlSAXHandler htmlDefaultSAXHandler = {
1175 NULL,
1176 NULL,
1177 NULL,
1178 NULL,
1179 NULL,
1180 getEntity,
1181 NULL,
1182 NULL,
1183 NULL,
1184 NULL,
1185 NULL,
1186 setDocumentLocator,
1187 startDocument,
1188 endDocument,
1189 startElement,
1190 endElement,
1191 NULL,
1192 characters,
1193 ignorableWhitespace,
1194 NULL,
1195 comment,
1196 xmlParserWarning,
1197 xmlParserError,
1198 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001199 getParameterEntity,
1200 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001201};
1202
1203/**
1204 * htmlDefaultSAXHandlerInit:
1205 *
1206 * Initialize the default SAX handler
1207 */
1208void
1209htmlDefaultSAXHandlerInit(void)
1210{
1211 htmlDefaultSAXHandler.internalSubset = NULL;
1212 htmlDefaultSAXHandler.isStandalone = NULL;
1213 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1214 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1215 htmlDefaultSAXHandler.resolveEntity = NULL;
1216 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001217 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001218 htmlDefaultSAXHandler.entityDecl = NULL;
1219 htmlDefaultSAXHandler.attributeDecl = NULL;
1220 htmlDefaultSAXHandler.elementDecl = NULL;
1221 htmlDefaultSAXHandler.notationDecl = NULL;
1222 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1223 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1224 htmlDefaultSAXHandler.startDocument = startDocument;
1225 htmlDefaultSAXHandler.endDocument = endDocument;
1226 htmlDefaultSAXHandler.startElement = startElement;
1227 htmlDefaultSAXHandler.endElement = endElement;
1228 htmlDefaultSAXHandler.reference = NULL;
1229 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001230 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001231 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1232 htmlDefaultSAXHandler.processingInstruction = NULL;
1233 htmlDefaultSAXHandler.comment = comment;
1234 htmlDefaultSAXHandler.warning = xmlParserWarning;
1235 htmlDefaultSAXHandler.error = xmlParserError;
1236 htmlDefaultSAXHandler.fatalError = xmlParserError;
1237}