blob: f1a85edaa13df51815fe67d0732116733b35ad68 [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 Veillard3c558c31999-12-22 11:30:41 +000010#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000016#include <stdlib.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000017#include <libxml/xmlmemory.h>
18#include <libxml/tree.h>
19#include <libxml/parser.h>
20#include <libxml/parserInternals.h>
21#include <libxml/valid.h>
22#include <libxml/entities.h>
Daniel Veillardd109e371999-03-05 06:26:45 +000023#include "xml-error.h"
Daniel Veillard361d8452000-04-03 19:48:13 +000024#include <libxml/debugXML.h>
25#include <libxml/xmlIO.h>
26#include <libxml/SAX.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000027
28/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000029/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000030
Daniel Veillard97b58771998-10-20 06:14:16 +000031/**
32 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000033 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000034 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000035 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000036 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000037 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000038 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000039const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000040getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000041{
Daniel Veillard27d88741999-05-29 11:51:49 +000042 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000043 return(NULL);
44}
45
Daniel Veillard97b58771998-10-20 06:14:16 +000046/**
47 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000048 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000049 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000050 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000051 * http://www.sgmlsource.com/dtds/memo.dtd
52 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000053 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000054 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000055const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000056getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000057{
Daniel Veillard27d88741999-05-29 11:51:49 +000058 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000059 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000060}
61
Daniel Veillard97b58771998-10-20 06:14:16 +000062/**
63 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000064 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000065 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000066 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000067 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000068 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 */
Daniel Veillard97b58771998-10-20 06:14:16 +000070int
Daniel Veillard27d88741999-05-29 11:51:49 +000071getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000072{
Daniel Veillard27d88741999-05-29 11:51:49 +000073 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000074 return(ctxt->input->line);
75}
Daniel Veillard97b58771998-10-20 06:14:16 +000076
77/**
78 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000079 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000080 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000081 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000082 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000083 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000084 */
Daniel Veillard97b58771998-10-20 06:14:16 +000085int
Daniel Veillard27d88741999-05-29 11:51:49 +000086getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000087{
Daniel Veillard27d88741999-05-29 11:51:49 +000088 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000089 return(ctxt->input->col);
90}
91
92/*
93 * The default SAX Locator.
94 */
95
96xmlSAXLocator xmlDefaultSAXLocator = {
97 getPublicId, getSystemId, getLineNumber, getColumnNumber
98};
99
Daniel Veillard97b58771998-10-20 06:14:16 +0000100/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000101 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000102 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000103 *
104 * Is this document tagged standalone ?
105 *
106 * Returns 1 if true
107 */
108int
Daniel Veillard27d88741999-05-29 11:51:49 +0000109isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000110{
Daniel Veillard27d88741999-05-29 11:51:49 +0000111 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000112 return(ctxt->myDoc->standalone == 1);
113}
114
115/**
116 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000117 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000118 *
119 * Does this document has an internal subset
120 *
121 * Returns 1 if true
122 */
123int
Daniel Veillard27d88741999-05-29 11:51:49 +0000124hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000125{
Daniel Veillard27d88741999-05-29 11:51:49 +0000126 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000127 return(ctxt->myDoc->intSubset != NULL);
128}
129
130/**
131 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000132 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000133 *
134 * Does this document has an external subset
135 *
136 * Returns 1 if true
137 */
138int
Daniel Veillard27d88741999-05-29 11:51:49 +0000139hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000140{
Daniel Veillard27d88741999-05-29 11:51:49 +0000141 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000142 return(ctxt->myDoc->extSubset != NULL);
143}
144
145/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000146 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000147 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000148 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000149 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000150 */
151void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000152internalSubset(void *ctx, const xmlChar *name,
153 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000154{
Daniel Veillard27d88741999-05-29 11:51:49 +0000155 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000156#ifdef DEBUG_SAX
157 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
158 name, ExternalID, SystemID);
159#endif
160 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000161}
162
163/**
164 * externalSubset:
165 * @ctx: the user data (XML parser context)
166 *
167 * Callback on external subset declaration.
168 */
169void
170externalSubset(void *ctx, const xmlChar *name,
171 const xmlChar *ExternalID, const xmlChar *SystemID)
172{
173 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
174#ifdef DEBUG_SAX
175 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
176 name, ExternalID, SystemID);
177#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000178 if (((ExternalID != NULL) || (SystemID != NULL)) &&
179 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
180 /*
181 * Try to fetch and parse the external subset.
182 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000183 xmlParserInputPtr oldinput;
184 int oldinputNr;
185 int oldinputMax;
186 xmlParserInputPtr *oldinputTab;
187 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000188 xmlParserInputPtr input = NULL;
189 xmlCharEncoding enc;
190
Daniel Veillardb05deb71999-08-10 19:04:08 +0000191 /*
192 * Ask the Entity resolver to load the damn thing
193 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000194 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
195 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000196 SystemID);
197 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000198 return;
199 }
200
Daniel Veillardcf461992000-03-14 18:30:20 +0000201 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
202
Daniel Veillardb05deb71999-08-10 19:04:08 +0000203 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000204 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000205 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000206 oldinput = ctxt->input;
207 oldinputNr = ctxt->inputNr;
208 oldinputMax = ctxt->inputMax;
209 oldinputTab = ctxt->inputTab;
210 oldwellFormed = ctxt->wellFormed;
211
212 ctxt->inputTab = (xmlParserInputPtr *)
213 xmlMalloc(5 * sizeof(xmlParserInputPtr));
214 if (ctxt->inputTab == NULL) {
215 ctxt->errNo = XML_ERR_NO_MEMORY;
216 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
217 ctxt->sax->error(ctxt->userData,
218 "externalSubset: out of memory\n");
219 ctxt->errNo = XML_ERR_NO_MEMORY;
220 ctxt->input = oldinput;
221 ctxt->inputNr = oldinputNr;
222 ctxt->inputMax = oldinputMax;
223 ctxt->inputTab = oldinputTab;
224 return;
225 }
226 ctxt->inputNr = 0;
227 ctxt->inputMax = 5;
228 ctxt->input = NULL;
229 xmlPushInput(ctxt, input);
230
231 /*
232 * On the fly encoding conversion if needed
233 */
234 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
235 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000236
237 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000238 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000239 input->line = 1;
240 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000241 input->base = ctxt->input->cur;
242 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000243 input->free = NULL;
244
245 /*
246 * let's parse that entity knowing it's an external subset.
247 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000248 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000249
Daniel Veillardcf461992000-03-14 18:30:20 +0000250 /*
251 * Free up the external entities
252 */
253
254 while (ctxt->inputNr > 1)
255 xmlPopInput(ctxt);
256 xmlFreeInputStream(ctxt->input);
257 xmlFree(ctxt->inputTab);
258
259 /*
260 * Restore the parsing context of the main entity
261 */
262 ctxt->input = oldinput;
263 ctxt->inputNr = oldinputNr;
264 ctxt->inputMax = oldinputMax;
265 ctxt->inputTab = oldinputTab;
266 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000267 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000268}
269
270/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000271 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000272 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000273 * @publicId: The public ID of the entity
274 * @systemId: The system ID of the entity
275 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000276 * The entity loader, to control the loading of external entities,
277 * the application can either:
278 * - override this resolveEntity() callback in the SAX block
279 * - or better use the xmlSetExternalEntityLoader() function to
280 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000281 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000282 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000283 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000284xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000285resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000286{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000288
289#ifdef DEBUG_SAX
290 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
291#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000292
Daniel Veillard686d6b62000-01-03 11:08:02 +0000293 return(xmlLoadExternalEntity((const char *) systemId,
294 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000295}
296
Daniel Veillard97b58771998-10-20 06:14:16 +0000297/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000298 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000299 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000300 * @name: The entity name
301 *
302 * Get an entity by name
303 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000304 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000305 */
306xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000307getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000308{
Daniel Veillard27d88741999-05-29 11:51:49 +0000309 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000310 xmlEntityPtr ret;
311
312#ifdef DEBUG_SAX
313 fprintf(stderr, "SAX.getEntity(%s)\n", name);
314#endif
315
316 ret = xmlGetDocEntity(ctxt->myDoc, name);
317 return(ret);
318}
319
Daniel Veillardb05deb71999-08-10 19:04:08 +0000320/**
321 * getParameterEntity:
322 * @ctx: the user data (XML parser context)
323 * @name: The entity name
324 *
325 * Get a parameter entity by name
326 *
327 * Returns the xmlEntityPtr if found.
328 */
329xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000330getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000331{
332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
333 xmlEntityPtr ret;
334
335#ifdef DEBUG_SAX
336 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
337#endif
338
339 ret = xmlGetParameterEntity(ctxt->myDoc, name);
340 return(ret);
341}
342
Daniel Veillard517752b1999-04-05 12:20:10 +0000343
344/**
345 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000346 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000347 * @name: the entity name
348 * @type: the entity type
349 * @publicId: The public ID of the entity
350 * @systemId: The system ID of the entity
351 * @content: the entity value (without processing).
352 *
353 * An entity definition has been parsed
354 */
355void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000356entityDecl(void *ctx, const xmlChar *name, int type,
357 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000358{
Daniel Veillard27d88741999-05-29 11:51:49 +0000359 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000360
361#ifdef DEBUG_SAX
362 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
363 name, type, publicId, systemId, content);
364#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000365 if (ctxt->inSubset == 1)
366 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
367 systemId, content);
368 else if (ctxt->inSubset == 2)
369 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
370 systemId, content);
371 else {
372 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
373 ctxt->sax->error(ctxt,
374 "SAX.entityDecl(%s) called while not in subset\n", name);
375 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000376}
377
378/**
379 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000380 * @ctx: the user data (XML parser context)
Daniel Veillardcf461992000-03-14 18:30:20 +0000381 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000382 * @type: the attribute type
383 * @publicId: The public ID of the attribute
384 * @systemId: The system ID of the attribute
385 * @content: the attribute value (without processing).
386 *
387 * An attribute definition has been parsed
388 */
389void
Daniel Veillardcf461992000-03-14 18:30:20 +0000390attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000391 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000392 xmlEnumerationPtr tree)
393{
Daniel Veillard27d88741999-05-29 11:51:49 +0000394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000395 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000396 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000397
398#ifdef DEBUG_SAX
399 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000400 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000401#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000402 name = xmlSplitQName(ctxt, fullname, &prefix);
403 if (ctxt->inSubset == 1)
404 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
405 name, prefix, type, def, defaultValue, tree);
406 else if (ctxt->inSubset == 2)
407 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
408 name, prefix, type, def, defaultValue, tree);
409 else {
410 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
411 ctxt->sax->error(ctxt,
412 "SAX.attributeDecl(%s) called while not in subset\n", name);
413 return;
414 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000415 if (attr == 0) ctxt->valid = 0;
416 if (ctxt->validate && ctxt->wellFormed &&
417 ctxt->myDoc && ctxt->myDoc->intSubset)
418 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
419 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000420 if (prefix != NULL)
421 xmlFree(prefix);
422 if (name != NULL)
423 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000424}
425
426/**
427 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000428 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000429 * @name: the element name
430 * @type: the element type
431 * @publicId: The public ID of the element
432 * @systemId: The system ID of the element
433 * @content: the element value (without processing).
434 *
435 * An element definition has been parsed
436 */
437void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000438elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000439 xmlElementContentPtr content)
440{
Daniel Veillard27d88741999-05-29 11:51:49 +0000441 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000442 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000443
444#ifdef DEBUG_SAX
445 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000446 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000447#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000448
Daniel Veillardcf461992000-03-14 18:30:20 +0000449 if (ctxt->inSubset == 1)
450 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000451 name, type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000452 else if (ctxt->inSubset == 2)
453 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
454 name, type, content);
455 else {
456 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
457 ctxt->sax->error(ctxt,
458 "SAX.elementDecl(%s) called while not in subset\n", name);
459 return;
460 }
461 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000462 if (ctxt->validate && ctxt->wellFormed &&
463 ctxt->myDoc && ctxt->myDoc->intSubset)
464 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000465}
466
467/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000468 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000469 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000470 * @name: The name of the notation
471 * @publicId: The public ID of the entity
472 * @systemId: The system ID of the entity
473 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000474 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000475 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000476void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000477notationDecl(void *ctx, const xmlChar *name,
478 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000479{
Daniel Veillard27d88741999-05-29 11:51:49 +0000480 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000481 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000482
Daniel Veillard260a68f1998-08-13 03:39:55 +0000483#ifdef DEBUG_SAX
484 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
485#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000486
Daniel Veillardcf461992000-03-14 18:30:20 +0000487 if (ctxt->inSubset == 1)
488 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000489 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000490 else if (ctxt->inSubset == 2)
491 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
492 publicId, systemId);
493 else {
494 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
495 ctxt->sax->error(ctxt,
496 "SAX.notationDecl(%s) called while not in subset\n", name);
497 return;
498 }
499 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000500 if (ctxt->validate && ctxt->wellFormed &&
501 ctxt->myDoc && ctxt->myDoc->intSubset)
502 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
503 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000504}
505
Daniel Veillard97b58771998-10-20 06:14:16 +0000506/**
507 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000508 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000509 * @name: The name of the entity
510 * @publicId: The public ID of the entity
511 * @systemId: The system ID of the entity
512 * @notationName: the name of the notation
513 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000514 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000515 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000516void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000517unparsedEntityDecl(void *ctx, const xmlChar *name,
518 const xmlChar *publicId, const xmlChar *systemId,
519 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000520{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000521 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000522#ifdef DEBUG_SAX
523 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
524 name, publicId, systemId, notationName);
525#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000526 if (ctxt->validate && ctxt->wellFormed &&
527 ctxt->myDoc && ctxt->myDoc->intSubset)
528 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
529 notationName);
530 xmlAddDocEntity(ctxt->myDoc, name,
531 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
532 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000533}
534
Daniel Veillard97b58771998-10-20 06:14:16 +0000535/**
536 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000537 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000538 * @loc: A SAX Locator
539 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000540 * Receive the document locator at startup, actually xmlDefaultSAXLocator
541 * Everything is available on the context, so this is useless in our case.
542 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000543void
Daniel Veillard27d88741999-05-29 11:51:49 +0000544setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000545{
Daniel Veillard27d88741999-05-29 11:51:49 +0000546 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000547#ifdef DEBUG_SAX
548 fprintf(stderr, "SAX.setDocumentLocator()\n");
549#endif
550}
551
Daniel Veillard97b58771998-10-20 06:14:16 +0000552/**
553 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000554 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000555 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000556 * called when the document start being processed.
557 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000558void
Daniel Veillard27d88741999-05-29 11:51:49 +0000559startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000560{
Daniel Veillard27d88741999-05-29 11:51:49 +0000561 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000562 xmlDocPtr doc;
563
Daniel Veillard260a68f1998-08-13 03:39:55 +0000564#ifdef DEBUG_SAX
565 fprintf(stderr, "SAX.startDocument()\n");
566#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000567 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
568 if (doc != NULL) {
569 if (ctxt->encoding != NULL)
570 doc->encoding = xmlStrdup(ctxt->encoding);
571 else
572 doc->encoding = NULL;
573 doc->standalone = ctxt->standalone;
574 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000575}
576
Daniel Veillard97b58771998-10-20 06:14:16 +0000577/**
578 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000579 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000580 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000581 * called when the document end has been detected.
582 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000583void
Daniel Veillard27d88741999-05-29 11:51:49 +0000584endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000585{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000586 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000587#ifdef DEBUG_SAX
588 fprintf(stderr, "SAX.endDocument()\n");
589#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000590 if (ctxt->validate && ctxt->wellFormed &&
591 ctxt->myDoc && ctxt->myDoc->intSubset)
592 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000593}
594
Daniel Veillard97b58771998-10-20 06:14:16 +0000595/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000596 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000597 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000598 * @name: The attribute name
599 * @value: The attribute value
600 *
601 * Handle an attribute that has been read by the parser.
602 * The default handling is to convert the attribute into an
603 * DOM subtree and past it in a new xmlAttr element added to
604 * the element.
605 */
606void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000607attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000608{
Daniel Veillard27d88741999-05-29 11:51:49 +0000609 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000610 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000611 xmlChar *name;
612 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000613 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000614 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000615
616/****************
617#ifdef DEBUG_SAX
618 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
619#endif
620 ****************/
621 /*
622 * Split the full name into a namespace prefix and the tag name
623 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000624 name = xmlSplitQName(ctxt, fullname, &ns);
625
626 /*
627 * Do the last stave of the attribute normalization
628 */
629 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
630 ctxt->node, fullname, value);
631 if (nval != NULL)
632 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000633
634 /*
635 * Check whether it's a namespace definition
636 */
637 if ((ns == NULL) &&
638 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
639 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
640 /* a default namespace definition */
641 xmlNewNs(ctxt->node, value, NULL);
642 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000643 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000644 if (nval != NULL)
645 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000646 return;
647 }
648 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
649 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000650 /*
651 * Validate also for namespace decls, they are attributes from
652 * an XML-1.0 perspective
653 TODO ... doesn't map well with current API
654 if (ctxt->validate && ctxt->wellFormed &&
655 ctxt->myDoc && ctxt->myDoc->intSubset)
656 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
657 ctxt->node, ret, value);
658 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000659 /* a standard namespace definition */
660 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000661 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000662 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000663 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000664 if (nval != NULL)
665 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000666 return;
667 }
668
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000669 if (ns != NULL)
670 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
671 else {
672 namespace = NULL;
673 }
674
Daniel Veillardb96e6431999-08-29 21:02:19 +0000675 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
676 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000677
Daniel Veillardb96e6431999-08-29 21:02:19 +0000678 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000679 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
680 xmlNodePtr tmp;
681
682 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
683 tmp = ret->children;
684 while (tmp != NULL) {
685 tmp->parent = (xmlNodePtr) ret;
686 if (tmp->next == NULL)
687 ret->last = tmp;
688 tmp = tmp->next;
689 }
690 } else {
691 ret->children = xmlNewDocText(ctxt->myDoc, value);
692 ret->last = ret->children;
693 if (ret->children != NULL)
694 ret->children->parent = (xmlNodePtr) ret;
695 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000696 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000697
698 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000699 ctxt->myDoc && ctxt->myDoc->intSubset) {
700
701 /*
702 * If we don't substitute entities, the validation should be
703 * done on a value with replaced entities anyway.
704 */
705 if (!ctxt->replaceEntities) {
706 xmlChar *val;
707
708 ctxt->depth++;
709 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
710 0,0,0);
711 ctxt->depth--;
712 if (val == NULL)
713 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
714 ctxt->myDoc, ctxt->node, ret, value);
715 else {
716 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
717 ctxt->myDoc, ctxt->node, ret, val);
718 xmlFree(val);
719 }
720 } else {
721 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000722 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000723 }
724 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000725 /*
726 * when validating, the ID registration is done at the attribute
727 * validation level. Otherwise we have to do specific handling here.
728 */
729 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
730 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000731 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
732 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000733 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000734
Daniel Veillardcf461992000-03-14 18:30:20 +0000735 if (nval != NULL)
736 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000737 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000738 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000739 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000740 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000741}
742
743/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000744 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000745 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000746 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000747 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000748 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000749 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000750 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000751void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000752startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000753{
Daniel Veillard27d88741999-05-29 11:51:49 +0000754 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000755 xmlNodePtr ret;
756 xmlNodePtr parent = ctxt->node;
757 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000758 xmlChar *name;
759 xmlChar *prefix;
760 const xmlChar *att;
761 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000762 int i;
763
Daniel Veillard260a68f1998-08-13 03:39:55 +0000764#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000765 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000766#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000767
768 /*
769 * First check on validity:
770 */
771 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
772 ((ctxt->myDoc->intSubset == NULL) ||
773 ((ctxt->myDoc->intSubset->notations == NULL) &&
774 (ctxt->myDoc->intSubset->elements == NULL) &&
775 (ctxt->myDoc->intSubset->attributes == NULL) &&
776 (ctxt->myDoc->intSubset->entities == NULL)))) {
777 if (ctxt->vctxt.error != NULL) {
778 ctxt->vctxt.error(ctxt->vctxt.userData,
779 "Validation failed: no DTD found !\n");
780 }
781 ctxt->validate = 0;
782 }
783
784
Daniel Veillard517752b1999-04-05 12:20:10 +0000785 /*
786 * Split the full name into a namespace prefix and the tag name
787 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000788 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000789
790
791 /*
792 * Note : the namespace resolution is deferred until the end of the
793 * attributes parsing, since local namespace can be defined as
794 * an attribute at this level.
795 */
796 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
797 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000798 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000799#ifdef DEBUG_SAX_TREE
800 fprintf(stderr, "Setting %s as root\n", name);
801#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000802 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000803 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000804 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000805 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000806
807 /*
808 * We are parsing a new node.
809 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000810#ifdef DEBUG_SAX_TREE
811 fprintf(stderr, "pushing(%s)\n", name);
812#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000813 nodePush(ctxt, ret);
814
815 /*
816 * Link the child element
817 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000818 if (parent != NULL) {
819 if (parent->type == XML_ELEMENT_NODE) {
820#ifdef DEBUG_SAX_TREE
821 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
822#endif
823 xmlAddChild(parent, ret);
824 } else {
825#ifdef DEBUG_SAX_TREE
826 fprintf(stderr, "adding sibling %s to ", name);
827 xmlDebugDumpOneNode(stderr, parent, 0);
828#endif
829 xmlAddSibling(parent, ret);
830 }
831 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000832
833 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000834 * If it's the Document root, finish the Dtd validation and
835 * check the document root element for validity
836 */
837 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
838 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
839 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
840 ctxt->vctxt.finishDtd = 1;
841 }
842 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000843 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000844 */
845 if (atts != NULL) {
846 i = 0;
847 att = atts[i++];
848 value = atts[i++];
849 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000850 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
851 attribute(ctxt, att, value);
852
853 att = atts[i++];
854 value = atts[i++];
855 }
856 }
857
858 /*
859 * process all the other attributes
860 */
861 if (atts != NULL) {
862 i = 0;
863 att = atts[i++];
864 value = atts[i++];
865 while ((att != NULL) && (value != NULL)) {
866 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
867 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000868
869 /*
870 * Next ones
871 */
872 att = atts[i++];
873 value = atts[i++];
874 }
875 }
876
877 /*
878 * Search the namespace, note that since the attributes have been
879 * processed, the local namespaces are available.
880 */
881 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
882 if ((ns == NULL) && (parent != NULL))
883 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
884 xmlSetNs(ret, ns);
885
886 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000887 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000888 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000889 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000890
Daniel Veillard260a68f1998-08-13 03:39:55 +0000891}
892
Daniel Veillard97b58771998-10-20 06:14:16 +0000893/**
894 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000895 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000896 * @name: The element name
897 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000898 * called when the end of an element has been detected.
899 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000900void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000901endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000902{
Daniel Veillard27d88741999-05-29 11:51:49 +0000903 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000904 xmlParserNodeInfo node_info;
905 xmlNodePtr cur = ctxt->node;
906
Daniel Veillard260a68f1998-08-13 03:39:55 +0000907#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000908 if (name == NULL)
909 fprintf(stderr, "SAX.endElement(NULL)\n");
910 else
911 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000912#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000913
914 /* Capture end position and add node */
915 if (cur != NULL && ctxt->record_info) {
916 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
917 node_info.end_line = ctxt->input->line;
918 node_info.node = cur;
919 xmlParserAddNodeInfo(ctxt, &node_info);
920 }
921
Daniel Veillardb05deb71999-08-10 19:04:08 +0000922 if (ctxt->validate && ctxt->wellFormed &&
923 ctxt->myDoc && ctxt->myDoc->intSubset)
924 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
925 cur);
926
927
Daniel Veillard517752b1999-04-05 12:20:10 +0000928 /*
929 * end of parsing of this node.
930 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000931#ifdef DEBUG_SAX_TREE
932 fprintf(stderr, "popping(%s)\n", cur->name);
933#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000934 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000935}
936
Daniel Veillard97b58771998-10-20 06:14:16 +0000937/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000938 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000939 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000940 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000941 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000942 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000943 */
944void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000945reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000946{
Daniel Veillard27d88741999-05-29 11:51:49 +0000947 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000948 xmlNodePtr ret;
949
Daniel Veillard11e00581998-10-24 18:27:49 +0000950#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000951 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000952#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000953 if (name[0] == '#')
954 ret = xmlNewCharRef(ctxt->myDoc, name);
955 else
956 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000957#ifdef DEBUG_SAX_TREE
958 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
959#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000960 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000961}
962
963/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000964 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000965 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000966 * @ch: a xmlChar string
967 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000968 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000969 * receiving some chars from the parser.
970 * Question: how much at a time ???
971 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000972void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000973characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000974{
Daniel Veillard27d88741999-05-29 11:51:49 +0000975 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000976 xmlNodePtr lastChild;
977
978#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000979 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000980#endif
981 /*
982 * Handle the data if any. If there is no child
983 * add it as content, otherwise if the last child is text,
984 * concatenate it, else create a new node of type text.
985 */
986
Daniel Veillard35008381999-10-25 13:15:52 +0000987 if (ctxt->node == NULL) {
988#ifdef DEBUG_SAX_TREE
989 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
990#endif
991 return;
992 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000993 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000994#ifdef DEBUG_SAX_TREE
995 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
996#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000997 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000998 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000999 else {
1000 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +00001001 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001002 else {
Daniel Veillard517752b1999-04-05 12:20:10 +00001003 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001004 xmlAddChild(ctxt->node, lastChild);
1005 }
1006 }
1007}
1008
Daniel Veillard97b58771998-10-20 06:14:16 +00001009/**
1010 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001011 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001012 * @ch: a xmlChar string
1013 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001014 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001015 * receiving some ignorable whitespaces from the parser.
1016 * Question: how much at a time ???
1017 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001018void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001019ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001020{
Daniel Veillard27d88741999-05-29 11:51:49 +00001021 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001022#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001023 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001024#endif
1025}
1026
Daniel Veillard97b58771998-10-20 06:14:16 +00001027/**
1028 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001029 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001030 * @target: the target name
1031 * @data: the PI data's
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001032 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001033 *
1034 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001035 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001036void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001037processingInstruction(void *ctx, const xmlChar *target,
1038 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001039{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001040 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1041 xmlNodePtr ret;
1042 xmlNodePtr parent = ctxt->node;
1043
Daniel Veillard260a68f1998-08-13 03:39:55 +00001044#ifdef DEBUG_SAX
1045 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1046#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001047
1048 ret = xmlNewPI(target, data);
1049 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001050 parent = ctxt->node;
1051
1052 if (ctxt->inSubset == 1) {
1053 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1054 return;
1055 } else if (ctxt->inSubset == 2) {
1056 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1057 return;
1058 }
1059 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001060#ifdef DEBUG_SAX_TREE
1061 fprintf(stderr, "Setting PI %s as root\n", target);
1062#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001063 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1064 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001065 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001066 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001067#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001068 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001069#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001070 xmlAddChild(parent, ret);
1071 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001072#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001073 fprintf(stderr, "adding PI %s sibling to ", target);
1074 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001075#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001076 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001077 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001078}
1079
Daniel Veillard517752b1999-04-05 12:20:10 +00001080/**
1081 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001082 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001083 * @href: the namespace associated URN
1084 * @prefix: the namespace prefix
1085 *
1086 * An old global namespace has been parsed.
1087 */
1088void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001089globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001090{
Daniel Veillard27d88741999-05-29 11:51:49 +00001091 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001092#ifdef DEBUG_SAX
1093 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1094#endif
1095 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1096}
1097
1098/**
1099 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001100 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001101 * @name: the namespace prefix
1102 *
1103 * Set the current element namespace.
1104 */
1105void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001106setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001107{
Daniel Veillard27d88741999-05-29 11:51:49 +00001108 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001109 xmlNsPtr ns;
1110 xmlNodePtr parent;
1111
1112#ifdef DEBUG_SAX
1113 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1114#endif
1115 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1116 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1117 if (ctxt->nodeNr >= 2) {
1118 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1119 if (parent != NULL)
1120 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1121 }
1122 }
1123 xmlSetNs(ctxt->node, ns);
1124}
1125
1126/**
1127 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001128 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001129 *
1130 * Get the current element namespace.
1131 */
1132xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001133getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001134{
Daniel Veillard27d88741999-05-29 11:51:49 +00001135 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001136 xmlNsPtr ret;
1137
1138#ifdef DEBUG_SAX
1139 fprintf(stderr, "SAX.getNamespace()\n");
1140#endif
1141 ret = ctxt->node->ns;
1142 return(ret);
1143}
1144
1145/**
1146 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001147 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001148 * @namespace: the namespace to check against
1149 *
1150 * Check that the current element namespace is the same as the
1151 * one read upon parsing.
1152 */
1153int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001154checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001155{
Daniel Veillard27d88741999-05-29 11:51:49 +00001156 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001157 xmlNodePtr cur = ctxt->node;
1158
1159#ifdef DEBUG_SAX
1160 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1161#endif
1162
1163 /*
1164 * Check that the Name in the ETag is the same as in the STag.
1165 */
1166 if (namespace == NULL) {
1167 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1168 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1169 ctxt->sax->error(ctxt,
1170 "End tags for %s don't hold the namespace %s\n",
1171 cur->name, cur->ns->prefix);
1172 ctxt->wellFormed = 0;
1173 }
1174 } else {
1175 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1176 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1177 ctxt->sax->error(ctxt,
1178 "End tags %s holds a prefix %s not used by the open tag\n",
1179 cur->name, namespace);
1180 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001181 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001182 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1183 ctxt->sax->error(ctxt,
1184 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1185 cur->name, cur->ns->prefix, namespace);
1186 ctxt->wellFormed = 0;
1187 } else
1188 return(1);
1189 }
1190 return(0);
1191}
1192
1193/**
1194 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001195 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001196 * @href: the namespace associated URN
1197 * @prefix: the namespace prefix
1198 *
1199 * A namespace has been parsed.
1200 */
1201void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001202namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001203{
Daniel Veillard27d88741999-05-29 11:51:49 +00001204 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001205#ifdef DEBUG_SAX
1206 if (prefix == NULL)
1207 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1208 else
1209 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1210#endif
1211 xmlNewNs(ctxt->node, href, prefix);
1212}
1213
1214/**
1215 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001216 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001217 * @value: the comment content
1218 *
1219 * A comment has been parsed.
1220 */
1221void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001222comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001223{
Daniel Veillard27d88741999-05-29 11:51:49 +00001224 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001225 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001226 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001227
Daniel Veillard517752b1999-04-05 12:20:10 +00001228#ifdef DEBUG_SAX
1229 fprintf(stderr, "SAX.comment(%s)\n", value);
1230#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001231 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001232 if (ret == NULL) return;
1233
Daniel Veillardcf461992000-03-14 18:30:20 +00001234 if (ctxt->inSubset == 1) {
1235 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1236 return;
1237 } else if (ctxt->inSubset == 2) {
1238 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1239 return;
1240 }
1241 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001242#ifdef DEBUG_SAX_TREE
1243 fprintf(stderr, "Setting comment as root\n");
1244#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001245 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1246 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001247 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001248 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001249#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001250 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001251#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001252 xmlAddChild(parent, ret);
1253 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001254#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001255 fprintf(stderr, "adding comment sibling to ");
1256 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001257#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001258 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001259 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001260}
1261
1262/**
1263 * cdataBlock:
1264 * @ctx: the user data (XML parser context)
1265 * @value: The pcdata content
1266 * @len: the block length
1267 *
1268 * called when a pcdata block has been parsed
1269 */
1270void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001271cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001272{
1273 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001274 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001275
1276#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001277 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001278#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001279 lastChild = xmlGetLastChild(ctxt->node);
1280#ifdef DEBUG_SAX_TREE
1281 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1282#endif
1283 if ((lastChild != NULL) &&
1284 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1285 xmlTextConcat(lastChild, value, len);
1286 } else {
1287 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1288 xmlAddChild(ctxt->node, ret);
1289 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001290}
1291
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001292/*
1293 * Default handler for XML, builds the DOM tree
1294 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001295xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001296 internalSubset,
1297 isStandalone,
1298 hasInternalSubset,
1299 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001300 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001301 getEntity,
1302 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001303 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001304 attributeDecl,
1305 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001306 unparsedEntityDecl,
1307 setDocumentLocator,
1308 startDocument,
1309 endDocument,
1310 startElement,
1311 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001312 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001313 characters,
1314 ignorableWhitespace,
1315 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001316 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001317 xmlParserWarning,
1318 xmlParserError,
1319 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001320 getParameterEntity,
1321 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001322 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001323};
1324
Daniel Veillard97b58771998-10-20 06:14:16 +00001325/**
1326 * xmlDefaultSAXHandlerInit:
1327 *
1328 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001329 */
1330void
1331xmlDefaultSAXHandlerInit(void)
1332{
Daniel Veillard517752b1999-04-05 12:20:10 +00001333 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001334 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001335 xmlDefaultSAXHandler.isStandalone = isStandalone;
1336 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1337 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001338 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001339 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001340 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001341 xmlDefaultSAXHandler.entityDecl = entityDecl;
1342 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1343 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001344 xmlDefaultSAXHandler.notationDecl = notationDecl;
1345 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1346 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1347 xmlDefaultSAXHandler.startDocument = startDocument;
1348 xmlDefaultSAXHandler.endDocument = endDocument;
1349 xmlDefaultSAXHandler.startElement = startElement;
1350 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001351 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001352 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001353 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001354 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1355 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001356 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001357 if (xmlGetWarningsDefaultValue == 0)
1358 xmlDefaultSAXHandler.warning = NULL;
1359 else
1360 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001361 xmlDefaultSAXHandler.error = xmlParserError;
1362 xmlDefaultSAXHandler.fatalError = xmlParserError;
1363}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001364
1365/*
1366 * Default handler for HTML, builds the DOM tree
1367 */
1368xmlSAXHandler htmlDefaultSAXHandler = {
1369 NULL,
1370 NULL,
1371 NULL,
1372 NULL,
1373 NULL,
1374 getEntity,
1375 NULL,
1376 NULL,
1377 NULL,
1378 NULL,
1379 NULL,
1380 setDocumentLocator,
1381 startDocument,
1382 endDocument,
1383 startElement,
1384 endElement,
1385 NULL,
1386 characters,
1387 ignorableWhitespace,
1388 NULL,
1389 comment,
1390 xmlParserWarning,
1391 xmlParserError,
1392 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001393 getParameterEntity,
1394 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001395 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001396};
1397
1398/**
1399 * htmlDefaultSAXHandlerInit:
1400 *
1401 * Initialize the default SAX handler
1402 */
1403void
1404htmlDefaultSAXHandlerInit(void)
1405{
1406 htmlDefaultSAXHandler.internalSubset = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001407 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001408 htmlDefaultSAXHandler.isStandalone = NULL;
1409 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1410 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1411 htmlDefaultSAXHandler.resolveEntity = NULL;
1412 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001413 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001414 htmlDefaultSAXHandler.entityDecl = NULL;
1415 htmlDefaultSAXHandler.attributeDecl = NULL;
1416 htmlDefaultSAXHandler.elementDecl = NULL;
1417 htmlDefaultSAXHandler.notationDecl = NULL;
1418 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1419 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1420 htmlDefaultSAXHandler.startDocument = startDocument;
1421 htmlDefaultSAXHandler.endDocument = endDocument;
1422 htmlDefaultSAXHandler.startElement = startElement;
1423 htmlDefaultSAXHandler.endElement = endElement;
1424 htmlDefaultSAXHandler.reference = NULL;
1425 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001426 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001427 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1428 htmlDefaultSAXHandler.processingInstruction = NULL;
1429 htmlDefaultSAXHandler.comment = comment;
1430 htmlDefaultSAXHandler.warning = xmlParserWarning;
1431 htmlDefaultSAXHandler.error = xmlParserError;
1432 htmlDefaultSAXHandler.fatalError = xmlParserError;
1433}