blob: e0c50660decd890148651e786d720fbd6aae8687 [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) {
555 if (ctxt->replaceEntities == 0)
556 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
814 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000815#ifdef DEBUG_SAX_TREE
816 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
817#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000819 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000820 else {
821 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000822 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000823 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000824 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000825 xmlAddChild(ctxt->node, lastChild);
826 }
827 }
828}
829
Daniel Veillard97b58771998-10-20 06:14:16 +0000830/**
831 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000832 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000833 * @ch: a xmlChar string
834 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000835 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000836 * receiving some ignorable whitespaces from the parser.
837 * Question: how much at a time ???
838 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000839void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000840ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000841{
Daniel Veillard27d88741999-05-29 11:51:49 +0000842 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000843#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000844 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000845#endif
846}
847
Daniel Veillard97b58771998-10-20 06:14:16 +0000848/**
849 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000850 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000851 * @target: the target name
852 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000853 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000854 *
855 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000856 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000857void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000858processingInstruction(void *ctx, const xmlChar *target,
859 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +0000860{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000861 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
862 xmlNodePtr ret;
863 xmlNodePtr parent = ctxt->node;
864
Daniel Veillard260a68f1998-08-13 03:39:55 +0000865#ifdef DEBUG_SAX
866 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
867#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000868
869 ret = xmlNewPI(target, data);
870 if (ret == NULL) return;
871 ret->doc = ctxt->myDoc;
872 if (ctxt->myDoc->root == NULL) {
873#ifdef DEBUG_SAX_TREE
874 fprintf(stderr, "Setting PI %s as root\n", target);
875#endif
876 ctxt->myDoc->root = ret;
877 } else if (parent == NULL) {
878 parent = ctxt->myDoc->root;
879 }
880 if (parent != NULL) {
881 if (parent->type == XML_ELEMENT_NODE) {
882#ifdef DEBUG_SAX_TREE
883 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
884#endif
885 xmlAddChild(parent, ret);
886 } else {
887#ifdef DEBUG_SAX_TREE
888 fprintf(stderr, "adding PI sibling %s to ", target);
889 xmlDebugDumpOneNode(stderr, parent, 0);
890#endif
891 xmlAddSibling(parent, ret);
892 }
893 }
894
Daniel Veillard260a68f1998-08-13 03:39:55 +0000895}
896
Daniel Veillard517752b1999-04-05 12:20:10 +0000897/**
898 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000899 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000900 * @href: the namespace associated URN
901 * @prefix: the namespace prefix
902 *
903 * An old global namespace has been parsed.
904 */
905void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000906globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000907{
Daniel Veillard27d88741999-05-29 11:51:49 +0000908 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000909#ifdef DEBUG_SAX
910 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
911#endif
912 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
913}
914
915/**
916 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000917 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000918 * @name: the namespace prefix
919 *
920 * Set the current element namespace.
921 */
922void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000923setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000924{
Daniel Veillard27d88741999-05-29 11:51:49 +0000925 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000926 xmlNsPtr ns;
927 xmlNodePtr parent;
928
929#ifdef DEBUG_SAX
930 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
931#endif
932 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
933 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
934 if (ctxt->nodeNr >= 2) {
935 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
936 if (parent != NULL)
937 ns = xmlSearchNs(ctxt->myDoc, parent, name);
938 }
939 }
940 xmlSetNs(ctxt->node, ns);
941}
942
943/**
944 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000945 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000946 *
947 * Get the current element namespace.
948 */
949xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000950getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000951{
Daniel Veillard27d88741999-05-29 11:51:49 +0000952 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000953 xmlNsPtr ret;
954
955#ifdef DEBUG_SAX
956 fprintf(stderr, "SAX.getNamespace()\n");
957#endif
958 ret = ctxt->node->ns;
959 return(ret);
960}
961
962/**
963 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000964 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000965 * @namespace: the namespace to check against
966 *
967 * Check that the current element namespace is the same as the
968 * one read upon parsing.
969 */
970int
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000971checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000972{
Daniel Veillard27d88741999-05-29 11:51:49 +0000973 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000974 xmlNodePtr cur = ctxt->node;
975
976#ifdef DEBUG_SAX
977 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
978#endif
979
980 /*
981 * Check that the Name in the ETag is the same as in the STag.
982 */
983 if (namespace == NULL) {
984 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
985 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
986 ctxt->sax->error(ctxt,
987 "End tags for %s don't hold the namespace %s\n",
988 cur->name, cur->ns->prefix);
989 ctxt->wellFormed = 0;
990 }
991 } else {
992 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
993 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
994 ctxt->sax->error(ctxt,
995 "End tags %s holds a prefix %s not used by the open tag\n",
996 cur->name, namespace);
997 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000998 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +0000999 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1000 ctxt->sax->error(ctxt,
1001 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1002 cur->name, cur->ns->prefix, namespace);
1003 ctxt->wellFormed = 0;
1004 } else
1005 return(1);
1006 }
1007 return(0);
1008}
1009
1010/**
1011 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001012 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001013 * @href: the namespace associated URN
1014 * @prefix: the namespace prefix
1015 *
1016 * A namespace has been parsed.
1017 */
1018void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001019namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001020{
Daniel Veillard27d88741999-05-29 11:51:49 +00001021 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001022#ifdef DEBUG_SAX
1023 if (prefix == NULL)
1024 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1025 else
1026 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1027#endif
1028 xmlNewNs(ctxt->node, href, prefix);
1029}
1030
1031/**
1032 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001033 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001034 * @value: the comment content
1035 *
1036 * A comment has been parsed.
1037 */
1038void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001039comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001040{
Daniel Veillard27d88741999-05-29 11:51:49 +00001041 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001042 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001043 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001044
Daniel Veillard517752b1999-04-05 12:20:10 +00001045#ifdef DEBUG_SAX
1046 fprintf(stderr, "SAX.comment(%s)\n", value);
1047#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001048 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001049 if (ret == NULL) return;
1050
1051 if (ctxt->myDoc->root == NULL) {
1052#ifdef DEBUG_SAX_TREE
1053 fprintf(stderr, "Setting comment as root\n");
1054#endif
1055 ctxt->myDoc->root = ret;
1056 } else if (parent == NULL) {
1057 parent = ctxt->myDoc->root;
1058 }
1059 if (parent != NULL) {
1060 if (parent->type == XML_ELEMENT_NODE) {
1061#ifdef DEBUG_SAX_TREE
1062 fprintf(stderr, "adding comment child to %s\n", parent->name);
1063#endif
1064 xmlAddChild(parent, ret);
1065 } else {
1066#ifdef DEBUG_SAX_TREE
1067 fprintf(stderr, "adding comment sibling to ");
1068 xmlDebugDumpOneNode(stderr, parent, 0);
1069#endif
1070 xmlAddSibling(parent, ret);
1071 }
1072 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001073}
1074
1075/**
1076 * cdataBlock:
1077 * @ctx: the user data (XML parser context)
1078 * @value: The pcdata content
1079 * @len: the block length
1080 *
1081 * called when a pcdata block has been parsed
1082 */
1083void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001084cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001085{
1086 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1087 xmlNodePtr ret;
1088
1089#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001090 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001091#endif
1092 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1093 xmlAddChild(ctxt->node, ret);
1094 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001095}
1096
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001097/*
1098 * Default handler for XML, builds the DOM tree
1099 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001100xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001101 internalSubset,
1102 isStandalone,
1103 hasInternalSubset,
1104 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001106 getEntity,
1107 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001108 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001109 attributeDecl,
1110 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111 unparsedEntityDecl,
1112 setDocumentLocator,
1113 startDocument,
1114 endDocument,
1115 startElement,
1116 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001117 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001118 characters,
1119 ignorableWhitespace,
1120 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001121 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001122 xmlParserWarning,
1123 xmlParserError,
1124 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001125 getParameterEntity,
1126 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001127};
1128
Daniel Veillard97b58771998-10-20 06:14:16 +00001129/**
1130 * xmlDefaultSAXHandlerInit:
1131 *
1132 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001133 */
1134void
1135xmlDefaultSAXHandlerInit(void)
1136{
Daniel Veillard517752b1999-04-05 12:20:10 +00001137 xmlDefaultSAXHandler.internalSubset = internalSubset;
1138 xmlDefaultSAXHandler.isStandalone = isStandalone;
1139 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1140 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001141 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001142 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001143 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001144 xmlDefaultSAXHandler.entityDecl = entityDecl;
1145 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1146 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 xmlDefaultSAXHandler.notationDecl = notationDecl;
1148 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1149 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1150 xmlDefaultSAXHandler.startDocument = startDocument;
1151 xmlDefaultSAXHandler.endDocument = endDocument;
1152 xmlDefaultSAXHandler.startElement = startElement;
1153 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001154 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001155 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001156 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001157 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1158 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001159 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001160 xmlDefaultSAXHandler.warning = xmlParserWarning;
1161 xmlDefaultSAXHandler.error = xmlParserError;
1162 xmlDefaultSAXHandler.fatalError = xmlParserError;
1163}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001164
1165/*
1166 * Default handler for HTML, builds the DOM tree
1167 */
1168xmlSAXHandler htmlDefaultSAXHandler = {
1169 NULL,
1170 NULL,
1171 NULL,
1172 NULL,
1173 NULL,
1174 getEntity,
1175 NULL,
1176 NULL,
1177 NULL,
1178 NULL,
1179 NULL,
1180 setDocumentLocator,
1181 startDocument,
1182 endDocument,
1183 startElement,
1184 endElement,
1185 NULL,
1186 characters,
1187 ignorableWhitespace,
1188 NULL,
1189 comment,
1190 xmlParserWarning,
1191 xmlParserError,
1192 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001193 getParameterEntity,
1194 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001195};
1196
1197/**
1198 * htmlDefaultSAXHandlerInit:
1199 *
1200 * Initialize the default SAX handler
1201 */
1202void
1203htmlDefaultSAXHandlerInit(void)
1204{
1205 htmlDefaultSAXHandler.internalSubset = NULL;
1206 htmlDefaultSAXHandler.isStandalone = NULL;
1207 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1208 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1209 htmlDefaultSAXHandler.resolveEntity = NULL;
1210 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001211 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001212 htmlDefaultSAXHandler.entityDecl = NULL;
1213 htmlDefaultSAXHandler.attributeDecl = NULL;
1214 htmlDefaultSAXHandler.elementDecl = NULL;
1215 htmlDefaultSAXHandler.notationDecl = NULL;
1216 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1217 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1218 htmlDefaultSAXHandler.startDocument = startDocument;
1219 htmlDefaultSAXHandler.endDocument = endDocument;
1220 htmlDefaultSAXHandler.startElement = startElement;
1221 htmlDefaultSAXHandler.endElement = endElement;
1222 htmlDefaultSAXHandler.reference = NULL;
1223 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001224 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001225 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1226 htmlDefaultSAXHandler.processingInstruction = NULL;
1227 htmlDefaultSAXHandler.comment = comment;
1228 htmlDefaultSAXHandler.warning = xmlParserWarning;
1229 htmlDefaultSAXHandler.error = xmlParserError;
1230 htmlDefaultSAXHandler.fatalError = xmlParserError;
1231}