blob: 68e2d316fe0371ac877955c598e4ab3b8e45fcc5 [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 Veillard260a68f1998-08-13 03:39:55 +000028
29/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000030/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000031
Daniel Veillard97b58771998-10-20 06:14:16 +000032/**
33 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000034 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000035 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000036 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000037 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000038 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000039 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000040const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000041getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000042{
Daniel Veillard27d88741999-05-29 11:51:49 +000043 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000044 return(NULL);
45}
46
Daniel Veillard97b58771998-10-20 06:14:16 +000047/**
48 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000049 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000050 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000051 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000052 * http://www.sgmlsource.com/dtds/memo.dtd
53 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000054 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000055 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000056const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000057getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000058{
Daniel Veillard27d88741999-05-29 11:51:49 +000059 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000060 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000061}
62
Daniel Veillard97b58771998-10-20 06:14:16 +000063/**
64 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000065 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000066 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000067 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000068 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000069 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000070 */
Daniel Veillard97b58771998-10-20 06:14:16 +000071int
Daniel Veillard27d88741999-05-29 11:51:49 +000072getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000073{
Daniel Veillard27d88741999-05-29 11:51:49 +000074 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000075 return(ctxt->input->line);
76}
Daniel Veillard97b58771998-10-20 06:14:16 +000077
78/**
79 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000080 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000081 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000082 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000083 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000084 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000085 */
Daniel Veillard97b58771998-10-20 06:14:16 +000086int
Daniel Veillard27d88741999-05-29 11:51:49 +000087getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000088{
Daniel Veillard27d88741999-05-29 11:51:49 +000089 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 return(ctxt->input->col);
91}
92
93/*
94 * The default SAX Locator.
95 */
96
97xmlSAXLocator xmlDefaultSAXLocator = {
98 getPublicId, getSystemId, getLineNumber, getColumnNumber
99};
100
Daniel Veillard97b58771998-10-20 06:14:16 +0000101/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000102 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000103 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000104 *
105 * Is this document tagged standalone ?
106 *
107 * Returns 1 if true
108 */
109int
Daniel Veillard27d88741999-05-29 11:51:49 +0000110isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000111{
Daniel Veillard27d88741999-05-29 11:51:49 +0000112 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000113 return(ctxt->myDoc->standalone == 1);
114}
115
116/**
117 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000118 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000119 *
120 * Does this document has an internal subset
121 *
122 * Returns 1 if true
123 */
124int
Daniel Veillard27d88741999-05-29 11:51:49 +0000125hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000126{
Daniel Veillard27d88741999-05-29 11:51:49 +0000127 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000128 return(ctxt->myDoc->intSubset != NULL);
129}
130
131/**
132 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000133 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000134 *
135 * Does this document has an external subset
136 *
137 * Returns 1 if true
138 */
139int
Daniel Veillard27d88741999-05-29 11:51:49 +0000140hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000141{
Daniel Veillard27d88741999-05-29 11:51:49 +0000142 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000143 return(ctxt->myDoc->extSubset != NULL);
144}
145
146/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000147 * internalSubset:
Daniel Veillard06047432000-04-24 11:33:38 +0000148 * @ctx: the user data (XML parser context)
149 * @name: the root element name
150 * @ExternalID: the external ID
151 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000152 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000153 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000154 */
155void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000156internalSubset(void *ctx, const xmlChar *name,
157 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000158{
Daniel Veillard27d88741999-05-29 11:51:49 +0000159 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000160#ifdef DEBUG_SAX
161 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
162 name, ExternalID, SystemID);
163#endif
164 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000165}
166
167/**
168 * externalSubset:
169 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000170 * @name: the root element name
171 * @ExternalID: the external ID
172 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000173 *
174 * Callback on external subset declaration.
175 */
176void
177externalSubset(void *ctx, const xmlChar *name,
178 const xmlChar *ExternalID, const xmlChar *SystemID)
179{
180 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
181#ifdef DEBUG_SAX
182 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
183 name, ExternalID, SystemID);
184#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000185 if (((ExternalID != NULL) || (SystemID != NULL)) &&
186 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
187 /*
188 * Try to fetch and parse the external subset.
189 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000190 xmlParserInputPtr oldinput;
191 int oldinputNr;
192 int oldinputMax;
193 xmlParserInputPtr *oldinputTab;
194 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000195 xmlParserInputPtr input = NULL;
196 xmlCharEncoding enc;
Daniel Veillardbe803962000-06-28 23:40:59 +0000197 xmlCharEncoding oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000198
Daniel Veillardb05deb71999-08-10 19:04:08 +0000199 /*
200 * Ask the Entity resolver to load the damn thing
201 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000202 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
203 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000204 SystemID);
205 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000206 return;
207 }
208
Daniel Veillardcf461992000-03-14 18:30:20 +0000209 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
210
Daniel Veillardb05deb71999-08-10 19:04:08 +0000211 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000212 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000213 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000214 oldinput = ctxt->input;
215 oldinputNr = ctxt->inputNr;
216 oldinputMax = ctxt->inputMax;
217 oldinputTab = ctxt->inputTab;
218 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000219 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000220
221 ctxt->inputTab = (xmlParserInputPtr *)
222 xmlMalloc(5 * sizeof(xmlParserInputPtr));
223 if (ctxt->inputTab == NULL) {
224 ctxt->errNo = XML_ERR_NO_MEMORY;
225 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
226 ctxt->sax->error(ctxt->userData,
227 "externalSubset: out of memory\n");
228 ctxt->errNo = XML_ERR_NO_MEMORY;
229 ctxt->input = oldinput;
230 ctxt->inputNr = oldinputNr;
231 ctxt->inputMax = oldinputMax;
232 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000233 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000234 return;
235 }
236 ctxt->inputNr = 0;
237 ctxt->inputMax = 5;
238 ctxt->input = NULL;
239 xmlPushInput(ctxt, input);
240
241 /*
242 * On the fly encoding conversion if needed
243 */
244 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
245 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000246
247 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000248 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000249 input->line = 1;
250 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000251 input->base = ctxt->input->cur;
252 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000253 input->free = NULL;
254
255 /*
256 * let's parse that entity knowing it's an external subset.
257 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000258 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000259
Daniel Veillardcf461992000-03-14 18:30:20 +0000260 /*
261 * Free up the external entities
262 */
263
264 while (ctxt->inputNr > 1)
265 xmlPopInput(ctxt);
266 xmlFreeInputStream(ctxt->input);
267 xmlFree(ctxt->inputTab);
268
269 /*
270 * Restore the parsing context of the main entity
271 */
272 ctxt->input = oldinput;
273 ctxt->inputNr = oldinputNr;
274 ctxt->inputMax = oldinputMax;
275 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000276 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000277 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000278 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000279}
280
281/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000282 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000283 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000284 * @publicId: The public ID of the entity
285 * @systemId: The system ID of the entity
286 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000287 * The entity loader, to control the loading of external entities,
288 * the application can either:
289 * - override this resolveEntity() callback in the SAX block
290 * - or better use the xmlSetExternalEntityLoader() function to
291 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000292 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000293 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000294 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000295xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000296resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000297{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299
300#ifdef DEBUG_SAX
301 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
302#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000303
Daniel Veillard686d6b62000-01-03 11:08:02 +0000304 return(xmlLoadExternalEntity((const char *) systemId,
305 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000306}
307
Daniel Veillard97b58771998-10-20 06:14:16 +0000308/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000309 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000310 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000311 * @name: The entity name
312 *
313 * Get an entity by name
314 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000315 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000316 */
317xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000318getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000319{
Daniel Veillard27d88741999-05-29 11:51:49 +0000320 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000321 xmlEntityPtr ret;
322
323#ifdef DEBUG_SAX
324 fprintf(stderr, "SAX.getEntity(%s)\n", name);
325#endif
326
327 ret = xmlGetDocEntity(ctxt->myDoc, name);
328 return(ret);
329}
330
Daniel Veillardb05deb71999-08-10 19:04:08 +0000331/**
332 * getParameterEntity:
333 * @ctx: the user data (XML parser context)
334 * @name: The entity name
335 *
336 * Get a parameter entity by name
337 *
338 * Returns the xmlEntityPtr if found.
339 */
340xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000341getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000342{
343 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
344 xmlEntityPtr ret;
345
346#ifdef DEBUG_SAX
347 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
348#endif
349
350 ret = xmlGetParameterEntity(ctxt->myDoc, name);
351 return(ret);
352}
353
Daniel Veillard517752b1999-04-05 12:20:10 +0000354
355/**
356 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000357 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000358 * @name: the entity name
359 * @type: the entity type
360 * @publicId: The public ID of the entity
361 * @systemId: The system ID of the entity
362 * @content: the entity value (without processing).
363 *
364 * An entity definition has been parsed
365 */
366void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000367entityDecl(void *ctx, const xmlChar *name, int type,
368 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000369{
Daniel Veillard27d88741999-05-29 11:51:49 +0000370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000371
372#ifdef DEBUG_SAX
373 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
374 name, type, publicId, systemId, content);
375#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000376 if (ctxt->inSubset == 1)
377 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
378 systemId, content);
379 else if (ctxt->inSubset == 2)
380 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
381 systemId, content);
382 else {
383 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
384 ctxt->sax->error(ctxt,
385 "SAX.entityDecl(%s) called while not in subset\n", name);
386 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000387}
388
389/**
390 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000391 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000392 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000393 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000394 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000395 * @def: the type of default value
396 * @defaultValue: the attribute default value
397 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000398 *
399 * An attribute definition has been parsed
400 */
401void
Daniel Veillardcf461992000-03-14 18:30:20 +0000402attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000403 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000404 xmlEnumerationPtr tree)
405{
Daniel Veillard27d88741999-05-29 11:51:49 +0000406 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000407 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000408 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000409
410#ifdef DEBUG_SAX
411 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000412 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000413#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000414 name = xmlSplitQName(ctxt, fullname, &prefix);
415 if (ctxt->inSubset == 1)
416 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
417 name, prefix, type, def, defaultValue, tree);
418 else if (ctxt->inSubset == 2)
419 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
420 name, prefix, type, def, defaultValue, tree);
421 else {
422 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
423 ctxt->sax->error(ctxt,
424 "SAX.attributeDecl(%s) called while not in subset\n", name);
425 return;
426 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000427 if (attr == 0) ctxt->valid = 0;
428 if (ctxt->validate && ctxt->wellFormed &&
429 ctxt->myDoc && ctxt->myDoc->intSubset)
430 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
431 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000432 if (prefix != NULL)
433 xmlFree(prefix);
434 if (name != NULL)
435 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000436}
437
438/**
439 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000440 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000441 * @name: the element name
442 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000443 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000444 *
445 * An element definition has been parsed
446 */
447void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000448elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000449 xmlElementContentPtr content)
450{
Daniel Veillard27d88741999-05-29 11:51:49 +0000451 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000452 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000453
454#ifdef DEBUG_SAX
455 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000456 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000457#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000458
Daniel Veillardcf461992000-03-14 18:30:20 +0000459 if (ctxt->inSubset == 1)
460 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000461 name, type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000462 else if (ctxt->inSubset == 2)
463 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
464 name, type, content);
465 else {
466 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
467 ctxt->sax->error(ctxt,
468 "SAX.elementDecl(%s) called while not in subset\n", name);
469 return;
470 }
471 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000472 if (ctxt->validate && ctxt->wellFormed &&
473 ctxt->myDoc && ctxt->myDoc->intSubset)
474 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000475}
476
477/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000478 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000479 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000480 * @name: The name of the notation
481 * @publicId: The public ID of the entity
482 * @systemId: The system ID of the entity
483 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000485 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000486void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000487notationDecl(void *ctx, const xmlChar *name,
488 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000489{
Daniel Veillard27d88741999-05-29 11:51:49 +0000490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000491 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000492
Daniel Veillard260a68f1998-08-13 03:39:55 +0000493#ifdef DEBUG_SAX
494 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
495#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000496
Daniel Veillardcf461992000-03-14 18:30:20 +0000497 if (ctxt->inSubset == 1)
498 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000499 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000500 else if (ctxt->inSubset == 2)
501 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
502 publicId, systemId);
503 else {
504 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
505 ctxt->sax->error(ctxt,
506 "SAX.notationDecl(%s) called while not in subset\n", name);
507 return;
508 }
509 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000510 if (ctxt->validate && ctxt->wellFormed &&
511 ctxt->myDoc && ctxt->myDoc->intSubset)
512 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
513 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000514}
515
Daniel Veillard97b58771998-10-20 06:14:16 +0000516/**
517 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000518 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000519 * @name: The name of the entity
520 * @publicId: The public ID of the entity
521 * @systemId: The system ID of the entity
522 * @notationName: the name of the notation
523 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000524 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000525 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000526void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000527unparsedEntityDecl(void *ctx, const xmlChar *name,
528 const xmlChar *publicId, const xmlChar *systemId,
529 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000530{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000531 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000532#ifdef DEBUG_SAX
533 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
534 name, publicId, systemId, notationName);
535#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000536 if (ctxt->validate && ctxt->wellFormed &&
537 ctxt->myDoc && ctxt->myDoc->intSubset)
538 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
539 notationName);
540 xmlAddDocEntity(ctxt->myDoc, name,
541 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
542 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000543}
544
Daniel Veillard97b58771998-10-20 06:14:16 +0000545/**
546 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000547 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000548 * @loc: A SAX Locator
549 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000550 * Receive the document locator at startup, actually xmlDefaultSAXLocator
551 * Everything is available on the context, so this is useless in our case.
552 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000553void
Daniel Veillard27d88741999-05-29 11:51:49 +0000554setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000555{
Daniel Veillard27d88741999-05-29 11:51:49 +0000556 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000557#ifdef DEBUG_SAX
558 fprintf(stderr, "SAX.setDocumentLocator()\n");
559#endif
560}
561
Daniel Veillard97b58771998-10-20 06:14:16 +0000562/**
563 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000564 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000565 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000566 * called when the document start being processed.
567 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000568void
Daniel Veillard27d88741999-05-29 11:51:49 +0000569startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000570{
Daniel Veillard27d88741999-05-29 11:51:49 +0000571 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000572 xmlDocPtr doc;
573
Daniel Veillard260a68f1998-08-13 03:39:55 +0000574#ifdef DEBUG_SAX
575 fprintf(stderr, "SAX.startDocument()\n");
576#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000577 if (ctxt->html) {
578 if (ctxt->myDoc == NULL)
579 ctxt->myDoc = htmlNewDoc(NULL, NULL);
580 } else {
581 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
582 if (doc != NULL) {
583 if (ctxt->encoding != NULL)
584 doc->encoding = xmlStrdup(ctxt->encoding);
585 else
586 doc->encoding = NULL;
587 doc->standalone = ctxt->standalone;
588 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000589 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000590}
591
Daniel Veillard97b58771998-10-20 06:14:16 +0000592/**
593 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000594 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000595 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000596 * called when the document end has been detected.
597 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000598void
Daniel Veillard27d88741999-05-29 11:51:49 +0000599endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000600{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000601 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000602#ifdef DEBUG_SAX
603 fprintf(stderr, "SAX.endDocument()\n");
604#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000605 if (ctxt->validate && ctxt->wellFormed &&
606 ctxt->myDoc && ctxt->myDoc->intSubset)
607 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000608
609 /*
610 * Grab the encoding if it was added on-the-fly
611 */
612 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
613 (ctxt->myDoc->encoding == NULL)) {
614 ctxt->myDoc->encoding = ctxt->encoding;
615 ctxt->encoding = NULL;
616 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000617 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
618 (ctxt->myDoc->encoding == NULL)) {
619 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
620 }
621 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
622 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
623 ctxt->myDoc->charset = ctxt->charset;
624 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000625}
626
Daniel Veillard97b58771998-10-20 06:14:16 +0000627/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000628 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000629 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000630 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000631 * @value: The attribute value
632 *
633 * Handle an attribute that has been read by the parser.
634 * The default handling is to convert the attribute into an
635 * DOM subtree and past it in a new xmlAttr element added to
636 * the element.
637 */
638void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000639attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000640{
Daniel Veillard27d88741999-05-29 11:51:49 +0000641 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000642 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000643 xmlChar *name;
644 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000645 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000646 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000647
648/****************
649#ifdef DEBUG_SAX
650 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
651#endif
652 ****************/
653 /*
654 * Split the full name into a namespace prefix and the tag name
655 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000656 name = xmlSplitQName(ctxt, fullname, &ns);
657
658 /*
659 * Do the last stave of the attribute normalization
660 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000661 if (ctxt->html)
662 nval = NULL;
663 else
664 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
Daniel Veillardcf461992000-03-14 18:30:20 +0000665 ctxt->node, fullname, value);
666 if (nval != NULL)
667 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000668
669 /*
670 * Check whether it's a namespace definition
671 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000672 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000673 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
674 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000675 xmlURIPtr uri;
676
677 uri = xmlParseURI((const char *)value);
678 if (uri == NULL) {
679 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
680 ctxt->sax->warning(ctxt->userData,
681 "nmlns: %s not a valid URI\n", value);
682 } else {
683 if (uri->scheme == NULL) {
684 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
685 ctxt->sax->warning(ctxt->userData,
686 "nmlns: URI %s is not absolute\n", value);
687 }
688 xmlFreeURI(uri);
689 }
690
Daniel Veillard517752b1999-04-05 12:20:10 +0000691 /* a default namespace definition */
692 xmlNewNs(ctxt->node, value, NULL);
693 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000694 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000695 if (nval != NULL)
696 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000697 return;
698 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000699 if ((!ctxt->html) &&
700 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000701 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000702 /*
703 * Validate also for namespace decls, they are attributes from
704 * an XML-1.0 perspective
705 TODO ... doesn't map well with current API
706 if (ctxt->validate && ctxt->wellFormed &&
707 ctxt->myDoc && ctxt->myDoc->intSubset)
708 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
709 ctxt->node, ret, value);
710 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000711 /* a standard namespace definition */
712 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000713 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000714 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000715 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000716 if (nval != NULL)
717 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000718 return;
719 }
720
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000721 if (ns != NULL)
722 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
723 else {
724 namespace = NULL;
725 }
726
Daniel Veillardb96e6431999-08-29 21:02:19 +0000727 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
728 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000729
Daniel Veillardb96e6431999-08-29 21:02:19 +0000730 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000731 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
732 xmlNodePtr tmp;
733
734 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
735 tmp = ret->children;
736 while (tmp != NULL) {
737 tmp->parent = (xmlNodePtr) ret;
738 if (tmp->next == NULL)
739 ret->last = tmp;
740 tmp = tmp->next;
741 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000742 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000743 ret->children = xmlNewDocText(ctxt->myDoc, value);
744 ret->last = ret->children;
745 if (ret->children != NULL)
746 ret->children->parent = (xmlNodePtr) ret;
747 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000748 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000749
Daniel Veillardbe803962000-06-28 23:40:59 +0000750 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000751 ctxt->myDoc && ctxt->myDoc->intSubset) {
752
753 /*
754 * If we don't substitute entities, the validation should be
755 * done on a value with replaced entities anyway.
756 */
757 if (!ctxt->replaceEntities) {
758 xmlChar *val;
759
760 ctxt->depth++;
761 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
762 0,0,0);
763 ctxt->depth--;
764 if (val == NULL)
765 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
766 ctxt->myDoc, ctxt->node, ret, value);
767 else {
768 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
769 ctxt->myDoc, ctxt->node, ret, val);
770 xmlFree(val);
771 }
772 } else {
773 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000774 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000775 }
776 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000777 /*
778 * when validating, the ID registration is done at the attribute
779 * validation level. Otherwise we have to do specific handling here.
780 */
781 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
782 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000783 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
784 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000785 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000786
Daniel Veillardcf461992000-03-14 18:30:20 +0000787 if (nval != NULL)
788 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000789 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000790 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000791 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000792 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000793}
794
795/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000796 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000797 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000798 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000799 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000800 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000801 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000802 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000803void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000804startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000805{
Daniel Veillard27d88741999-05-29 11:51:49 +0000806 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000807 xmlNodePtr ret;
808 xmlNodePtr parent = ctxt->node;
809 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000810 xmlChar *name;
811 xmlChar *prefix;
812 const xmlChar *att;
813 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000814 int i;
815
Daniel Veillard260a68f1998-08-13 03:39:55 +0000816#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000817 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000819
820 /*
821 * First check on validity:
822 */
823 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
824 ((ctxt->myDoc->intSubset == NULL) ||
825 ((ctxt->myDoc->intSubset->notations == NULL) &&
826 (ctxt->myDoc->intSubset->elements == NULL) &&
827 (ctxt->myDoc->intSubset->attributes == NULL) &&
828 (ctxt->myDoc->intSubset->entities == NULL)))) {
829 if (ctxt->vctxt.error != NULL) {
830 ctxt->vctxt.error(ctxt->vctxt.userData,
831 "Validation failed: no DTD found !\n");
832 }
833 ctxt->validate = 0;
834 }
835
836
Daniel Veillard517752b1999-04-05 12:20:10 +0000837 /*
838 * Split the full name into a namespace prefix and the tag name
839 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000840 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000841
842
843 /*
844 * Note : the namespace resolution is deferred until the end of the
845 * attributes parsing, since local namespace can be defined as
846 * an attribute at this level.
847 */
848 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
849 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000850 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000851#ifdef DEBUG_SAX_TREE
852 fprintf(stderr, "Setting %s as root\n", name);
853#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000854 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000855 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000856 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000857 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000858 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000859
860 /*
861 * We are parsing a new node.
862 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000863#ifdef DEBUG_SAX_TREE
864 fprintf(stderr, "pushing(%s)\n", name);
865#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000866 nodePush(ctxt, ret);
867
868 /*
869 * Link the child element
870 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000871 if (parent != NULL) {
872 if (parent->type == XML_ELEMENT_NODE) {
873#ifdef DEBUG_SAX_TREE
874 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
875#endif
876 xmlAddChild(parent, ret);
877 } else {
878#ifdef DEBUG_SAX_TREE
879 fprintf(stderr, "adding sibling %s to ", name);
880 xmlDebugDumpOneNode(stderr, parent, 0);
881#endif
882 xmlAddSibling(parent, ret);
883 }
884 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000885
886 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000887 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000888 */
889 if (atts != NULL) {
890 i = 0;
891 att = atts[i++];
892 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000893 if (!ctxt->html) {
894 while ((att != NULL) && (value != NULL)) {
895 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
896 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000897
Daniel Veillardbe803962000-06-28 23:40:59 +0000898 att = atts[i++];
899 value = atts[i++];
900 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000901 }
902 }
903
904 /*
905 * Search the namespace, note that since the attributes have been
906 * processed, the local namespaces are available.
907 */
908 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
909 if ((ns == NULL) && (parent != NULL))
910 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
911 xmlSetNs(ret, ns);
912
Daniel Veillardbe803962000-06-28 23:40:59 +0000913 /*
914 * process all the other attributes
915 */
916 if (atts != NULL) {
917 i = 0;
918 att = atts[i++];
919 value = atts[i++];
920 if (ctxt->html) {
921 while (att != NULL) {
922 attribute(ctxt, att, value);
923 att = atts[i++];
924 value = atts[i++];
925 }
926 } else {
927 while ((att != NULL) && (value != NULL)) {
928 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
929 attribute(ctxt, att, value);
930
931 /*
932 * Next ones
933 */
934 att = atts[i++];
935 value = atts[i++];
936 }
937 }
938 }
939
940 /*
941 * If it's the Document root, finish the Dtd validation and
942 * check the document root element for validity
943 */
944 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
945 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
946 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
947 ctxt->vctxt.finishDtd = 1;
948 }
949
Daniel Veillard517752b1999-04-05 12:20:10 +0000950 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000951 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000952 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000953 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000954
Daniel Veillard260a68f1998-08-13 03:39:55 +0000955}
956
Daniel Veillard97b58771998-10-20 06:14:16 +0000957/**
958 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000959 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000960 * @name: The element name
961 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000962 * called when the end of an element has been detected.
963 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000964void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000965endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000966{
Daniel Veillard27d88741999-05-29 11:51:49 +0000967 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000968 xmlParserNodeInfo node_info;
969 xmlNodePtr cur = ctxt->node;
970
Daniel Veillard260a68f1998-08-13 03:39:55 +0000971#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000972 if (name == NULL)
973 fprintf(stderr, "SAX.endElement(NULL)\n");
974 else
975 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000976#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000977
978 /* Capture end position and add node */
979 if (cur != NULL && ctxt->record_info) {
980 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
981 node_info.end_line = ctxt->input->line;
982 node_info.node = cur;
983 xmlParserAddNodeInfo(ctxt, &node_info);
984 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000985 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000986
Daniel Veillardb05deb71999-08-10 19:04:08 +0000987 if (ctxt->validate && ctxt->wellFormed &&
988 ctxt->myDoc && ctxt->myDoc->intSubset)
989 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
990 cur);
991
992
Daniel Veillard517752b1999-04-05 12:20:10 +0000993 /*
994 * end of parsing of this node.
995 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000996#ifdef DEBUG_SAX_TREE
997 fprintf(stderr, "popping(%s)\n", cur->name);
998#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000999 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001000}
1001
Daniel Veillard97b58771998-10-20 06:14:16 +00001002/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001003 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001004 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001005 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001006 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001007 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001008 */
1009void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001010reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001011{
Daniel Veillard27d88741999-05-29 11:51:49 +00001012 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001013 xmlNodePtr ret;
1014
Daniel Veillard11e00581998-10-24 18:27:49 +00001015#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001016 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001017#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001018 if (name[0] == '#')
1019 ret = xmlNewCharRef(ctxt->myDoc, name);
1020 else
1021 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001022#ifdef DEBUG_SAX_TREE
1023 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
1024#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001025 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001026}
1027
1028/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001029 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001030 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001031 * @ch: a xmlChar string
1032 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001033 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001034 * receiving some chars from the parser.
1035 * Question: how much at a time ???
1036 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001037void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001038characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001039{
Daniel Veillard27d88741999-05-29 11:51:49 +00001040 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041 xmlNodePtr lastChild;
1042
1043#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001044 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001045#endif
1046 /*
1047 * Handle the data if any. If there is no child
1048 * add it as content, otherwise if the last child is text,
1049 * concatenate it, else create a new node of type text.
1050 */
1051
Daniel Veillard35008381999-10-25 13:15:52 +00001052 if (ctxt->node == NULL) {
1053#ifdef DEBUG_SAX_TREE
1054 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1055#endif
1056 return;
1057 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001058 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001059#ifdef DEBUG_SAX_TREE
1060 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1061#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001062
1063 /*
1064 * Here we needed an accelerator mechanism in case of very large
1065 * elements. Use an attribute in the structure !!!
1066 */
1067 if (lastChild == NULL) {
1068 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001069 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001070#ifndef XML_USE_BUFFER_CONTENT
1071 if (ctxt->node->children != NULL) {
1072 ctxt->nodelen = len;
1073 ctxt->nodemem = len + 1;
1074 }
1075#endif
1076 } else {
1077 if (xmlNodeIsText(lastChild)) {
1078#ifndef XML_USE_BUFFER_CONTENT
1079 /*
1080 * The whole point of maintaining nodelen and nodemem,
1081 * xmlTextConcat is too costly, i.e. compute lenght,
1082 * reallocate a new buffer, move data, append ch. Here
1083 * We try to minimaze realloc() uses and avoid copying
1084 * and recomputing lenght over and over.
1085 */
1086 if (ctxt->nodelen + len >= ctxt->nodemem) {
1087 xmlChar *newbuf;
1088 int size;
1089
1090 size = ctxt->nodemem + len;
1091 size *= 2;
1092 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1093 if (newbuf == NULL) {
1094 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1095 ctxt->sax->error(ctxt->userData,
1096 "SAX.characters(): out of memory\n");
1097 return;
1098 }
1099 ctxt->nodemem = size;
1100 lastChild->content = newbuf;
1101 }
1102 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1103 ctxt->nodelen += len;
1104 lastChild->content[ctxt->nodelen] = 0;
1105#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001106 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001107#endif
1108 } else {
1109 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001110 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001111 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001112#ifndef XML_USE_BUFFER_CONTENT
1113 if (ctxt->node->children != NULL) {
1114 ctxt->nodelen = len;
1115 ctxt->nodemem = len + 1;
1116 }
1117#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001118 }
1119 }
1120}
1121
Daniel Veillard97b58771998-10-20 06:14:16 +00001122/**
1123 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001124 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001125 * @ch: a xmlChar string
1126 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001127 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001128 * receiving some ignorable whitespaces from the parser.
1129 * Question: how much at a time ???
1130 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001131void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001132ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001133{
Daniel Veillard27d88741999-05-29 11:51:49 +00001134 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001135#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001136 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001137#endif
1138}
1139
Daniel Veillard97b58771998-10-20 06:14:16 +00001140/**
1141 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001142 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001143 * @target: the target name
1144 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001145 *
1146 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001148void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001149processingInstruction(void *ctx, const xmlChar *target,
1150 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001151{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001152 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1153 xmlNodePtr ret;
1154 xmlNodePtr parent = ctxt->node;
1155
Daniel Veillard260a68f1998-08-13 03:39:55 +00001156#ifdef DEBUG_SAX
1157 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1158#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001159
1160 ret = xmlNewPI(target, data);
1161 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001162 parent = ctxt->node;
1163
1164 if (ctxt->inSubset == 1) {
1165 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1166 return;
1167 } else if (ctxt->inSubset == 2) {
1168 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1169 return;
1170 }
1171 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001172#ifdef DEBUG_SAX_TREE
1173 fprintf(stderr, "Setting PI %s as root\n", target);
1174#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001175 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1176 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001177 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001178 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001179#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001180 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001181#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001182 xmlAddChild(parent, ret);
1183 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001184#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001185 fprintf(stderr, "adding PI %s sibling to ", target);
1186 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001187#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001188 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001189 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001190}
1191
Daniel Veillard517752b1999-04-05 12:20:10 +00001192/**
1193 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001194 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001195 * @href: the namespace associated URN
1196 * @prefix: the namespace prefix
1197 *
1198 * An old global namespace has been parsed.
1199 */
1200void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001201globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001202{
Daniel Veillard27d88741999-05-29 11:51:49 +00001203 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001204#ifdef DEBUG_SAX
1205 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1206#endif
1207 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1208}
1209
1210/**
1211 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001212 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001213 * @name: the namespace prefix
1214 *
1215 * Set the current element namespace.
1216 */
Daniel Veillard06047432000-04-24 11:33:38 +00001217
Daniel Veillard517752b1999-04-05 12:20:10 +00001218void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001219setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001220{
Daniel Veillard27d88741999-05-29 11:51:49 +00001221 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001222 xmlNsPtr ns;
1223 xmlNodePtr parent;
1224
1225#ifdef DEBUG_SAX
1226 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1227#endif
1228 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1229 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1230 if (ctxt->nodeNr >= 2) {
1231 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1232 if (parent != NULL)
1233 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1234 }
1235 }
1236 xmlSetNs(ctxt->node, ns);
1237}
1238
1239/**
1240 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001241 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001242 *
1243 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001244 *
1245 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001246 */
Daniel Veillard06047432000-04-24 11:33:38 +00001247
Daniel Veillard517752b1999-04-05 12:20:10 +00001248xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001249getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001250{
Daniel Veillard27d88741999-05-29 11:51:49 +00001251 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001252 xmlNsPtr ret;
1253
1254#ifdef DEBUG_SAX
1255 fprintf(stderr, "SAX.getNamespace()\n");
1256#endif
1257 ret = ctxt->node->ns;
1258 return(ret);
1259}
1260
1261/**
1262 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001263 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001264 * @namespace: the namespace to check against
1265 *
1266 * Check that the current element namespace is the same as the
1267 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001268 *
1269 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001270 */
Daniel Veillard06047432000-04-24 11:33:38 +00001271
Daniel Veillard517752b1999-04-05 12:20:10 +00001272int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001273checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001274{
Daniel Veillard27d88741999-05-29 11:51:49 +00001275 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001276 xmlNodePtr cur = ctxt->node;
1277
1278#ifdef DEBUG_SAX
1279 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1280#endif
1281
1282 /*
1283 * Check that the Name in the ETag is the same as in the STag.
1284 */
1285 if (namespace == NULL) {
1286 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1287 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1288 ctxt->sax->error(ctxt,
1289 "End tags for %s don't hold the namespace %s\n",
1290 cur->name, cur->ns->prefix);
1291 ctxt->wellFormed = 0;
1292 }
1293 } else {
1294 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1295 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1296 ctxt->sax->error(ctxt,
1297 "End tags %s holds a prefix %s not used by the open tag\n",
1298 cur->name, namespace);
1299 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001300 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001301 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1302 ctxt->sax->error(ctxt,
1303 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1304 cur->name, cur->ns->prefix, namespace);
1305 ctxt->wellFormed = 0;
1306 } else
1307 return(1);
1308 }
1309 return(0);
1310}
1311
1312/**
1313 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001314 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001315 * @href: the namespace associated URN
1316 * @prefix: the namespace prefix
1317 *
1318 * A namespace has been parsed.
1319 */
1320void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001321namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001322{
Daniel Veillard27d88741999-05-29 11:51:49 +00001323 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001324#ifdef DEBUG_SAX
1325 if (prefix == NULL)
1326 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1327 else
1328 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1329#endif
1330 xmlNewNs(ctxt->node, href, prefix);
1331}
1332
1333/**
1334 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001335 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001336 * @value: the comment content
1337 *
1338 * A comment has been parsed.
1339 */
1340void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001341comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001342{
Daniel Veillard27d88741999-05-29 11:51:49 +00001343 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001344 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001345 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001346
Daniel Veillard517752b1999-04-05 12:20:10 +00001347#ifdef DEBUG_SAX
1348 fprintf(stderr, "SAX.comment(%s)\n", value);
1349#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001350 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001351 if (ret == NULL) return;
1352
Daniel Veillardcf461992000-03-14 18:30:20 +00001353 if (ctxt->inSubset == 1) {
1354 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1355 return;
1356 } else if (ctxt->inSubset == 2) {
1357 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1358 return;
1359 }
1360 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001361#ifdef DEBUG_SAX_TREE
1362 fprintf(stderr, "Setting comment as root\n");
1363#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001364 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1365 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001366 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001367 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001368#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001369 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001370#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001371 xmlAddChild(parent, ret);
1372 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001373#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001374 fprintf(stderr, "adding comment sibling to ");
1375 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001376#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001377 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001378 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001379}
1380
1381/**
1382 * cdataBlock:
1383 * @ctx: the user data (XML parser context)
1384 * @value: The pcdata content
1385 * @len: the block length
1386 *
1387 * called when a pcdata block has been parsed
1388 */
1389void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001390cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001391{
1392 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001393 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001394
1395#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001396 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001397#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001398 lastChild = xmlGetLastChild(ctxt->node);
1399#ifdef DEBUG_SAX_TREE
1400 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1401#endif
1402 if ((lastChild != NULL) &&
1403 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1404 xmlTextConcat(lastChild, value, len);
1405 } else {
1406 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1407 xmlAddChild(ctxt->node, ret);
1408 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001409}
1410
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001411/*
1412 * Default handler for XML, builds the DOM tree
1413 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001414xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001415 internalSubset,
1416 isStandalone,
1417 hasInternalSubset,
1418 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001419 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001420 getEntity,
1421 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001422 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001423 attributeDecl,
1424 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001425 unparsedEntityDecl,
1426 setDocumentLocator,
1427 startDocument,
1428 endDocument,
1429 startElement,
1430 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001431 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001432 characters,
1433 ignorableWhitespace,
1434 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001435 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001436 xmlParserWarning,
1437 xmlParserError,
1438 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001439 getParameterEntity,
1440 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001441 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001442};
1443
Daniel Veillard97b58771998-10-20 06:14:16 +00001444/**
1445 * xmlDefaultSAXHandlerInit:
1446 *
1447 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001448 */
1449void
1450xmlDefaultSAXHandlerInit(void)
1451{
Daniel Veillard517752b1999-04-05 12:20:10 +00001452 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001453 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001454 xmlDefaultSAXHandler.isStandalone = isStandalone;
1455 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1456 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001457 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001458 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001459 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001460 xmlDefaultSAXHandler.entityDecl = entityDecl;
1461 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1462 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001463 xmlDefaultSAXHandler.notationDecl = notationDecl;
1464 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1465 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1466 xmlDefaultSAXHandler.startDocument = startDocument;
1467 xmlDefaultSAXHandler.endDocument = endDocument;
1468 xmlDefaultSAXHandler.startElement = startElement;
1469 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001470 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001471 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001472 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001473 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1474 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001475 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001476 if (xmlGetWarningsDefaultValue == 0)
1477 xmlDefaultSAXHandler.warning = NULL;
1478 else
1479 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001480 xmlDefaultSAXHandler.error = xmlParserError;
1481 xmlDefaultSAXHandler.fatalError = xmlParserError;
1482}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001483
1484/*
1485 * Default handler for HTML, builds the DOM tree
1486 */
1487xmlSAXHandler htmlDefaultSAXHandler = {
1488 NULL,
1489 NULL,
1490 NULL,
1491 NULL,
1492 NULL,
1493 getEntity,
1494 NULL,
1495 NULL,
1496 NULL,
1497 NULL,
1498 NULL,
1499 setDocumentLocator,
1500 startDocument,
1501 endDocument,
1502 startElement,
1503 endElement,
1504 NULL,
1505 characters,
1506 ignorableWhitespace,
1507 NULL,
1508 comment,
1509 xmlParserWarning,
1510 xmlParserError,
1511 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001512 getParameterEntity,
1513 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001514 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001515};
1516
1517/**
1518 * htmlDefaultSAXHandlerInit:
1519 *
1520 * Initialize the default SAX handler
1521 */
1522void
1523htmlDefaultSAXHandlerInit(void)
1524{
1525 htmlDefaultSAXHandler.internalSubset = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001526 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001527 htmlDefaultSAXHandler.isStandalone = NULL;
1528 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1529 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1530 htmlDefaultSAXHandler.resolveEntity = NULL;
1531 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001532 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001533 htmlDefaultSAXHandler.entityDecl = NULL;
1534 htmlDefaultSAXHandler.attributeDecl = NULL;
1535 htmlDefaultSAXHandler.elementDecl = NULL;
1536 htmlDefaultSAXHandler.notationDecl = NULL;
1537 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1538 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1539 htmlDefaultSAXHandler.startDocument = startDocument;
1540 htmlDefaultSAXHandler.endDocument = endDocument;
1541 htmlDefaultSAXHandler.startElement = startElement;
1542 htmlDefaultSAXHandler.endElement = endElement;
1543 htmlDefaultSAXHandler.reference = NULL;
1544 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001545 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001546 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1547 htmlDefaultSAXHandler.processingInstruction = NULL;
1548 htmlDefaultSAXHandler.comment = comment;
1549 htmlDefaultSAXHandler.warning = xmlParserWarning;
1550 htmlDefaultSAXHandler.error = xmlParserError;
1551 htmlDefaultSAXHandler.fatalError = xmlParserError;
1552}