blob: c352a044b31be113a7d5d5380a9314f730397168 [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 Veillardbe803962000-06-28 23:40:59 +000027#include <libxml/uri.h>
Daniel Veillardd83eb822000-06-30 18:39:56 +000028#include <libxml/HTMLtree.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000029
30/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000031/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000032
Daniel Veillard97b58771998-10-20 06:14:16 +000033/**
34 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000035 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000036 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000037 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000038 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000039 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000040 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000041const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000042getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000043{
Daniel Veillard27d88741999-05-29 11:51:49 +000044 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000045 return(NULL);
46}
47
Daniel Veillard97b58771998-10-20 06:14:16 +000048/**
49 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000050 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000051 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000052 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000053 * http://www.sgmlsource.com/dtds/memo.dtd
54 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000055 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000056 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000057const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000058getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000059{
Daniel Veillard27d88741999-05-29 11:51:49 +000060 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000061 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000062}
63
Daniel Veillard97b58771998-10-20 06:14:16 +000064/**
65 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000066 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000067 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000069 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000070 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000071 */
Daniel Veillard97b58771998-10-20 06:14:16 +000072int
Daniel Veillard27d88741999-05-29 11:51:49 +000073getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000074{
Daniel Veillard27d88741999-05-29 11:51:49 +000075 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000076 return(ctxt->input->line);
77}
Daniel Veillard97b58771998-10-20 06:14:16 +000078
79/**
80 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000081 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000082 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000083 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000084 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000085 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000086 */
Daniel Veillard97b58771998-10-20 06:14:16 +000087int
Daniel Veillard27d88741999-05-29 11:51:49 +000088getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000089{
Daniel Veillard27d88741999-05-29 11:51:49 +000090 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000091 return(ctxt->input->col);
92}
93
94/*
95 * The default SAX Locator.
96 */
97
98xmlSAXLocator xmlDefaultSAXLocator = {
99 getPublicId, getSystemId, getLineNumber, getColumnNumber
100};
101
Daniel Veillard97b58771998-10-20 06:14:16 +0000102/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000103 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000104 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000105 *
106 * Is this document tagged standalone ?
107 *
108 * Returns 1 if true
109 */
110int
Daniel Veillard27d88741999-05-29 11:51:49 +0000111isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000112{
Daniel Veillard27d88741999-05-29 11:51:49 +0000113 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000114 return(ctxt->myDoc->standalone == 1);
115}
116
117/**
118 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000119 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000120 *
121 * Does this document has an internal subset
122 *
123 * Returns 1 if true
124 */
125int
Daniel Veillard27d88741999-05-29 11:51:49 +0000126hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000127{
Daniel Veillard27d88741999-05-29 11:51:49 +0000128 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000129 return(ctxt->myDoc->intSubset != NULL);
130}
131
132/**
133 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000134 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000135 *
136 * Does this document has an external subset
137 *
138 * Returns 1 if true
139 */
140int
Daniel Veillard27d88741999-05-29 11:51:49 +0000141hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000142{
Daniel Veillard27d88741999-05-29 11:51:49 +0000143 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000144 return(ctxt->myDoc->extSubset != NULL);
145}
146
147/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000148 * internalSubset:
Daniel Veillard06047432000-04-24 11:33:38 +0000149 * @ctx: the user data (XML parser context)
150 * @name: the root element name
151 * @ExternalID: the external ID
152 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000153 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000154 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000155 */
156void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000157internalSubset(void *ctx, const xmlChar *name,
158 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000159{
Daniel Veillard27d88741999-05-29 11:51:49 +0000160 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardd83eb822000-06-30 18:39:56 +0000161 xmlDtdPtr dtd;
Daniel Veillard517752b1999-04-05 12:20:10 +0000162#ifdef DEBUG_SAX
163 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
164 name, ExternalID, SystemID);
165#endif
Daniel Veillardd83eb822000-06-30 18:39:56 +0000166
167 if (ctxt->myDoc == NULL)
168 return;
169 dtd = xmlGetIntSubset(ctxt->myDoc);
170 if (dtd != NULL) {
171 xmlUnlinkNode((xmlNodePtr) dtd);
172 xmlFreeDtd(dtd);
173 ctxt->myDoc->intSubset = NULL;
174 }
175 ctxt->myDoc->intSubset =
176 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000177}
178
179/**
180 * externalSubset:
181 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000182 * @name: the root element name
183 * @ExternalID: the external ID
184 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000185 *
186 * Callback on external subset declaration.
187 */
188void
189externalSubset(void *ctx, const xmlChar *name,
190 const xmlChar *ExternalID, const xmlChar *SystemID)
191{
192 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
193#ifdef DEBUG_SAX
194 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
195 name, ExternalID, SystemID);
196#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000197 if (((ExternalID != NULL) || (SystemID != NULL)) &&
198 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
199 /*
200 * Try to fetch and parse the external subset.
201 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000202 xmlParserInputPtr oldinput;
203 int oldinputNr;
204 int oldinputMax;
205 xmlParserInputPtr *oldinputTab;
206 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000207 xmlParserInputPtr input = NULL;
208 xmlCharEncoding enc;
Daniel Veillardbe803962000-06-28 23:40:59 +0000209 xmlCharEncoding oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000210
Daniel Veillardb05deb71999-08-10 19:04:08 +0000211 /*
212 * Ask the Entity resolver to load the damn thing
213 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000214 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
215 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000216 SystemID);
217 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000218 return;
219 }
220
Daniel Veillardcf461992000-03-14 18:30:20 +0000221 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
222
Daniel Veillardb05deb71999-08-10 19:04:08 +0000223 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000224 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000225 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000226 oldinput = ctxt->input;
227 oldinputNr = ctxt->inputNr;
228 oldinputMax = ctxt->inputMax;
229 oldinputTab = ctxt->inputTab;
230 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000231 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000232
233 ctxt->inputTab = (xmlParserInputPtr *)
234 xmlMalloc(5 * sizeof(xmlParserInputPtr));
235 if (ctxt->inputTab == NULL) {
236 ctxt->errNo = XML_ERR_NO_MEMORY;
237 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
238 ctxt->sax->error(ctxt->userData,
239 "externalSubset: out of memory\n");
240 ctxt->errNo = XML_ERR_NO_MEMORY;
241 ctxt->input = oldinput;
242 ctxt->inputNr = oldinputNr;
243 ctxt->inputMax = oldinputMax;
244 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000245 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000246 return;
247 }
248 ctxt->inputNr = 0;
249 ctxt->inputMax = 5;
250 ctxt->input = NULL;
251 xmlPushInput(ctxt, input);
252
253 /*
254 * On the fly encoding conversion if needed
255 */
256 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
257 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000258
259 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000260 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000261 input->line = 1;
262 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000263 input->base = ctxt->input->cur;
264 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000265 input->free = NULL;
266
267 /*
268 * let's parse that entity knowing it's an external subset.
269 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000270 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000271
Daniel Veillardcf461992000-03-14 18:30:20 +0000272 /*
273 * Free up the external entities
274 */
275
276 while (ctxt->inputNr > 1)
277 xmlPopInput(ctxt);
278 xmlFreeInputStream(ctxt->input);
279 xmlFree(ctxt->inputTab);
280
281 /*
282 * Restore the parsing context of the main entity
283 */
284 ctxt->input = oldinput;
285 ctxt->inputNr = oldinputNr;
286 ctxt->inputMax = oldinputMax;
287 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000288 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000289 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000290 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000291}
292
293/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000294 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000295 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000296 * @publicId: The public ID of the entity
297 * @systemId: The system ID of the entity
298 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000299 * The entity loader, to control the loading of external entities,
300 * the application can either:
301 * - override this resolveEntity() callback in the SAX block
302 * - or better use the xmlSetExternalEntityLoader() function to
303 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000304 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000305 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000306 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000307xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000308resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000309{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000310 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000311
312#ifdef DEBUG_SAX
313 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
314#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000315
Daniel Veillard686d6b62000-01-03 11:08:02 +0000316 return(xmlLoadExternalEntity((const char *) systemId,
317 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000318}
319
Daniel Veillard97b58771998-10-20 06:14:16 +0000320/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000321 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000322 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000323 * @name: The entity name
324 *
325 * Get an entity by name
326 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000327 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000328 */
329xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000330getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000331{
Daniel Veillard27d88741999-05-29 11:51:49 +0000332 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000333 xmlEntityPtr ret;
334
335#ifdef DEBUG_SAX
336 fprintf(stderr, "SAX.getEntity(%s)\n", name);
337#endif
338
339 ret = xmlGetDocEntity(ctxt->myDoc, name);
340 return(ret);
341}
342
Daniel Veillardb05deb71999-08-10 19:04:08 +0000343/**
344 * getParameterEntity:
345 * @ctx: the user data (XML parser context)
346 * @name: The entity name
347 *
348 * Get a parameter entity by name
349 *
350 * Returns the xmlEntityPtr if found.
351 */
352xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000353getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000354{
355 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
356 xmlEntityPtr ret;
357
358#ifdef DEBUG_SAX
359 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
360#endif
361
362 ret = xmlGetParameterEntity(ctxt->myDoc, name);
363 return(ret);
364}
365
Daniel Veillard517752b1999-04-05 12:20:10 +0000366
367/**
368 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000369 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000370 * @name: the entity name
371 * @type: the entity type
372 * @publicId: The public ID of the entity
373 * @systemId: The system ID of the entity
374 * @content: the entity value (without processing).
375 *
376 * An entity definition has been parsed
377 */
378void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000379entityDecl(void *ctx, const xmlChar *name, int type,
380 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000381{
Daniel Veillard27d88741999-05-29 11:51:49 +0000382 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000383
384#ifdef DEBUG_SAX
385 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
386 name, type, publicId, systemId, content);
387#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000388 if (ctxt->inSubset == 1)
389 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
390 systemId, content);
391 else if (ctxt->inSubset == 2)
392 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
393 systemId, content);
394 else {
395 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
396 ctxt->sax->error(ctxt,
397 "SAX.entityDecl(%s) called while not in subset\n", name);
398 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000399}
400
401/**
402 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000403 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000404 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000405 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000406 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000407 * @def: the type of default value
408 * @defaultValue: the attribute default value
409 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000410 *
411 * An attribute definition has been parsed
412 */
413void
Daniel Veillardcf461992000-03-14 18:30:20 +0000414attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000415 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000416 xmlEnumerationPtr tree)
417{
Daniel Veillard27d88741999-05-29 11:51:49 +0000418 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000419 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000420 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000421
422#ifdef DEBUG_SAX
423 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000424 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000425#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000426 name = xmlSplitQName(ctxt, fullname, &prefix);
427 if (ctxt->inSubset == 1)
428 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
429 name, prefix, type, def, defaultValue, tree);
430 else if (ctxt->inSubset == 2)
431 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
432 name, prefix, type, def, defaultValue, tree);
433 else {
434 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
435 ctxt->sax->error(ctxt,
436 "SAX.attributeDecl(%s) called while not in subset\n", name);
437 return;
438 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000439 if (attr == 0) ctxt->valid = 0;
440 if (ctxt->validate && ctxt->wellFormed &&
441 ctxt->myDoc && ctxt->myDoc->intSubset)
442 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
443 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000444 if (prefix != NULL)
445 xmlFree(prefix);
446 if (name != NULL)
447 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000448}
449
450/**
451 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000452 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000453 * @name: the element name
454 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000455 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000456 *
457 * An element definition has been parsed
458 */
459void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000460elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000461 xmlElementContentPtr content)
462{
Daniel Veillard27d88741999-05-29 11:51:49 +0000463 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000464 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000465
466#ifdef DEBUG_SAX
467 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000468 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000469#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000470
Daniel Veillardcf461992000-03-14 18:30:20 +0000471 if (ctxt->inSubset == 1)
472 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000473 name, type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000474 else if (ctxt->inSubset == 2)
475 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
476 name, type, content);
477 else {
478 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
479 ctxt->sax->error(ctxt,
480 "SAX.elementDecl(%s) called while not in subset\n", name);
481 return;
482 }
483 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000484 if (ctxt->validate && ctxt->wellFormed &&
485 ctxt->myDoc && ctxt->myDoc->intSubset)
486 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000487}
488
489/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000490 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000491 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000492 * @name: The name of the notation
493 * @publicId: The public ID of the entity
494 * @systemId: The system ID of the entity
495 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000497 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000498void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000499notationDecl(void *ctx, const xmlChar *name,
500 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000501{
Daniel Veillard27d88741999-05-29 11:51:49 +0000502 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000503 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000504
Daniel Veillard260a68f1998-08-13 03:39:55 +0000505#ifdef DEBUG_SAX
506 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
507#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000508
Daniel Veillardcf461992000-03-14 18:30:20 +0000509 if (ctxt->inSubset == 1)
510 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000511 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000512 else if (ctxt->inSubset == 2)
513 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
514 publicId, systemId);
515 else {
516 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
517 ctxt->sax->error(ctxt,
518 "SAX.notationDecl(%s) called while not in subset\n", name);
519 return;
520 }
521 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000522 if (ctxt->validate && ctxt->wellFormed &&
523 ctxt->myDoc && ctxt->myDoc->intSubset)
524 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
525 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000526}
527
Daniel Veillard97b58771998-10-20 06:14:16 +0000528/**
529 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000530 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000531 * @name: The name of the entity
532 * @publicId: The public ID of the entity
533 * @systemId: The system ID of the entity
534 * @notationName: the name of the notation
535 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000536 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000537 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000538void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000539unparsedEntityDecl(void *ctx, const xmlChar *name,
540 const xmlChar *publicId, const xmlChar *systemId,
541 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000542{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000543 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000544#ifdef DEBUG_SAX
545 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
546 name, publicId, systemId, notationName);
547#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000548 if (ctxt->validate && ctxt->wellFormed &&
549 ctxt->myDoc && ctxt->myDoc->intSubset)
550 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
551 notationName);
552 xmlAddDocEntity(ctxt->myDoc, name,
553 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
554 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000555}
556
Daniel Veillard97b58771998-10-20 06:14:16 +0000557/**
558 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000559 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000560 * @loc: A SAX Locator
561 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000562 * Receive the document locator at startup, actually xmlDefaultSAXLocator
563 * Everything is available on the context, so this is useless in our case.
564 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000565void
Daniel Veillard27d88741999-05-29 11:51:49 +0000566setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000567{
Daniel Veillard27d88741999-05-29 11:51:49 +0000568 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000569#ifdef DEBUG_SAX
570 fprintf(stderr, "SAX.setDocumentLocator()\n");
571#endif
572}
573
Daniel Veillard97b58771998-10-20 06:14:16 +0000574/**
575 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000576 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000577 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000578 * called when the document start being processed.
579 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000580void
Daniel Veillard27d88741999-05-29 11:51:49 +0000581startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000582{
Daniel Veillard27d88741999-05-29 11:51:49 +0000583 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000584 xmlDocPtr doc;
585
Daniel Veillard260a68f1998-08-13 03:39:55 +0000586#ifdef DEBUG_SAX
587 fprintf(stderr, "SAX.startDocument()\n");
588#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000589 if (ctxt->html) {
590 if (ctxt->myDoc == NULL)
591 ctxt->myDoc = htmlNewDoc(NULL, NULL);
592 } else {
593 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
594 if (doc != NULL) {
595 if (ctxt->encoding != NULL)
596 doc->encoding = xmlStrdup(ctxt->encoding);
597 else
598 doc->encoding = NULL;
599 doc->standalone = ctxt->standalone;
600 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000601 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000602}
603
Daniel Veillard97b58771998-10-20 06:14:16 +0000604/**
605 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000606 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000607 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000608 * called when the document end has been detected.
609 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000610void
Daniel Veillard27d88741999-05-29 11:51:49 +0000611endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000612{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000613 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000614#ifdef DEBUG_SAX
615 fprintf(stderr, "SAX.endDocument()\n");
616#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000617 if (ctxt->validate && ctxt->wellFormed &&
618 ctxt->myDoc && ctxt->myDoc->intSubset)
619 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000620
621 /*
622 * Grab the encoding if it was added on-the-fly
623 */
624 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
625 (ctxt->myDoc->encoding == NULL)) {
626 ctxt->myDoc->encoding = ctxt->encoding;
627 ctxt->encoding = NULL;
628 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000629 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
630 (ctxt->myDoc->encoding == NULL)) {
631 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
632 }
633 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
634 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
635 ctxt->myDoc->charset = ctxt->charset;
636 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000637}
638
Daniel Veillard97b58771998-10-20 06:14:16 +0000639/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000640 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000641 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000642 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000643 * @value: The attribute value
644 *
645 * Handle an attribute that has been read by the parser.
646 * The default handling is to convert the attribute into an
647 * DOM subtree and past it in a new xmlAttr element added to
648 * the element.
649 */
650void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000651attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000652{
Daniel Veillard27d88741999-05-29 11:51:49 +0000653 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000654 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000655 xmlChar *name;
656 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000657 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000658 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000659
660/****************
661#ifdef DEBUG_SAX
662 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
663#endif
664 ****************/
665 /*
666 * Split the full name into a namespace prefix and the tag name
667 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000668 name = xmlSplitQName(ctxt, fullname, &ns);
669
670 /*
671 * Do the last stave of the attribute normalization
672 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000673 if (ctxt->html)
674 nval = NULL;
675 else
676 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
Daniel Veillardcf461992000-03-14 18:30:20 +0000677 ctxt->node, fullname, value);
678 if (nval != NULL)
679 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000680
681 /*
682 * Check whether it's a namespace definition
683 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000684 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000685 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
686 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000687 xmlURIPtr uri;
688
689 uri = xmlParseURI((const char *)value);
690 if (uri == NULL) {
691 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
692 ctxt->sax->warning(ctxt->userData,
693 "nmlns: %s not a valid URI\n", value);
694 } else {
695 if (uri->scheme == NULL) {
696 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
697 ctxt->sax->warning(ctxt->userData,
698 "nmlns: URI %s is not absolute\n", value);
699 }
700 xmlFreeURI(uri);
701 }
702
Daniel Veillard517752b1999-04-05 12:20:10 +0000703 /* a default namespace definition */
704 xmlNewNs(ctxt->node, value, NULL);
705 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000706 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000707 if (nval != NULL)
708 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000709 return;
710 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000711 if ((!ctxt->html) &&
712 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000713 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000714 /*
715 * Validate also for namespace decls, they are attributes from
716 * an XML-1.0 perspective
717 TODO ... doesn't map well with current API
718 if (ctxt->validate && ctxt->wellFormed &&
719 ctxt->myDoc && ctxt->myDoc->intSubset)
720 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
721 ctxt->node, ret, value);
722 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000723 /* a standard namespace definition */
724 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000725 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000726 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000727 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000728 if (nval != NULL)
729 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000730 return;
731 }
732
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000733 if (ns != NULL)
734 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
735 else {
736 namespace = NULL;
737 }
738
Daniel Veillardb96e6431999-08-29 21:02:19 +0000739 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
740 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000741
Daniel Veillardb96e6431999-08-29 21:02:19 +0000742 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000743 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
744 xmlNodePtr tmp;
745
746 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
747 tmp = ret->children;
748 while (tmp != NULL) {
749 tmp->parent = (xmlNodePtr) ret;
750 if (tmp->next == NULL)
751 ret->last = tmp;
752 tmp = tmp->next;
753 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000754 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000755 ret->children = xmlNewDocText(ctxt->myDoc, value);
756 ret->last = ret->children;
757 if (ret->children != NULL)
758 ret->children->parent = (xmlNodePtr) ret;
759 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000760 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000761
Daniel Veillardbe803962000-06-28 23:40:59 +0000762 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000763 ctxt->myDoc && ctxt->myDoc->intSubset) {
764
765 /*
766 * If we don't substitute entities, the validation should be
767 * done on a value with replaced entities anyway.
768 */
769 if (!ctxt->replaceEntities) {
770 xmlChar *val;
771
772 ctxt->depth++;
773 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
774 0,0,0);
775 ctxt->depth--;
776 if (val == NULL)
777 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
778 ctxt->myDoc, ctxt->node, ret, value);
779 else {
780 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
781 ctxt->myDoc, ctxt->node, ret, val);
782 xmlFree(val);
783 }
784 } else {
785 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000786 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000787 }
788 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000789 /*
790 * when validating, the ID registration is done at the attribute
791 * validation level. Otherwise we have to do specific handling here.
792 */
793 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
794 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000795 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
796 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000797 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000798
Daniel Veillardcf461992000-03-14 18:30:20 +0000799 if (nval != NULL)
800 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000801 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000802 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000803 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000804 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000805}
806
807/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000808 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000809 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000810 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000811 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000812 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000813 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000814 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000815void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000816startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000817{
Daniel Veillard27d88741999-05-29 11:51:49 +0000818 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000819 xmlNodePtr ret;
820 xmlNodePtr parent = ctxt->node;
821 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000822 xmlChar *name;
823 xmlChar *prefix;
824 const xmlChar *att;
825 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000826 int i;
827
Daniel Veillard260a68f1998-08-13 03:39:55 +0000828#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000829 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000830#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000831
832 /*
833 * First check on validity:
834 */
835 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
836 ((ctxt->myDoc->intSubset == NULL) ||
837 ((ctxt->myDoc->intSubset->notations == NULL) &&
838 (ctxt->myDoc->intSubset->elements == NULL) &&
839 (ctxt->myDoc->intSubset->attributes == NULL) &&
840 (ctxt->myDoc->intSubset->entities == NULL)))) {
841 if (ctxt->vctxt.error != NULL) {
842 ctxt->vctxt.error(ctxt->vctxt.userData,
843 "Validation failed: no DTD found !\n");
844 }
845 ctxt->validate = 0;
846 }
847
848
Daniel Veillard517752b1999-04-05 12:20:10 +0000849 /*
850 * Split the full name into a namespace prefix and the tag name
851 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000852 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000853
854
855 /*
856 * Note : the namespace resolution is deferred until the end of the
857 * attributes parsing, since local namespace can be defined as
858 * an attribute at this level.
859 */
860 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
861 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000862 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000863#ifdef DEBUG_SAX_TREE
864 fprintf(stderr, "Setting %s as root\n", name);
865#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000866 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000867 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000868 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000869 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000870 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000871
872 /*
873 * We are parsing a new node.
874 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000875#ifdef DEBUG_SAX_TREE
876 fprintf(stderr, "pushing(%s)\n", name);
877#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000878 nodePush(ctxt, ret);
879
880 /*
881 * Link the child element
882 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000883 if (parent != NULL) {
884 if (parent->type == XML_ELEMENT_NODE) {
885#ifdef DEBUG_SAX_TREE
886 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
887#endif
888 xmlAddChild(parent, ret);
889 } else {
890#ifdef DEBUG_SAX_TREE
891 fprintf(stderr, "adding sibling %s to ", name);
892 xmlDebugDumpOneNode(stderr, parent, 0);
893#endif
894 xmlAddSibling(parent, ret);
895 }
896 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000897
898 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000899 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000900 */
901 if (atts != NULL) {
902 i = 0;
903 att = atts[i++];
904 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000905 if (!ctxt->html) {
906 while ((att != NULL) && (value != NULL)) {
907 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
908 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000909
Daniel Veillardbe803962000-06-28 23:40:59 +0000910 att = atts[i++];
911 value = atts[i++];
912 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000913 }
914 }
915
916 /*
917 * Search the namespace, note that since the attributes have been
918 * processed, the local namespaces are available.
919 */
920 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
921 if ((ns == NULL) && (parent != NULL))
922 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
923 xmlSetNs(ret, ns);
924
Daniel Veillardbe803962000-06-28 23:40:59 +0000925 /*
926 * process all the other attributes
927 */
928 if (atts != NULL) {
929 i = 0;
930 att = atts[i++];
931 value = atts[i++];
932 if (ctxt->html) {
933 while (att != NULL) {
934 attribute(ctxt, att, value);
935 att = atts[i++];
936 value = atts[i++];
937 }
938 } else {
939 while ((att != NULL) && (value != NULL)) {
940 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
941 attribute(ctxt, att, value);
942
943 /*
944 * Next ones
945 */
946 att = atts[i++];
947 value = atts[i++];
948 }
949 }
950 }
951
952 /*
953 * If it's the Document root, finish the Dtd validation and
954 * check the document root element for validity
955 */
956 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
957 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
958 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
959 ctxt->vctxt.finishDtd = 1;
960 }
961
Daniel Veillard517752b1999-04-05 12:20:10 +0000962 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000963 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000964 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000965 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000966
Daniel Veillard260a68f1998-08-13 03:39:55 +0000967}
968
Daniel Veillard97b58771998-10-20 06:14:16 +0000969/**
970 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000971 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000972 * @name: The element name
973 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000974 * called when the end of an element has been detected.
975 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000976void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000977endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000978{
Daniel Veillard27d88741999-05-29 11:51:49 +0000979 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000980 xmlParserNodeInfo node_info;
981 xmlNodePtr cur = ctxt->node;
982
Daniel Veillard260a68f1998-08-13 03:39:55 +0000983#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000984 if (name == NULL)
985 fprintf(stderr, "SAX.endElement(NULL)\n");
986 else
987 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000988#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000989
990 /* Capture end position and add node */
991 if (cur != NULL && ctxt->record_info) {
992 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
993 node_info.end_line = ctxt->input->line;
994 node_info.node = cur;
995 xmlParserAddNodeInfo(ctxt, &node_info);
996 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000997 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000998
Daniel Veillardb05deb71999-08-10 19:04:08 +0000999 if (ctxt->validate && ctxt->wellFormed &&
1000 ctxt->myDoc && ctxt->myDoc->intSubset)
1001 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1002 cur);
1003
1004
Daniel Veillard517752b1999-04-05 12:20:10 +00001005 /*
1006 * end of parsing of this node.
1007 */
Daniel Veillardb96e6431999-08-29 21:02:19 +00001008#ifdef DEBUG_SAX_TREE
1009 fprintf(stderr, "popping(%s)\n", cur->name);
1010#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001011 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001012}
1013
Daniel Veillard97b58771998-10-20 06:14:16 +00001014/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001015 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001016 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001017 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001018 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001019 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001020 */
1021void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001022reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001023{
Daniel Veillard27d88741999-05-29 11:51:49 +00001024 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001025 xmlNodePtr ret;
1026
Daniel Veillard11e00581998-10-24 18:27:49 +00001027#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001028 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001029#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001030 if (name[0] == '#')
1031 ret = xmlNewCharRef(ctxt->myDoc, name);
1032 else
1033 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001034#ifdef DEBUG_SAX_TREE
1035 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
1036#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001037 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001038}
1039
1040/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001041 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001042 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001043 * @ch: a xmlChar string
1044 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001045 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001046 * receiving some chars from the parser.
1047 * Question: how much at a time ???
1048 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001049void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001050characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001051{
Daniel Veillard27d88741999-05-29 11:51:49 +00001052 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001053 xmlNodePtr lastChild;
1054
1055#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001056 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001057#endif
1058 /*
1059 * Handle the data if any. If there is no child
1060 * add it as content, otherwise if the last child is text,
1061 * concatenate it, else create a new node of type text.
1062 */
1063
Daniel Veillard35008381999-10-25 13:15:52 +00001064 if (ctxt->node == NULL) {
1065#ifdef DEBUG_SAX_TREE
1066 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1067#endif
1068 return;
1069 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001070 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001071#ifdef DEBUG_SAX_TREE
1072 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1073#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001074
1075 /*
1076 * Here we needed an accelerator mechanism in case of very large
1077 * elements. Use an attribute in the structure !!!
1078 */
1079 if (lastChild == NULL) {
1080 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001081 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001082#ifndef XML_USE_BUFFER_CONTENT
1083 if (ctxt->node->children != NULL) {
1084 ctxt->nodelen = len;
1085 ctxt->nodemem = len + 1;
1086 }
1087#endif
1088 } else {
1089 if (xmlNodeIsText(lastChild)) {
1090#ifndef XML_USE_BUFFER_CONTENT
1091 /*
1092 * The whole point of maintaining nodelen and nodemem,
1093 * xmlTextConcat is too costly, i.e. compute lenght,
1094 * reallocate a new buffer, move data, append ch. Here
1095 * We try to minimaze realloc() uses and avoid copying
1096 * and recomputing lenght over and over.
1097 */
1098 if (ctxt->nodelen + len >= ctxt->nodemem) {
1099 xmlChar *newbuf;
1100 int size;
1101
1102 size = ctxt->nodemem + len;
1103 size *= 2;
1104 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1105 if (newbuf == NULL) {
1106 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1107 ctxt->sax->error(ctxt->userData,
1108 "SAX.characters(): out of memory\n");
1109 return;
1110 }
1111 ctxt->nodemem = size;
1112 lastChild->content = newbuf;
1113 }
1114 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1115 ctxt->nodelen += len;
1116 lastChild->content[ctxt->nodelen] = 0;
1117#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001118 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001119#endif
1120 } else {
1121 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001122 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001123 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001124#ifndef XML_USE_BUFFER_CONTENT
1125 if (ctxt->node->children != NULL) {
1126 ctxt->nodelen = len;
1127 ctxt->nodemem = len + 1;
1128 }
1129#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001130 }
1131 }
1132}
1133
Daniel Veillard97b58771998-10-20 06:14:16 +00001134/**
1135 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001136 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001137 * @ch: a xmlChar string
1138 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001139 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001140 * receiving some ignorable whitespaces from the parser.
1141 * Question: how much at a time ???
1142 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001143void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001144ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001145{
Daniel Veillard27d88741999-05-29 11:51:49 +00001146 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001148 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001149#endif
1150}
1151
Daniel Veillard97b58771998-10-20 06:14:16 +00001152/**
1153 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001154 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001155 * @target: the target name
1156 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001157 *
1158 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001159 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001160void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001161processingInstruction(void *ctx, const xmlChar *target,
1162 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001163{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001164 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1165 xmlNodePtr ret;
1166 xmlNodePtr parent = ctxt->node;
1167
Daniel Veillard260a68f1998-08-13 03:39:55 +00001168#ifdef DEBUG_SAX
1169 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1170#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001171
1172 ret = xmlNewPI(target, data);
1173 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001174 parent = ctxt->node;
1175
1176 if (ctxt->inSubset == 1) {
1177 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1178 return;
1179 } else if (ctxt->inSubset == 2) {
1180 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1181 return;
1182 }
1183 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001184#ifdef DEBUG_SAX_TREE
1185 fprintf(stderr, "Setting PI %s as root\n", target);
1186#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001187 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1188 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001189 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001190 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001191#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001192 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001193#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001194 xmlAddChild(parent, ret);
1195 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001196#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001197 fprintf(stderr, "adding PI %s sibling to ", target);
1198 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001199#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001200 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001201 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001202}
1203
Daniel Veillard517752b1999-04-05 12:20:10 +00001204/**
1205 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001206 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001207 * @href: the namespace associated URN
1208 * @prefix: the namespace prefix
1209 *
1210 * An old global namespace has been parsed.
1211 */
1212void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001213globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001214{
Daniel Veillard27d88741999-05-29 11:51:49 +00001215 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001216#ifdef DEBUG_SAX
1217 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1218#endif
1219 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1220}
1221
1222/**
1223 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001224 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001225 * @name: the namespace prefix
1226 *
1227 * Set the current element namespace.
1228 */
Daniel Veillard06047432000-04-24 11:33:38 +00001229
Daniel Veillard517752b1999-04-05 12:20:10 +00001230void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001231setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001232{
Daniel Veillard27d88741999-05-29 11:51:49 +00001233 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001234 xmlNsPtr ns;
1235 xmlNodePtr parent;
1236
1237#ifdef DEBUG_SAX
1238 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1239#endif
1240 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1241 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1242 if (ctxt->nodeNr >= 2) {
1243 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1244 if (parent != NULL)
1245 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1246 }
1247 }
1248 xmlSetNs(ctxt->node, ns);
1249}
1250
1251/**
1252 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001253 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001254 *
1255 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001256 *
1257 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001258 */
Daniel Veillard06047432000-04-24 11:33:38 +00001259
Daniel Veillard517752b1999-04-05 12:20:10 +00001260xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001261getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001262{
Daniel Veillard27d88741999-05-29 11:51:49 +00001263 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001264 xmlNsPtr ret;
1265
1266#ifdef DEBUG_SAX
1267 fprintf(stderr, "SAX.getNamespace()\n");
1268#endif
1269 ret = ctxt->node->ns;
1270 return(ret);
1271}
1272
1273/**
1274 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001275 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001276 * @namespace: the namespace to check against
1277 *
1278 * Check that the current element namespace is the same as the
1279 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001280 *
1281 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001282 */
Daniel Veillard06047432000-04-24 11:33:38 +00001283
Daniel Veillard517752b1999-04-05 12:20:10 +00001284int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001285checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001286{
Daniel Veillard27d88741999-05-29 11:51:49 +00001287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001288 xmlNodePtr cur = ctxt->node;
1289
1290#ifdef DEBUG_SAX
1291 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1292#endif
1293
1294 /*
1295 * Check that the Name in the ETag is the same as in the STag.
1296 */
1297 if (namespace == NULL) {
1298 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1299 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1300 ctxt->sax->error(ctxt,
1301 "End tags for %s don't hold the namespace %s\n",
1302 cur->name, cur->ns->prefix);
1303 ctxt->wellFormed = 0;
1304 }
1305 } else {
1306 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1307 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1308 ctxt->sax->error(ctxt,
1309 "End tags %s holds a prefix %s not used by the open tag\n",
1310 cur->name, namespace);
1311 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001312 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001313 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1314 ctxt->sax->error(ctxt,
1315 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1316 cur->name, cur->ns->prefix, namespace);
1317 ctxt->wellFormed = 0;
1318 } else
1319 return(1);
1320 }
1321 return(0);
1322}
1323
1324/**
1325 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001326 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001327 * @href: the namespace associated URN
1328 * @prefix: the namespace prefix
1329 *
1330 * A namespace has been parsed.
1331 */
1332void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001333namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001334{
Daniel Veillard27d88741999-05-29 11:51:49 +00001335 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001336#ifdef DEBUG_SAX
1337 if (prefix == NULL)
1338 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1339 else
1340 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1341#endif
1342 xmlNewNs(ctxt->node, href, prefix);
1343}
1344
1345/**
1346 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001347 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001348 * @value: the comment content
1349 *
1350 * A comment has been parsed.
1351 */
1352void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001353comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001354{
Daniel Veillard27d88741999-05-29 11:51:49 +00001355 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001356 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001357 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001358
Daniel Veillard517752b1999-04-05 12:20:10 +00001359#ifdef DEBUG_SAX
1360 fprintf(stderr, "SAX.comment(%s)\n", value);
1361#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001362 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001363 if (ret == NULL) return;
1364
Daniel Veillardcf461992000-03-14 18:30:20 +00001365 if (ctxt->inSubset == 1) {
1366 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1367 return;
1368 } else if (ctxt->inSubset == 2) {
1369 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1370 return;
1371 }
1372 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001373#ifdef DEBUG_SAX_TREE
1374 fprintf(stderr, "Setting comment as root\n");
1375#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001376 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1377 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001378 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001379 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001380#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001381 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001382#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001383 xmlAddChild(parent, ret);
1384 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001385#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001386 fprintf(stderr, "adding comment sibling to ");
1387 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001388#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001389 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001390 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001391}
1392
1393/**
1394 * cdataBlock:
1395 * @ctx: the user data (XML parser context)
1396 * @value: The pcdata content
1397 * @len: the block length
1398 *
1399 * called when a pcdata block has been parsed
1400 */
1401void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001402cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001403{
1404 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001405 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001406
1407#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001408 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001409#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001410 lastChild = xmlGetLastChild(ctxt->node);
1411#ifdef DEBUG_SAX_TREE
1412 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1413#endif
1414 if ((lastChild != NULL) &&
1415 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1416 xmlTextConcat(lastChild, value, len);
1417 } else {
1418 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1419 xmlAddChild(ctxt->node, ret);
1420 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001421}
1422
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001423/*
1424 * Default handler for XML, builds the DOM tree
1425 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001426xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001427 internalSubset,
1428 isStandalone,
1429 hasInternalSubset,
1430 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001431 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001432 getEntity,
1433 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001434 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001435 attributeDecl,
1436 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001437 unparsedEntityDecl,
1438 setDocumentLocator,
1439 startDocument,
1440 endDocument,
1441 startElement,
1442 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001443 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001444 characters,
1445 ignorableWhitespace,
1446 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001447 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001448 xmlParserWarning,
1449 xmlParserError,
1450 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001451 getParameterEntity,
1452 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001453 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001454};
1455
Daniel Veillard97b58771998-10-20 06:14:16 +00001456/**
1457 * xmlDefaultSAXHandlerInit:
1458 *
1459 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001460 */
1461void
1462xmlDefaultSAXHandlerInit(void)
1463{
Daniel Veillard517752b1999-04-05 12:20:10 +00001464 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001465 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001466 xmlDefaultSAXHandler.isStandalone = isStandalone;
1467 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1468 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001469 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001470 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001471 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001472 xmlDefaultSAXHandler.entityDecl = entityDecl;
1473 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1474 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001475 xmlDefaultSAXHandler.notationDecl = notationDecl;
1476 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1477 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1478 xmlDefaultSAXHandler.startDocument = startDocument;
1479 xmlDefaultSAXHandler.endDocument = endDocument;
1480 xmlDefaultSAXHandler.startElement = startElement;
1481 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001482 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001484 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001485 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1486 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001487 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001488 if (xmlGetWarningsDefaultValue == 0)
1489 xmlDefaultSAXHandler.warning = NULL;
1490 else
1491 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001492 xmlDefaultSAXHandler.error = xmlParserError;
1493 xmlDefaultSAXHandler.fatalError = xmlParserError;
1494}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001495
1496/*
1497 * Default handler for HTML, builds the DOM tree
1498 */
1499xmlSAXHandler htmlDefaultSAXHandler = {
Daniel Veillardd83eb822000-06-30 18:39:56 +00001500 internalSubset,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001501 NULL,
1502 NULL,
1503 NULL,
1504 NULL,
1505 getEntity,
1506 NULL,
1507 NULL,
1508 NULL,
1509 NULL,
1510 NULL,
1511 setDocumentLocator,
1512 startDocument,
1513 endDocument,
1514 startElement,
1515 endElement,
1516 NULL,
1517 characters,
1518 ignorableWhitespace,
1519 NULL,
1520 comment,
1521 xmlParserWarning,
1522 xmlParserError,
1523 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001524 getParameterEntity,
1525 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001526 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001527};
1528
1529/**
1530 * htmlDefaultSAXHandlerInit:
1531 *
1532 * Initialize the default SAX handler
1533 */
1534void
1535htmlDefaultSAXHandlerInit(void)
1536{
Daniel Veillardd83eb822000-06-30 18:39:56 +00001537 htmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001538 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001539 htmlDefaultSAXHandler.isStandalone = NULL;
1540 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1541 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1542 htmlDefaultSAXHandler.resolveEntity = NULL;
1543 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001544 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001545 htmlDefaultSAXHandler.entityDecl = NULL;
1546 htmlDefaultSAXHandler.attributeDecl = NULL;
1547 htmlDefaultSAXHandler.elementDecl = NULL;
1548 htmlDefaultSAXHandler.notationDecl = NULL;
1549 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1550 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1551 htmlDefaultSAXHandler.startDocument = startDocument;
1552 htmlDefaultSAXHandler.endDocument = endDocument;
1553 htmlDefaultSAXHandler.startElement = startElement;
1554 htmlDefaultSAXHandler.endElement = endElement;
1555 htmlDefaultSAXHandler.reference = NULL;
1556 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001557 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001558 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1559 htmlDefaultSAXHandler.processingInstruction = NULL;
1560 htmlDefaultSAXHandler.comment = comment;
1561 htmlDefaultSAXHandler.warning = xmlParserWarning;
1562 htmlDefaultSAXHandler.error = xmlParserError;
1563 htmlDefaultSAXHandler.fatalError = xmlParserError;
1564}