blob: 5293df72291efd45a5c74870ef20d80760dede6b [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 Veillard260a68f1998-08-13 03:39:55 +0000598}
599
Daniel Veillard97b58771998-10-20 06:14:16 +0000600/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000601 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000602 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000603 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000604 * @value: The attribute value
605 *
606 * Handle an attribute that has been read by the parser.
607 * The default handling is to convert the attribute into an
608 * DOM subtree and past it in a new xmlAttr element added to
609 * the element.
610 */
611void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000612attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000613{
Daniel Veillard27d88741999-05-29 11:51:49 +0000614 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000615 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000616 xmlChar *name;
617 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000618 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000619 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000620
621/****************
622#ifdef DEBUG_SAX
623 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
624#endif
625 ****************/
626 /*
627 * Split the full name into a namespace prefix and the tag name
628 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000629 name = xmlSplitQName(ctxt, fullname, &ns);
630
631 /*
632 * Do the last stave of the attribute normalization
633 */
634 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
635 ctxt->node, fullname, value);
636 if (nval != NULL)
637 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000638
639 /*
640 * Check whether it's a namespace definition
641 */
642 if ((ns == NULL) &&
643 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
644 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
645 /* a default namespace definition */
646 xmlNewNs(ctxt->node, value, NULL);
647 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000648 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000649 if (nval != NULL)
650 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000651 return;
652 }
653 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
654 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000655 /*
656 * Validate also for namespace decls, they are attributes from
657 * an XML-1.0 perspective
658 TODO ... doesn't map well with current API
659 if (ctxt->validate && ctxt->wellFormed &&
660 ctxt->myDoc && ctxt->myDoc->intSubset)
661 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
662 ctxt->node, ret, value);
663 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000664 /* a standard namespace definition */
665 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000666 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000667 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000668 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000669 if (nval != NULL)
670 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000671 return;
672 }
673
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000674 if (ns != NULL)
675 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
676 else {
677 namespace = NULL;
678 }
679
Daniel Veillardb96e6431999-08-29 21:02:19 +0000680 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
681 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000682
Daniel Veillardb96e6431999-08-29 21:02:19 +0000683 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000684 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
685 xmlNodePtr tmp;
686
687 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
688 tmp = ret->children;
689 while (tmp != NULL) {
690 tmp->parent = (xmlNodePtr) ret;
691 if (tmp->next == NULL)
692 ret->last = tmp;
693 tmp = tmp->next;
694 }
695 } else {
696 ret->children = xmlNewDocText(ctxt->myDoc, value);
697 ret->last = ret->children;
698 if (ret->children != NULL)
699 ret->children->parent = (xmlNodePtr) ret;
700 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000701 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000702
703 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000704 ctxt->myDoc && ctxt->myDoc->intSubset) {
705
706 /*
707 * If we don't substitute entities, the validation should be
708 * done on a value with replaced entities anyway.
709 */
710 if (!ctxt->replaceEntities) {
711 xmlChar *val;
712
713 ctxt->depth++;
714 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
715 0,0,0);
716 ctxt->depth--;
717 if (val == NULL)
718 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
719 ctxt->myDoc, ctxt->node, ret, value);
720 else {
721 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
722 ctxt->myDoc, ctxt->node, ret, val);
723 xmlFree(val);
724 }
725 } else {
726 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000727 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000728 }
729 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000730 /*
731 * when validating, the ID registration is done at the attribute
732 * validation level. Otherwise we have to do specific handling here.
733 */
734 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
735 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000736 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
737 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000738 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000739
Daniel Veillardcf461992000-03-14 18:30:20 +0000740 if (nval != NULL)
741 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000742 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000743 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000744 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000745 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000746}
747
748/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000749 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000750 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000751 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000752 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000753 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000754 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000755 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000756void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000757startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000758{
Daniel Veillard27d88741999-05-29 11:51:49 +0000759 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000760 xmlNodePtr ret;
761 xmlNodePtr parent = ctxt->node;
762 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000763 xmlChar *name;
764 xmlChar *prefix;
765 const xmlChar *att;
766 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000767 int i;
768
Daniel Veillard260a68f1998-08-13 03:39:55 +0000769#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000770 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000771#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000772
773 /*
774 * First check on validity:
775 */
776 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
777 ((ctxt->myDoc->intSubset == NULL) ||
778 ((ctxt->myDoc->intSubset->notations == NULL) &&
779 (ctxt->myDoc->intSubset->elements == NULL) &&
780 (ctxt->myDoc->intSubset->attributes == NULL) &&
781 (ctxt->myDoc->intSubset->entities == NULL)))) {
782 if (ctxt->vctxt.error != NULL) {
783 ctxt->vctxt.error(ctxt->vctxt.userData,
784 "Validation failed: no DTD found !\n");
785 }
786 ctxt->validate = 0;
787 }
788
789
Daniel Veillard517752b1999-04-05 12:20:10 +0000790 /*
791 * Split the full name into a namespace prefix and the tag name
792 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000793 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000794
795
796 /*
797 * Note : the namespace resolution is deferred until the end of the
798 * attributes parsing, since local namespace can be defined as
799 * an attribute at this level.
800 */
801 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
802 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000803 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000804#ifdef DEBUG_SAX_TREE
805 fprintf(stderr, "Setting %s as root\n", name);
806#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000807 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000808 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000809 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000810 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000811
812 /*
813 * We are parsing a new node.
814 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000815#ifdef DEBUG_SAX_TREE
816 fprintf(stderr, "pushing(%s)\n", name);
817#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000818 nodePush(ctxt, ret);
819
820 /*
821 * Link the child element
822 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000823 if (parent != NULL) {
824 if (parent->type == XML_ELEMENT_NODE) {
825#ifdef DEBUG_SAX_TREE
826 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
827#endif
828 xmlAddChild(parent, ret);
829 } else {
830#ifdef DEBUG_SAX_TREE
831 fprintf(stderr, "adding sibling %s to ", name);
832 xmlDebugDumpOneNode(stderr, parent, 0);
833#endif
834 xmlAddSibling(parent, ret);
835 }
836 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000837
838 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000839 * If it's the Document root, finish the Dtd validation and
840 * check the document root element for validity
841 */
842 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
843 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
844 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
845 ctxt->vctxt.finishDtd = 1;
846 }
847 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000848 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000849 */
850 if (atts != NULL) {
851 i = 0;
852 att = atts[i++];
853 value = atts[i++];
854 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000855 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
856 attribute(ctxt, att, value);
857
858 att = atts[i++];
859 value = atts[i++];
860 }
861 }
862
863 /*
864 * process all the other attributes
865 */
866 if (atts != NULL) {
867 i = 0;
868 att = atts[i++];
869 value = atts[i++];
870 while ((att != NULL) && (value != NULL)) {
871 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
872 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000873
874 /*
875 * Next ones
876 */
877 att = atts[i++];
878 value = atts[i++];
879 }
880 }
881
882 /*
883 * Search the namespace, note that since the attributes have been
884 * processed, the local namespaces are available.
885 */
886 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
887 if ((ns == NULL) && (parent != NULL))
888 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
889 xmlSetNs(ret, ns);
890
891 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000892 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000893 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000894 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000895
Daniel Veillard260a68f1998-08-13 03:39:55 +0000896}
897
Daniel Veillard97b58771998-10-20 06:14:16 +0000898/**
899 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000900 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000901 * @name: The element name
902 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000903 * called when the end of an element has been detected.
904 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000905void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000906endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000907{
Daniel Veillard27d88741999-05-29 11:51:49 +0000908 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000909 xmlParserNodeInfo node_info;
910 xmlNodePtr cur = ctxt->node;
911
Daniel Veillard260a68f1998-08-13 03:39:55 +0000912#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000913 if (name == NULL)
914 fprintf(stderr, "SAX.endElement(NULL)\n");
915 else
916 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000917#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000918
919 /* Capture end position and add node */
920 if (cur != NULL && ctxt->record_info) {
921 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
922 node_info.end_line = ctxt->input->line;
923 node_info.node = cur;
924 xmlParserAddNodeInfo(ctxt, &node_info);
925 }
926
Daniel Veillardb05deb71999-08-10 19:04:08 +0000927 if (ctxt->validate && ctxt->wellFormed &&
928 ctxt->myDoc && ctxt->myDoc->intSubset)
929 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
930 cur);
931
932
Daniel Veillard517752b1999-04-05 12:20:10 +0000933 /*
934 * end of parsing of this node.
935 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000936#ifdef DEBUG_SAX_TREE
937 fprintf(stderr, "popping(%s)\n", cur->name);
938#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000939 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000940}
941
Daniel Veillard97b58771998-10-20 06:14:16 +0000942/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000943 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000944 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000945 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000946 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000947 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000948 */
949void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000950reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000951{
Daniel Veillard27d88741999-05-29 11:51:49 +0000952 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000953 xmlNodePtr ret;
954
Daniel Veillard11e00581998-10-24 18:27:49 +0000955#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000956 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000957#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000958 if (name[0] == '#')
959 ret = xmlNewCharRef(ctxt->myDoc, name);
960 else
961 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000962#ifdef DEBUG_SAX_TREE
963 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
964#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000965 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000966}
967
968/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000969 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000970 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000971 * @ch: a xmlChar string
972 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +0000973 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000974 * receiving some chars from the parser.
975 * Question: how much at a time ???
976 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000977void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000978characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000979{
Daniel Veillard27d88741999-05-29 11:51:49 +0000980 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000981 xmlNodePtr lastChild;
982
983#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000984 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000985#endif
986 /*
987 * Handle the data if any. If there is no child
988 * add it as content, otherwise if the last child is text,
989 * concatenate it, else create a new node of type text.
990 */
991
Daniel Veillard35008381999-10-25 13:15:52 +0000992 if (ctxt->node == NULL) {
993#ifdef DEBUG_SAX_TREE
994 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
995#endif
996 return;
997 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000998 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000999#ifdef DEBUG_SAX_TREE
1000 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1001#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001002 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +00001003 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001004 else {
1005 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +00001006 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001007 else {
Daniel Veillard517752b1999-04-05 12:20:10 +00001008 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001009 xmlAddChild(ctxt->node, lastChild);
1010 }
1011 }
1012}
1013
Daniel Veillard97b58771998-10-20 06:14:16 +00001014/**
1015 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001016 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001017 * @ch: a xmlChar string
1018 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001019 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001020 * receiving some ignorable whitespaces from the parser.
1021 * Question: how much at a time ???
1022 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001023void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001024ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001025{
Daniel Veillard27d88741999-05-29 11:51:49 +00001026 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001027#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001028 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001029#endif
1030}
1031
Daniel Veillard97b58771998-10-20 06:14:16 +00001032/**
1033 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001034 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001035 * @target: the target name
1036 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001037 *
1038 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001039 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001040void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001041processingInstruction(void *ctx, const xmlChar *target,
1042 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001043{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001044 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1045 xmlNodePtr ret;
1046 xmlNodePtr parent = ctxt->node;
1047
Daniel Veillard260a68f1998-08-13 03:39:55 +00001048#ifdef DEBUG_SAX
1049 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1050#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001051
1052 ret = xmlNewPI(target, data);
1053 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001054 parent = ctxt->node;
1055
1056 if (ctxt->inSubset == 1) {
1057 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1058 return;
1059 } else if (ctxt->inSubset == 2) {
1060 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1061 return;
1062 }
1063 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001064#ifdef DEBUG_SAX_TREE
1065 fprintf(stderr, "Setting PI %s as root\n", target);
1066#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001067 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1068 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001069 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001070 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001071#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001072 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001073#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001074 xmlAddChild(parent, ret);
1075 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001076#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001077 fprintf(stderr, "adding PI %s sibling to ", target);
1078 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001079#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001080 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001081 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001082}
1083
Daniel Veillard517752b1999-04-05 12:20:10 +00001084/**
1085 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001086 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001087 * @href: the namespace associated URN
1088 * @prefix: the namespace prefix
1089 *
1090 * An old global namespace has been parsed.
1091 */
1092void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001093globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001094{
Daniel Veillard27d88741999-05-29 11:51:49 +00001095 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001096#ifdef DEBUG_SAX
1097 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1098#endif
1099 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1100}
1101
1102/**
1103 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001104 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001105 * @name: the namespace prefix
1106 *
1107 * Set the current element namespace.
1108 */
Daniel Veillard06047432000-04-24 11:33:38 +00001109
Daniel Veillard517752b1999-04-05 12:20:10 +00001110void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001111setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001112{
Daniel Veillard27d88741999-05-29 11:51:49 +00001113 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001114 xmlNsPtr ns;
1115 xmlNodePtr parent;
1116
1117#ifdef DEBUG_SAX
1118 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1119#endif
1120 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1121 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1122 if (ctxt->nodeNr >= 2) {
1123 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1124 if (parent != NULL)
1125 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1126 }
1127 }
1128 xmlSetNs(ctxt->node, ns);
1129}
1130
1131/**
1132 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001133 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001134 *
1135 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001136 *
1137 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001138 */
Daniel Veillard06047432000-04-24 11:33:38 +00001139
Daniel Veillard517752b1999-04-05 12:20:10 +00001140xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001141getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001142{
Daniel Veillard27d88741999-05-29 11:51:49 +00001143 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001144 xmlNsPtr ret;
1145
1146#ifdef DEBUG_SAX
1147 fprintf(stderr, "SAX.getNamespace()\n");
1148#endif
1149 ret = ctxt->node->ns;
1150 return(ret);
1151}
1152
1153/**
1154 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001155 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001156 * @namespace: the namespace to check against
1157 *
1158 * Check that the current element namespace is the same as the
1159 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001160 *
1161 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001162 */
Daniel Veillard06047432000-04-24 11:33:38 +00001163
Daniel Veillard517752b1999-04-05 12:20:10 +00001164int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001165checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001166{
Daniel Veillard27d88741999-05-29 11:51:49 +00001167 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001168 xmlNodePtr cur = ctxt->node;
1169
1170#ifdef DEBUG_SAX
1171 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1172#endif
1173
1174 /*
1175 * Check that the Name in the ETag is the same as in the STag.
1176 */
1177 if (namespace == NULL) {
1178 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1179 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1180 ctxt->sax->error(ctxt,
1181 "End tags for %s don't hold the namespace %s\n",
1182 cur->name, cur->ns->prefix);
1183 ctxt->wellFormed = 0;
1184 }
1185 } else {
1186 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1187 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1188 ctxt->sax->error(ctxt,
1189 "End tags %s holds a prefix %s not used by the open tag\n",
1190 cur->name, namespace);
1191 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001192 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001193 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1194 ctxt->sax->error(ctxt,
1195 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1196 cur->name, cur->ns->prefix, namespace);
1197 ctxt->wellFormed = 0;
1198 } else
1199 return(1);
1200 }
1201 return(0);
1202}
1203
1204/**
1205 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001206 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001207 * @href: the namespace associated URN
1208 * @prefix: the namespace prefix
1209 *
1210 * A namespace has been parsed.
1211 */
1212void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001213namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001214{
Daniel Veillard27d88741999-05-29 11:51:49 +00001215 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001216#ifdef DEBUG_SAX
1217 if (prefix == NULL)
1218 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1219 else
1220 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1221#endif
1222 xmlNewNs(ctxt->node, href, prefix);
1223}
1224
1225/**
1226 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001227 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001228 * @value: the comment content
1229 *
1230 * A comment has been parsed.
1231 */
1232void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001233comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001234{
Daniel Veillard27d88741999-05-29 11:51:49 +00001235 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001236 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001237 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001238
Daniel Veillard517752b1999-04-05 12:20:10 +00001239#ifdef DEBUG_SAX
1240 fprintf(stderr, "SAX.comment(%s)\n", value);
1241#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001242 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001243 if (ret == NULL) return;
1244
Daniel Veillardcf461992000-03-14 18:30:20 +00001245 if (ctxt->inSubset == 1) {
1246 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1247 return;
1248 } else if (ctxt->inSubset == 2) {
1249 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1250 return;
1251 }
1252 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001253#ifdef DEBUG_SAX_TREE
1254 fprintf(stderr, "Setting comment as root\n");
1255#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001256 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1257 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001258 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001259 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001260#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001261 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001262#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001263 xmlAddChild(parent, ret);
1264 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001265#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001266 fprintf(stderr, "adding comment sibling to ");
1267 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001268#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001269 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001270 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001271}
1272
1273/**
1274 * cdataBlock:
1275 * @ctx: the user data (XML parser context)
1276 * @value: The pcdata content
1277 * @len: the block length
1278 *
1279 * called when a pcdata block has been parsed
1280 */
1281void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001282cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001283{
1284 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001285 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001286
1287#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001288 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001289#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001290 lastChild = xmlGetLastChild(ctxt->node);
1291#ifdef DEBUG_SAX_TREE
1292 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1293#endif
1294 if ((lastChild != NULL) &&
1295 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1296 xmlTextConcat(lastChild, value, len);
1297 } else {
1298 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1299 xmlAddChild(ctxt->node, ret);
1300 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001301}
1302
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001303/*
1304 * Default handler for XML, builds the DOM tree
1305 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001306xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001307 internalSubset,
1308 isStandalone,
1309 hasInternalSubset,
1310 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001311 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001312 getEntity,
1313 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001314 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001315 attributeDecl,
1316 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001317 unparsedEntityDecl,
1318 setDocumentLocator,
1319 startDocument,
1320 endDocument,
1321 startElement,
1322 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001323 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001324 characters,
1325 ignorableWhitespace,
1326 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001327 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001328 xmlParserWarning,
1329 xmlParserError,
1330 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001331 getParameterEntity,
1332 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001333 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001334};
1335
Daniel Veillard97b58771998-10-20 06:14:16 +00001336/**
1337 * xmlDefaultSAXHandlerInit:
1338 *
1339 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001340 */
1341void
1342xmlDefaultSAXHandlerInit(void)
1343{
Daniel Veillard517752b1999-04-05 12:20:10 +00001344 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001345 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001346 xmlDefaultSAXHandler.isStandalone = isStandalone;
1347 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1348 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001349 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001350 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001351 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001352 xmlDefaultSAXHandler.entityDecl = entityDecl;
1353 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1354 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001355 xmlDefaultSAXHandler.notationDecl = notationDecl;
1356 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1357 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1358 xmlDefaultSAXHandler.startDocument = startDocument;
1359 xmlDefaultSAXHandler.endDocument = endDocument;
1360 xmlDefaultSAXHandler.startElement = startElement;
1361 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001362 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001363 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001364 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001365 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1366 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001367 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001368 if (xmlGetWarningsDefaultValue == 0)
1369 xmlDefaultSAXHandler.warning = NULL;
1370 else
1371 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001372 xmlDefaultSAXHandler.error = xmlParserError;
1373 xmlDefaultSAXHandler.fatalError = xmlParserError;
1374}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001375
1376/*
1377 * Default handler for HTML, builds the DOM tree
1378 */
1379xmlSAXHandler htmlDefaultSAXHandler = {
1380 NULL,
1381 NULL,
1382 NULL,
1383 NULL,
1384 NULL,
1385 getEntity,
1386 NULL,
1387 NULL,
1388 NULL,
1389 NULL,
1390 NULL,
1391 setDocumentLocator,
1392 startDocument,
1393 endDocument,
1394 startElement,
1395 endElement,
1396 NULL,
1397 characters,
1398 ignorableWhitespace,
1399 NULL,
1400 comment,
1401 xmlParserWarning,
1402 xmlParserError,
1403 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001404 getParameterEntity,
1405 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001406 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001407};
1408
1409/**
1410 * htmlDefaultSAXHandlerInit:
1411 *
1412 * Initialize the default SAX handler
1413 */
1414void
1415htmlDefaultSAXHandlerInit(void)
1416{
1417 htmlDefaultSAXHandler.internalSubset = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001418 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001419 htmlDefaultSAXHandler.isStandalone = NULL;
1420 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1421 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1422 htmlDefaultSAXHandler.resolveEntity = NULL;
1423 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001424 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001425 htmlDefaultSAXHandler.entityDecl = NULL;
1426 htmlDefaultSAXHandler.attributeDecl = NULL;
1427 htmlDefaultSAXHandler.elementDecl = NULL;
1428 htmlDefaultSAXHandler.notationDecl = NULL;
1429 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1430 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1431 htmlDefaultSAXHandler.startDocument = startDocument;
1432 htmlDefaultSAXHandler.endDocument = endDocument;
1433 htmlDefaultSAXHandler.startElement = startElement;
1434 htmlDefaultSAXHandler.endElement = endElement;
1435 htmlDefaultSAXHandler.reference = NULL;
1436 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001437 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001438 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1439 htmlDefaultSAXHandler.processingInstruction = NULL;
1440 htmlDefaultSAXHandler.comment = comment;
1441 htmlDefaultSAXHandler.warning = xmlParserWarning;
1442 htmlDefaultSAXHandler.error = xmlParserError;
1443 htmlDefaultSAXHandler.fatalError = xmlParserError;
1444}