blob: dace3058687643bf7efa2d0f42ec9c68cdf5d970 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
Daniel Veillard97b58771998-10-20 06:14:16 +00003 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004 * See Copyright for the status of this software.
5 *
Daniel Veillard97b58771998-10-20 06:14:16 +00006 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000016#include <stdlib.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000017#include <libxml/xmlmemory.h>
18#include <libxml/tree.h>
19#include <libxml/parser.h>
20#include <libxml/parserInternals.h>
21#include <libxml/valid.h>
22#include <libxml/entities.h>
Daniel Veillardd109e371999-03-05 06:26:45 +000023#include "xml-error.h"
Daniel Veillard361d8452000-04-03 19:48:13 +000024#include <libxml/debugXML.h>
25#include <libxml/xmlIO.h>
26#include <libxml/SAX.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000027
28/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000029/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000030
Daniel Veillard97b58771998-10-20 06:14:16 +000031/**
32 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000033 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000034 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000035 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000036 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000037 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000038 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000039const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000040getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000041{
Daniel Veillard27d88741999-05-29 11:51:49 +000042 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000043 return(NULL);
44}
45
Daniel Veillard97b58771998-10-20 06:14:16 +000046/**
47 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000048 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000049 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000050 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000051 * http://www.sgmlsource.com/dtds/memo.dtd
52 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000053 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000054 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000055const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000056getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000057{
Daniel Veillard27d88741999-05-29 11:51:49 +000058 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000059 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000060}
61
Daniel Veillard97b58771998-10-20 06:14:16 +000062/**
63 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000064 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000065 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000066 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000067 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000068 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 */
Daniel Veillard97b58771998-10-20 06:14:16 +000070int
Daniel Veillard27d88741999-05-29 11:51:49 +000071getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000072{
Daniel Veillard27d88741999-05-29 11:51:49 +000073 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000074 return(ctxt->input->line);
75}
Daniel Veillard97b58771998-10-20 06:14:16 +000076
77/**
78 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000079 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000080 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000081 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000082 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000083 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000084 */
Daniel Veillard97b58771998-10-20 06:14:16 +000085int
Daniel Veillard27d88741999-05-29 11:51:49 +000086getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000087{
Daniel Veillard27d88741999-05-29 11:51:49 +000088 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000089 return(ctxt->input->col);
90}
91
92/*
93 * The default SAX Locator.
94 */
95
96xmlSAXLocator xmlDefaultSAXLocator = {
97 getPublicId, getSystemId, getLineNumber, getColumnNumber
98};
99
Daniel Veillard97b58771998-10-20 06:14:16 +0000100/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000101 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000102 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000103 *
104 * Is this document tagged standalone ?
105 *
106 * Returns 1 if true
107 */
108int
Daniel Veillard27d88741999-05-29 11:51:49 +0000109isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000110{
Daniel Veillard27d88741999-05-29 11:51:49 +0000111 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000112 return(ctxt->myDoc->standalone == 1);
113}
114
115/**
116 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000117 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000118 *
119 * Does this document has an internal subset
120 *
121 * Returns 1 if true
122 */
123int
Daniel Veillard27d88741999-05-29 11:51:49 +0000124hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000125{
Daniel Veillard27d88741999-05-29 11:51:49 +0000126 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000127 return(ctxt->myDoc->intSubset != NULL);
128}
129
130/**
131 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000132 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000133 *
134 * Does this document has an external subset
135 *
136 * Returns 1 if true
137 */
138int
Daniel Veillard27d88741999-05-29 11:51:49 +0000139hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000140{
Daniel Veillard27d88741999-05-29 11:51:49 +0000141 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000142 return(ctxt->myDoc->extSubset != NULL);
143}
144
145/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000146 * internalSubset:
Daniel Veillard06047432000-04-24 11:33:38 +0000147 * @ctx: the user data (XML parser context)
148 * @name: the root element name
149 * @ExternalID: the external ID
150 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000151 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000152 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000153 */
154void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000155internalSubset(void *ctx, const xmlChar *name,
156 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000157{
Daniel Veillard27d88741999-05-29 11:51:49 +0000158 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000159#ifdef DEBUG_SAX
160 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
161 name, ExternalID, SystemID);
162#endif
163 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000164}
165
166/**
167 * externalSubset:
168 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000169 * @name: the root element name
170 * @ExternalID: the external ID
171 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000172 *
173 * Callback on external subset declaration.
174 */
175void
176externalSubset(void *ctx, const xmlChar *name,
177 const xmlChar *ExternalID, const xmlChar *SystemID)
178{
179 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
180#ifdef DEBUG_SAX
181 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
182 name, ExternalID, SystemID);
183#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000184 if (((ExternalID != NULL) || (SystemID != NULL)) &&
185 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
186 /*
187 * Try to fetch and parse the external subset.
188 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000189 xmlParserInputPtr oldinput;
190 int oldinputNr;
191 int oldinputMax;
192 xmlParserInputPtr *oldinputTab;
193 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000194 xmlParserInputPtr input = NULL;
195 xmlCharEncoding enc;
196
Daniel Veillardb05deb71999-08-10 19:04:08 +0000197 /*
198 * Ask the Entity resolver to load the damn thing
199 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000200 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
201 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000202 SystemID);
203 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000204 return;
205 }
206
Daniel Veillardcf461992000-03-14 18:30:20 +0000207 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
208
Daniel Veillardb05deb71999-08-10 19:04:08 +0000209 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000210 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000211 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000212 oldinput = ctxt->input;
213 oldinputNr = ctxt->inputNr;
214 oldinputMax = ctxt->inputMax;
215 oldinputTab = ctxt->inputTab;
216 oldwellFormed = ctxt->wellFormed;
217
218 ctxt->inputTab = (xmlParserInputPtr *)
219 xmlMalloc(5 * sizeof(xmlParserInputPtr));
220 if (ctxt->inputTab == NULL) {
221 ctxt->errNo = XML_ERR_NO_MEMORY;
222 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
223 ctxt->sax->error(ctxt->userData,
224 "externalSubset: out of memory\n");
225 ctxt->errNo = XML_ERR_NO_MEMORY;
226 ctxt->input = oldinput;
227 ctxt->inputNr = oldinputNr;
228 ctxt->inputMax = oldinputMax;
229 ctxt->inputTab = oldinputTab;
230 return;
231 }
232 ctxt->inputNr = 0;
233 ctxt->inputMax = 5;
234 ctxt->input = NULL;
235 xmlPushInput(ctxt, input);
236
237 /*
238 * On the fly encoding conversion if needed
239 */
240 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
241 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000242
243 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000244 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000245 input->line = 1;
246 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000247 input->base = ctxt->input->cur;
248 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000249 input->free = NULL;
250
251 /*
252 * let's parse that entity knowing it's an external subset.
253 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000254 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000255
Daniel Veillardcf461992000-03-14 18:30:20 +0000256 /*
257 * Free up the external entities
258 */
259
260 while (ctxt->inputNr > 1)
261 xmlPopInput(ctxt);
262 xmlFreeInputStream(ctxt->input);
263 xmlFree(ctxt->inputTab);
264
265 /*
266 * Restore the parsing context of the main entity
267 */
268 ctxt->input = oldinput;
269 ctxt->inputNr = oldinputNr;
270 ctxt->inputMax = oldinputMax;
271 ctxt->inputTab = oldinputTab;
272 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000273 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000274}
275
276/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000277 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000278 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000279 * @publicId: The public ID of the entity
280 * @systemId: The system ID of the entity
281 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000282 * The entity loader, to control the loading of external entities,
283 * the application can either:
284 * - override this resolveEntity() callback in the SAX block
285 * - or better use the xmlSetExternalEntityLoader() function to
286 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000287 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000288 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000289 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000290xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000291resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000292{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000293 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000294
295#ifdef DEBUG_SAX
296 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
297#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000298
Daniel Veillard686d6b62000-01-03 11:08:02 +0000299 return(xmlLoadExternalEntity((const char *) systemId,
300 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000301}
302
Daniel Veillard97b58771998-10-20 06:14:16 +0000303/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000304 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000305 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000306 * @name: The entity name
307 *
308 * Get an entity by name
309 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000310 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000311 */
312xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000313getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000314{
Daniel Veillard27d88741999-05-29 11:51:49 +0000315 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000316 xmlEntityPtr ret;
317
318#ifdef DEBUG_SAX
319 fprintf(stderr, "SAX.getEntity(%s)\n", name);
320#endif
321
322 ret = xmlGetDocEntity(ctxt->myDoc, name);
323 return(ret);
324}
325
Daniel Veillardb05deb71999-08-10 19:04:08 +0000326/**
327 * getParameterEntity:
328 * @ctx: the user data (XML parser context)
329 * @name: The entity name
330 *
331 * Get a parameter entity by name
332 *
333 * Returns the xmlEntityPtr if found.
334 */
335xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000336getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000337{
338 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
339 xmlEntityPtr ret;
340
341#ifdef DEBUG_SAX
342 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
343#endif
344
345 ret = xmlGetParameterEntity(ctxt->myDoc, name);
346 return(ret);
347}
348
Daniel Veillard517752b1999-04-05 12:20:10 +0000349
350/**
351 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000352 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000353 * @name: the entity name
354 * @type: the entity type
355 * @publicId: The public ID of the entity
356 * @systemId: The system ID of the entity
357 * @content: the entity value (without processing).
358 *
359 * An entity definition has been parsed
360 */
361void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000362entityDecl(void *ctx, const xmlChar *name, int type,
363 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000364{
Daniel Veillard27d88741999-05-29 11:51:49 +0000365 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000366
367#ifdef DEBUG_SAX
368 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
369 name, type, publicId, systemId, content);
370#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000371 if (ctxt->inSubset == 1)
372 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
373 systemId, content);
374 else if (ctxt->inSubset == 2)
375 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
376 systemId, content);
377 else {
378 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
379 ctxt->sax->error(ctxt,
380 "SAX.entityDecl(%s) called while not in subset\n", name);
381 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000382}
383
384/**
385 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000386 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000387 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000388 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000389 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000390 * @def: the type of default value
391 * @defaultValue: the attribute default value
392 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000393 *
394 * An attribute definition has been parsed
395 */
396void
Daniel Veillardcf461992000-03-14 18:30:20 +0000397attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000398 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000399 xmlEnumerationPtr tree)
400{
Daniel Veillard27d88741999-05-29 11:51:49 +0000401 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000402 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000403 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000404
405#ifdef DEBUG_SAX
406 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000407 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000408#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000409 name = xmlSplitQName(ctxt, fullname, &prefix);
410 if (ctxt->inSubset == 1)
411 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
412 name, prefix, type, def, defaultValue, tree);
413 else if (ctxt->inSubset == 2)
414 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
415 name, prefix, type, def, defaultValue, tree);
416 else {
417 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
418 ctxt->sax->error(ctxt,
419 "SAX.attributeDecl(%s) called while not in subset\n", name);
420 return;
421 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000422 if (attr == 0) ctxt->valid = 0;
423 if (ctxt->validate && ctxt->wellFormed &&
424 ctxt->myDoc && ctxt->myDoc->intSubset)
425 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
426 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000427 if (prefix != NULL)
428 xmlFree(prefix);
429 if (name != NULL)
430 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000431}
432
433/**
434 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000435 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000436 * @name: the element name
437 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000438 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000439 *
440 * An element definition has been parsed
441 */
442void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000443elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000444 xmlElementContentPtr content)
445{
Daniel Veillard27d88741999-05-29 11:51:49 +0000446 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000447 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000448
449#ifdef DEBUG_SAX
450 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000451 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000452#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000453
Daniel Veillardcf461992000-03-14 18:30:20 +0000454 if (ctxt->inSubset == 1)
455 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000456 name, type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000457 else if (ctxt->inSubset == 2)
458 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
459 name, type, content);
460 else {
461 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
462 ctxt->sax->error(ctxt,
463 "SAX.elementDecl(%s) called while not in subset\n", name);
464 return;
465 }
466 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000467 if (ctxt->validate && ctxt->wellFormed &&
468 ctxt->myDoc && ctxt->myDoc->intSubset)
469 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000470}
471
472/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000473 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000474 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000475 * @name: The name of the notation
476 * @publicId: The public ID of the entity
477 * @systemId: The system ID of the entity
478 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000479 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000480 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000481void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000482notationDecl(void *ctx, const xmlChar *name,
483 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000484{
Daniel Veillard27d88741999-05-29 11:51:49 +0000485 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000486 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000487
Daniel Veillard260a68f1998-08-13 03:39:55 +0000488#ifdef DEBUG_SAX
489 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
490#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000491
Daniel Veillardcf461992000-03-14 18:30:20 +0000492 if (ctxt->inSubset == 1)
493 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000494 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000495 else if (ctxt->inSubset == 2)
496 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
497 publicId, systemId);
498 else {
499 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
500 ctxt->sax->error(ctxt,
501 "SAX.notationDecl(%s) called while not in subset\n", name);
502 return;
503 }
504 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000505 if (ctxt->validate && ctxt->wellFormed &&
506 ctxt->myDoc && ctxt->myDoc->intSubset)
507 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
508 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000509}
510
Daniel Veillard97b58771998-10-20 06:14:16 +0000511/**
512 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000513 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000514 * @name: The name of the entity
515 * @publicId: The public ID of the entity
516 * @systemId: The system ID of the entity
517 * @notationName: the name of the notation
518 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000519 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000520 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000521void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000522unparsedEntityDecl(void *ctx, const xmlChar *name,
523 const xmlChar *publicId, const xmlChar *systemId,
524 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000525{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000526 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000527#ifdef DEBUG_SAX
528 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
529 name, publicId, systemId, notationName);
530#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000531 if (ctxt->validate && ctxt->wellFormed &&
532 ctxt->myDoc && ctxt->myDoc->intSubset)
533 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
534 notationName);
535 xmlAddDocEntity(ctxt->myDoc, name,
536 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
537 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000538}
539
Daniel Veillard97b58771998-10-20 06:14:16 +0000540/**
541 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000542 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000543 * @loc: A SAX Locator
544 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000545 * Receive the document locator at startup, actually xmlDefaultSAXLocator
546 * Everything is available on the context, so this is useless in our case.
547 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000548void
Daniel Veillard27d88741999-05-29 11:51:49 +0000549setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000550{
Daniel Veillard27d88741999-05-29 11:51:49 +0000551 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000552#ifdef DEBUG_SAX
553 fprintf(stderr, "SAX.setDocumentLocator()\n");
554#endif
555}
556
Daniel Veillard97b58771998-10-20 06:14:16 +0000557/**
558 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000559 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000560 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000561 * called when the document start being processed.
562 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000563void
Daniel Veillard27d88741999-05-29 11:51:49 +0000564startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000565{
Daniel Veillard27d88741999-05-29 11:51:49 +0000566 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000567 xmlDocPtr doc;
568
Daniel Veillard260a68f1998-08-13 03:39:55 +0000569#ifdef DEBUG_SAX
570 fprintf(stderr, "SAX.startDocument()\n");
571#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000572 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
573 if (doc != NULL) {
574 if (ctxt->encoding != NULL)
575 doc->encoding = xmlStrdup(ctxt->encoding);
576 else
577 doc->encoding = NULL;
578 doc->standalone = ctxt->standalone;
579 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000580}
581
Daniel Veillard97b58771998-10-20 06:14:16 +0000582/**
583 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000584 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000585 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000586 * called when the document end has been detected.
587 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000588void
Daniel Veillard27d88741999-05-29 11:51:49 +0000589endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000590{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000591 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000592#ifdef DEBUG_SAX
593 fprintf(stderr, "SAX.endDocument()\n");
594#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000595 if (ctxt->validate && ctxt->wellFormed &&
596 ctxt->myDoc && ctxt->myDoc->intSubset)
597 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000598
599 /*
600 * Grab the encoding if it was added on-the-fly
601 */
602 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
603 (ctxt->myDoc->encoding == NULL)) {
604 ctxt->myDoc->encoding = ctxt->encoding;
605 ctxt->encoding = NULL;
606 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000607}
608
Daniel Veillard97b58771998-10-20 06:14:16 +0000609/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000610 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000611 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000612 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000613 * @value: The attribute value
614 *
615 * Handle an attribute that has been read by the parser.
616 * The default handling is to convert the attribute into an
617 * DOM subtree and past it in a new xmlAttr element added to
618 * the element.
619 */
620void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000621attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000622{
Daniel Veillard27d88741999-05-29 11:51:49 +0000623 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000624 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000625 xmlChar *name;
626 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000627 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000628 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000629
630/****************
631#ifdef DEBUG_SAX
632 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
633#endif
634 ****************/
635 /*
636 * Split the full name into a namespace prefix and the tag name
637 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000638 name = xmlSplitQName(ctxt, fullname, &ns);
639
640 /*
641 * Do the last stave of the attribute normalization
642 */
643 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
644 ctxt->node, fullname, value);
645 if (nval != NULL)
646 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000647
648 /*
649 * Check whether it's a namespace definition
650 */
651 if ((ns == NULL) &&
652 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
653 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
654 /* a default namespace definition */
655 xmlNewNs(ctxt->node, value, NULL);
656 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000657 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000658 if (nval != NULL)
659 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000660 return;
661 }
662 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
663 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000664 /*
665 * Validate also for namespace decls, they are attributes from
666 * an XML-1.0 perspective
667 TODO ... doesn't map well with current API
668 if (ctxt->validate && ctxt->wellFormed &&
669 ctxt->myDoc && ctxt->myDoc->intSubset)
670 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
671 ctxt->node, ret, value);
672 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000673 /* a standard namespace definition */
674 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000675 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000676 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000677 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000678 if (nval != NULL)
679 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000680 return;
681 }
682
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000683 if (ns != NULL)
684 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
685 else {
686 namespace = NULL;
687 }
688
Daniel Veillardb96e6431999-08-29 21:02:19 +0000689 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
690 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000691
Daniel Veillardb96e6431999-08-29 21:02:19 +0000692 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000693 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
694 xmlNodePtr tmp;
695
696 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
697 tmp = ret->children;
698 while (tmp != NULL) {
699 tmp->parent = (xmlNodePtr) ret;
700 if (tmp->next == NULL)
701 ret->last = tmp;
702 tmp = tmp->next;
703 }
704 } else {
705 ret->children = xmlNewDocText(ctxt->myDoc, value);
706 ret->last = ret->children;
707 if (ret->children != NULL)
708 ret->children->parent = (xmlNodePtr) ret;
709 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000710 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000711
712 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000713 ctxt->myDoc && ctxt->myDoc->intSubset) {
714
715 /*
716 * If we don't substitute entities, the validation should be
717 * done on a value with replaced entities anyway.
718 */
719 if (!ctxt->replaceEntities) {
720 xmlChar *val;
721
722 ctxt->depth++;
723 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
724 0,0,0);
725 ctxt->depth--;
726 if (val == NULL)
727 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
728 ctxt->myDoc, ctxt->node, ret, value);
729 else {
730 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
731 ctxt->myDoc, ctxt->node, ret, val);
732 xmlFree(val);
733 }
734 } else {
735 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000736 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000737 }
738 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000739 /*
740 * when validating, the ID registration is done at the attribute
741 * validation level. Otherwise we have to do specific handling here.
742 */
743 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
744 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000745 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
746 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000747 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000748
Daniel Veillardcf461992000-03-14 18:30:20 +0000749 if (nval != NULL)
750 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000751 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000752 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000753 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000754 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000755}
756
757/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000758 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000759 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000760 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000761 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000762 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000763 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000764 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000765void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000766startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000767{
Daniel Veillard27d88741999-05-29 11:51:49 +0000768 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000769 xmlNodePtr ret;
770 xmlNodePtr parent = ctxt->node;
771 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000772 xmlChar *name;
773 xmlChar *prefix;
774 const xmlChar *att;
775 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000776 int i;
777
Daniel Veillard260a68f1998-08-13 03:39:55 +0000778#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000779 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000780#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000781
782 /*
783 * First check on validity:
784 */
785 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
786 ((ctxt->myDoc->intSubset == NULL) ||
787 ((ctxt->myDoc->intSubset->notations == NULL) &&
788 (ctxt->myDoc->intSubset->elements == NULL) &&
789 (ctxt->myDoc->intSubset->attributes == NULL) &&
790 (ctxt->myDoc->intSubset->entities == NULL)))) {
791 if (ctxt->vctxt.error != NULL) {
792 ctxt->vctxt.error(ctxt->vctxt.userData,
793 "Validation failed: no DTD found !\n");
794 }
795 ctxt->validate = 0;
796 }
797
798
Daniel Veillard517752b1999-04-05 12:20:10 +0000799 /*
800 * Split the full name into a namespace prefix and the tag name
801 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000802 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000803
804
805 /*
806 * Note : the namespace resolution is deferred until the end of the
807 * attributes parsing, since local namespace can be defined as
808 * an attribute at this level.
809 */
810 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
811 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000812 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000813#ifdef DEBUG_SAX_TREE
814 fprintf(stderr, "Setting %s as root\n", name);
815#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000816 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000817 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000818 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000819 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000820
821 /*
822 * We are parsing a new node.
823 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000824#ifdef DEBUG_SAX_TREE
825 fprintf(stderr, "pushing(%s)\n", name);
826#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000827 nodePush(ctxt, ret);
828
829 /*
830 * Link the child element
831 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000832 if (parent != NULL) {
833 if (parent->type == XML_ELEMENT_NODE) {
834#ifdef DEBUG_SAX_TREE
835 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
836#endif
837 xmlAddChild(parent, ret);
838 } else {
839#ifdef DEBUG_SAX_TREE
840 fprintf(stderr, "adding sibling %s to ", name);
841 xmlDebugDumpOneNode(stderr, parent, 0);
842#endif
843 xmlAddSibling(parent, ret);
844 }
845 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000846
847 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000848 * If it's the Document root, finish the Dtd validation and
849 * check the document root element for validity
850 */
851 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
852 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
853 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
854 ctxt->vctxt.finishDtd = 1;
855 }
856 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000857 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000858 */
859 if (atts != NULL) {
860 i = 0;
861 att = atts[i++];
862 value = atts[i++];
863 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000864 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
865 attribute(ctxt, att, value);
866
867 att = atts[i++];
868 value = atts[i++];
869 }
870 }
871
872 /*
873 * process all the other attributes
874 */
875 if (atts != NULL) {
876 i = 0;
877 att = atts[i++];
878 value = atts[i++];
879 while ((att != NULL) && (value != NULL)) {
880 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
881 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000882
883 /*
884 * Next ones
885 */
886 att = atts[i++];
887 value = atts[i++];
888 }
889 }
890
891 /*
892 * Search the namespace, note that since the attributes have been
893 * processed, the local namespaces are available.
894 */
895 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
896 if ((ns == NULL) && (parent != NULL))
897 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
898 xmlSetNs(ret, ns);
899
900 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000901 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000902 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000903 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000904
Daniel Veillard260a68f1998-08-13 03:39:55 +0000905}
906
Daniel Veillard97b58771998-10-20 06:14:16 +0000907/**
908 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000909 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000910 * @name: The element name
911 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000912 * called when the end of an element has been detected.
913 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000914void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000915endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000916{
Daniel Veillard27d88741999-05-29 11:51:49 +0000917 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000918 xmlParserNodeInfo node_info;
919 xmlNodePtr cur = ctxt->node;
920
Daniel Veillard260a68f1998-08-13 03:39:55 +0000921#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000922 if (name == NULL)
923 fprintf(stderr, "SAX.endElement(NULL)\n");
924 else
925 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000926#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000927
928 /* Capture end position and add node */
929 if (cur != NULL && ctxt->record_info) {
930 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
931 node_info.end_line = ctxt->input->line;
932 node_info.node = cur;
933 xmlParserAddNodeInfo(ctxt, &node_info);
934 }
935
Daniel Veillardb05deb71999-08-10 19:04:08 +0000936 if (ctxt->validate && ctxt->wellFormed &&
937 ctxt->myDoc && ctxt->myDoc->intSubset)
938 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
939 cur);
940
941
Daniel Veillard517752b1999-04-05 12:20:10 +0000942 /*
943 * end of parsing of this node.
944 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000945#ifdef DEBUG_SAX_TREE
946 fprintf(stderr, "popping(%s)\n", cur->name);
947#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000948 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000949}
950
Daniel Veillard97b58771998-10-20 06:14:16 +0000951/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000952 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000953 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000954 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000955 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000956 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000957 */
958void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000959reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000960{
Daniel Veillard27d88741999-05-29 11:51:49 +0000961 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000962 xmlNodePtr ret;
963
Daniel Veillard11e00581998-10-24 18:27:49 +0000964#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000965 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000966#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000967 if (name[0] == '#')
968 ret = xmlNewCharRef(ctxt->myDoc, name);
969 else
970 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000971#ifdef DEBUG_SAX_TREE
972 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
973#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000974 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000975}
976
977/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000978 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000979 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000980 * @ch: a xmlChar string
981 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000982 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000983 * receiving some chars from the parser.
984 * Question: how much at a time ???
985 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000986void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000987characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000988{
Daniel Veillard27d88741999-05-29 11:51:49 +0000989 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000990 xmlNodePtr lastChild;
991
992#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000993 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000994#endif
995 /*
996 * Handle the data if any. If there is no child
997 * add it as content, otherwise if the last child is text,
998 * concatenate it, else create a new node of type text.
999 */
1000
Daniel Veillard35008381999-10-25 13:15:52 +00001001 if (ctxt->node == NULL) {
1002#ifdef DEBUG_SAX_TREE
1003 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1004#endif
1005 return;
1006 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001007 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001008#ifdef DEBUG_SAX_TREE
1009 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1010#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001011 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +00001012 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001013 else {
1014 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +00001015 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001016 else {
Daniel Veillard517752b1999-04-05 12:20:10 +00001017 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001018 xmlAddChild(ctxt->node, lastChild);
1019 }
1020 }
1021}
1022
Daniel Veillard97b58771998-10-20 06:14:16 +00001023/**
1024 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001025 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001026 * @ch: a xmlChar string
1027 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001028 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029 * receiving some ignorable whitespaces from the parser.
1030 * Question: how much at a time ???
1031 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001032void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001033ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001034{
Daniel Veillard27d88741999-05-29 11:51:49 +00001035 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001036#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001037 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001038#endif
1039}
1040
Daniel Veillard97b58771998-10-20 06:14:16 +00001041/**
1042 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001043 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001044 * @target: the target name
1045 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001046 *
1047 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001048 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001049void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001050processingInstruction(void *ctx, const xmlChar *target,
1051 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001052{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001053 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1054 xmlNodePtr ret;
1055 xmlNodePtr parent = ctxt->node;
1056
Daniel Veillard260a68f1998-08-13 03:39:55 +00001057#ifdef DEBUG_SAX
1058 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1059#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001060
1061 ret = xmlNewPI(target, data);
1062 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001063 parent = ctxt->node;
1064
1065 if (ctxt->inSubset == 1) {
1066 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1067 return;
1068 } else if (ctxt->inSubset == 2) {
1069 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1070 return;
1071 }
1072 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001073#ifdef DEBUG_SAX_TREE
1074 fprintf(stderr, "Setting PI %s as root\n", target);
1075#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001076 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1077 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001078 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001079 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001080#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001081 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001082#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001083 xmlAddChild(parent, ret);
1084 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001085#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001086 fprintf(stderr, "adding PI %s sibling to ", target);
1087 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001088#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001089 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001090 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001091}
1092
Daniel Veillard517752b1999-04-05 12:20:10 +00001093/**
1094 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001095 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001096 * @href: the namespace associated URN
1097 * @prefix: the namespace prefix
1098 *
1099 * An old global namespace has been parsed.
1100 */
1101void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001102globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001103{
Daniel Veillard27d88741999-05-29 11:51:49 +00001104 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001105#ifdef DEBUG_SAX
1106 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1107#endif
1108 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1109}
1110
1111/**
1112 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001113 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001114 * @name: the namespace prefix
1115 *
1116 * Set the current element namespace.
1117 */
Daniel Veillard06047432000-04-24 11:33:38 +00001118
Daniel Veillard517752b1999-04-05 12:20:10 +00001119void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001120setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001121{
Daniel Veillard27d88741999-05-29 11:51:49 +00001122 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001123 xmlNsPtr ns;
1124 xmlNodePtr parent;
1125
1126#ifdef DEBUG_SAX
1127 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1128#endif
1129 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1130 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1131 if (ctxt->nodeNr >= 2) {
1132 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1133 if (parent != NULL)
1134 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1135 }
1136 }
1137 xmlSetNs(ctxt->node, ns);
1138}
1139
1140/**
1141 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001142 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001143 *
1144 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001145 *
1146 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001147 */
Daniel Veillard06047432000-04-24 11:33:38 +00001148
Daniel Veillard517752b1999-04-05 12:20:10 +00001149xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001150getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001151{
Daniel Veillard27d88741999-05-29 11:51:49 +00001152 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001153 xmlNsPtr ret;
1154
1155#ifdef DEBUG_SAX
1156 fprintf(stderr, "SAX.getNamespace()\n");
1157#endif
1158 ret = ctxt->node->ns;
1159 return(ret);
1160}
1161
1162/**
1163 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001164 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001165 * @namespace: the namespace to check against
1166 *
1167 * Check that the current element namespace is the same as the
1168 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001169 *
1170 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001171 */
Daniel Veillard06047432000-04-24 11:33:38 +00001172
Daniel Veillard517752b1999-04-05 12:20:10 +00001173int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001174checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001175{
Daniel Veillard27d88741999-05-29 11:51:49 +00001176 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001177 xmlNodePtr cur = ctxt->node;
1178
1179#ifdef DEBUG_SAX
1180 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1181#endif
1182
1183 /*
1184 * Check that the Name in the ETag is the same as in the STag.
1185 */
1186 if (namespace == NULL) {
1187 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1188 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1189 ctxt->sax->error(ctxt,
1190 "End tags for %s don't hold the namespace %s\n",
1191 cur->name, cur->ns->prefix);
1192 ctxt->wellFormed = 0;
1193 }
1194 } else {
1195 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1196 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1197 ctxt->sax->error(ctxt,
1198 "End tags %s holds a prefix %s not used by the open tag\n",
1199 cur->name, namespace);
1200 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001201 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001202 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1203 ctxt->sax->error(ctxt,
1204 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1205 cur->name, cur->ns->prefix, namespace);
1206 ctxt->wellFormed = 0;
1207 } else
1208 return(1);
1209 }
1210 return(0);
1211}
1212
1213/**
1214 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001215 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001216 * @href: the namespace associated URN
1217 * @prefix: the namespace prefix
1218 *
1219 * A namespace has been parsed.
1220 */
1221void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001222namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001223{
Daniel Veillard27d88741999-05-29 11:51:49 +00001224 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001225#ifdef DEBUG_SAX
1226 if (prefix == NULL)
1227 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1228 else
1229 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1230#endif
1231 xmlNewNs(ctxt->node, href, prefix);
1232}
1233
1234/**
1235 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001236 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001237 * @value: the comment content
1238 *
1239 * A comment has been parsed.
1240 */
1241void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001242comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001243{
Daniel Veillard27d88741999-05-29 11:51:49 +00001244 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001245 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001246 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001247
Daniel Veillard517752b1999-04-05 12:20:10 +00001248#ifdef DEBUG_SAX
1249 fprintf(stderr, "SAX.comment(%s)\n", value);
1250#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001251 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001252 if (ret == NULL) return;
1253
Daniel Veillardcf461992000-03-14 18:30:20 +00001254 if (ctxt->inSubset == 1) {
1255 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1256 return;
1257 } else if (ctxt->inSubset == 2) {
1258 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1259 return;
1260 }
1261 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001262#ifdef DEBUG_SAX_TREE
1263 fprintf(stderr, "Setting comment as root\n");
1264#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001265 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1266 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001267 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001268 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001269#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001270 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001271#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001272 xmlAddChild(parent, ret);
1273 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001274#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001275 fprintf(stderr, "adding comment sibling to ");
1276 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001277#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001278 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001279 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001280}
1281
1282/**
1283 * cdataBlock:
1284 * @ctx: the user data (XML parser context)
1285 * @value: The pcdata content
1286 * @len: the block length
1287 *
1288 * called when a pcdata block has been parsed
1289 */
1290void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001291cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001292{
1293 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001294 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001295
1296#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001297 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001298#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001299 lastChild = xmlGetLastChild(ctxt->node);
1300#ifdef DEBUG_SAX_TREE
1301 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1302#endif
1303 if ((lastChild != NULL) &&
1304 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1305 xmlTextConcat(lastChild, value, len);
1306 } else {
1307 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1308 xmlAddChild(ctxt->node, ret);
1309 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001310}
1311
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001312/*
1313 * Default handler for XML, builds the DOM tree
1314 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001315xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001316 internalSubset,
1317 isStandalone,
1318 hasInternalSubset,
1319 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001320 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001321 getEntity,
1322 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001323 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001324 attributeDecl,
1325 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001326 unparsedEntityDecl,
1327 setDocumentLocator,
1328 startDocument,
1329 endDocument,
1330 startElement,
1331 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001332 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001333 characters,
1334 ignorableWhitespace,
1335 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001336 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001337 xmlParserWarning,
1338 xmlParserError,
1339 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001340 getParameterEntity,
1341 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001342 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001343};
1344
Daniel Veillard97b58771998-10-20 06:14:16 +00001345/**
1346 * xmlDefaultSAXHandlerInit:
1347 *
1348 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001349 */
1350void
1351xmlDefaultSAXHandlerInit(void)
1352{
Daniel Veillard517752b1999-04-05 12:20:10 +00001353 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001354 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001355 xmlDefaultSAXHandler.isStandalone = isStandalone;
1356 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1357 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001358 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001359 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001360 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001361 xmlDefaultSAXHandler.entityDecl = entityDecl;
1362 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1363 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001364 xmlDefaultSAXHandler.notationDecl = notationDecl;
1365 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1366 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1367 xmlDefaultSAXHandler.startDocument = startDocument;
1368 xmlDefaultSAXHandler.endDocument = endDocument;
1369 xmlDefaultSAXHandler.startElement = startElement;
1370 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001371 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001372 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001373 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001374 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1375 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001376 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001377 if (xmlGetWarningsDefaultValue == 0)
1378 xmlDefaultSAXHandler.warning = NULL;
1379 else
1380 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001381 xmlDefaultSAXHandler.error = xmlParserError;
1382 xmlDefaultSAXHandler.fatalError = xmlParserError;
1383}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001384
1385/*
1386 * Default handler for HTML, builds the DOM tree
1387 */
1388xmlSAXHandler htmlDefaultSAXHandler = {
1389 NULL,
1390 NULL,
1391 NULL,
1392 NULL,
1393 NULL,
1394 getEntity,
1395 NULL,
1396 NULL,
1397 NULL,
1398 NULL,
1399 NULL,
1400 setDocumentLocator,
1401 startDocument,
1402 endDocument,
1403 startElement,
1404 endElement,
1405 NULL,
1406 characters,
1407 ignorableWhitespace,
1408 NULL,
1409 comment,
1410 xmlParserWarning,
1411 xmlParserError,
1412 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001413 getParameterEntity,
1414 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001415 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001416};
1417
1418/**
1419 * htmlDefaultSAXHandlerInit:
1420 *
1421 * Initialize the default SAX handler
1422 */
1423void
1424htmlDefaultSAXHandlerInit(void)
1425{
1426 htmlDefaultSAXHandler.internalSubset = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001427 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001428 htmlDefaultSAXHandler.isStandalone = NULL;
1429 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1430 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1431 htmlDefaultSAXHandler.resolveEntity = NULL;
1432 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001433 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001434 htmlDefaultSAXHandler.entityDecl = NULL;
1435 htmlDefaultSAXHandler.attributeDecl = NULL;
1436 htmlDefaultSAXHandler.elementDecl = NULL;
1437 htmlDefaultSAXHandler.notationDecl = NULL;
1438 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1439 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1440 htmlDefaultSAXHandler.startDocument = startDocument;
1441 htmlDefaultSAXHandler.endDocument = endDocument;
1442 htmlDefaultSAXHandler.startElement = startElement;
1443 htmlDefaultSAXHandler.endElement = endElement;
1444 htmlDefaultSAXHandler.reference = NULL;
1445 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001446 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001447 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1448 htmlDefaultSAXHandler.processingInstruction = NULL;
1449 htmlDefaultSAXHandler.comment = comment;
1450 htmlDefaultSAXHandler.warning = xmlParserWarning;
1451 htmlDefaultSAXHandler.error = xmlParserError;
1452 htmlDefaultSAXHandler.fatalError = xmlParserError;
1453}