blob: ee3af393c996bc517424f02b6b7d274d928e1b47 [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
Daniel Veillard97b58771998-10-20 06:14:16 +00003 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004 * See Copyright for the status of this software.
5 *
Daniel Veillard97b58771998-10-20 06:14:16 +00006 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
Daniel Veillard7f7d1111999-09-22 09:46:25 +00009
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#ifdef WIN32
11#include "win32config.h"
12#else
13#include "config.h"
14#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000016#include <stdlib.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000017#include <libxml/xmlmemory.h>
18#include <libxml/tree.h>
19#include <libxml/parser.h>
20#include <libxml/parserInternals.h>
21#include <libxml/valid.h>
22#include <libxml/entities.h>
Daniel Veillardd109e371999-03-05 06:26:45 +000023#include "xml-error.h"
Daniel Veillard361d8452000-04-03 19:48:13 +000024#include <libxml/debugXML.h>
25#include <libxml/xmlIO.h>
26#include <libxml/SAX.h>
Daniel Veillardbe803962000-06-28 23:40:59 +000027#include <libxml/uri.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000028
29/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000030/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000031
Daniel Veillard97b58771998-10-20 06:14:16 +000032/**
33 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000034 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000035 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000036 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000037 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000038 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000039 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000040const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000041getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000042{
Daniel Veillard27d88741999-05-29 11:51:49 +000043 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000044 return(NULL);
45}
46
Daniel Veillard97b58771998-10-20 06:14:16 +000047/**
48 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000049 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000050 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000051 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000052 * http://www.sgmlsource.com/dtds/memo.dtd
53 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000054 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000055 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000056const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000057getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000058{
Daniel Veillard27d88741999-05-29 11:51:49 +000059 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000060 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000061}
62
Daniel Veillard97b58771998-10-20 06:14:16 +000063/**
64 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000065 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000066 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000067 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000068 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000069 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000070 */
Daniel Veillard97b58771998-10-20 06:14:16 +000071int
Daniel Veillard27d88741999-05-29 11:51:49 +000072getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000073{
Daniel Veillard27d88741999-05-29 11:51:49 +000074 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000075 return(ctxt->input->line);
76}
Daniel Veillard97b58771998-10-20 06:14:16 +000077
78/**
79 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000080 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000081 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000082 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000083 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000084 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000085 */
Daniel Veillard97b58771998-10-20 06:14:16 +000086int
Daniel Veillard27d88741999-05-29 11:51:49 +000087getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000088{
Daniel Veillard27d88741999-05-29 11:51:49 +000089 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 return(ctxt->input->col);
91}
92
93/*
94 * The default SAX Locator.
95 */
96
97xmlSAXLocator xmlDefaultSAXLocator = {
98 getPublicId, getSystemId, getLineNumber, getColumnNumber
99};
100
Daniel Veillard97b58771998-10-20 06:14:16 +0000101/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000102 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000103 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000104 *
105 * Is this document tagged standalone ?
106 *
107 * Returns 1 if true
108 */
109int
Daniel Veillard27d88741999-05-29 11:51:49 +0000110isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000111{
Daniel Veillard27d88741999-05-29 11:51:49 +0000112 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000113 return(ctxt->myDoc->standalone == 1);
114}
115
116/**
117 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000118 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000119 *
120 * Does this document has an internal subset
121 *
122 * Returns 1 if true
123 */
124int
Daniel Veillard27d88741999-05-29 11:51:49 +0000125hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000126{
Daniel Veillard27d88741999-05-29 11:51:49 +0000127 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000128 return(ctxt->myDoc->intSubset != NULL);
129}
130
131/**
132 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000133 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000134 *
135 * Does this document has an external subset
136 *
137 * Returns 1 if true
138 */
139int
Daniel Veillard27d88741999-05-29 11:51:49 +0000140hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000141{
Daniel Veillard27d88741999-05-29 11:51:49 +0000142 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000143 return(ctxt->myDoc->extSubset != NULL);
144}
145
146/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000147 * internalSubset:
Daniel Veillard06047432000-04-24 11:33:38 +0000148 * @ctx: the user data (XML parser context)
149 * @name: the root element name
150 * @ExternalID: the external ID
151 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000152 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000153 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000154 */
155void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000156internalSubset(void *ctx, const xmlChar *name,
157 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000158{
Daniel Veillard27d88741999-05-29 11:51:49 +0000159 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000160#ifdef DEBUG_SAX
161 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
162 name, ExternalID, SystemID);
163#endif
164 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000165}
166
167/**
168 * externalSubset:
169 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000170 * @name: the root element name
171 * @ExternalID: the external ID
172 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000173 *
174 * Callback on external subset declaration.
175 */
176void
177externalSubset(void *ctx, const xmlChar *name,
178 const xmlChar *ExternalID, const xmlChar *SystemID)
179{
180 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
181#ifdef DEBUG_SAX
182 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
183 name, ExternalID, SystemID);
184#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000185 if (((ExternalID != NULL) || (SystemID != NULL)) &&
186 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
187 /*
188 * Try to fetch and parse the external subset.
189 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000190 xmlParserInputPtr oldinput;
191 int oldinputNr;
192 int oldinputMax;
193 xmlParserInputPtr *oldinputTab;
194 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000195 xmlParserInputPtr input = NULL;
196 xmlCharEncoding enc;
Daniel Veillardbe803962000-06-28 23:40:59 +0000197 xmlCharEncoding oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000198
Daniel Veillardb05deb71999-08-10 19:04:08 +0000199 /*
200 * Ask the Entity resolver to load the damn thing
201 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000202 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
203 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000204 SystemID);
205 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000206 return;
207 }
208
Daniel Veillardcf461992000-03-14 18:30:20 +0000209 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
210
Daniel Veillardb05deb71999-08-10 19:04:08 +0000211 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000212 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000213 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000214 oldinput = ctxt->input;
215 oldinputNr = ctxt->inputNr;
216 oldinputMax = ctxt->inputMax;
217 oldinputTab = ctxt->inputTab;
218 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000219 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000220
221 ctxt->inputTab = (xmlParserInputPtr *)
222 xmlMalloc(5 * sizeof(xmlParserInputPtr));
223 if (ctxt->inputTab == NULL) {
224 ctxt->errNo = XML_ERR_NO_MEMORY;
225 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
226 ctxt->sax->error(ctxt->userData,
227 "externalSubset: out of memory\n");
228 ctxt->errNo = XML_ERR_NO_MEMORY;
229 ctxt->input = oldinput;
230 ctxt->inputNr = oldinputNr;
231 ctxt->inputMax = oldinputMax;
232 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000233 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000234 return;
235 }
236 ctxt->inputNr = 0;
237 ctxt->inputMax = 5;
238 ctxt->input = NULL;
239 xmlPushInput(ctxt, input);
240
241 /*
242 * On the fly encoding conversion if needed
243 */
244 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
245 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000246
247 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000248 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000249 input->line = 1;
250 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000251 input->base = ctxt->input->cur;
252 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000253 input->free = NULL;
254
255 /*
256 * let's parse that entity knowing it's an external subset.
257 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000258 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000259
Daniel Veillardcf461992000-03-14 18:30:20 +0000260 /*
261 * Free up the external entities
262 */
263
264 while (ctxt->inputNr > 1)
265 xmlPopInput(ctxt);
266 xmlFreeInputStream(ctxt->input);
267 xmlFree(ctxt->inputTab);
268
269 /*
270 * Restore the parsing context of the main entity
271 */
272 ctxt->input = oldinput;
273 ctxt->inputNr = oldinputNr;
274 ctxt->inputMax = oldinputMax;
275 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000276 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000277 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000278 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000279}
280
281/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000282 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000283 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000284 * @publicId: The public ID of the entity
285 * @systemId: The system ID of the entity
286 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000287 * The entity loader, to control the loading of external entities,
288 * the application can either:
289 * - override this resolveEntity() callback in the SAX block
290 * - or better use the xmlSetExternalEntityLoader() function to
291 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000292 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000293 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000294 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000295xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000296resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000297{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000299
300#ifdef DEBUG_SAX
301 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
302#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000303
Daniel Veillard686d6b62000-01-03 11:08:02 +0000304 return(xmlLoadExternalEntity((const char *) systemId,
305 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000306}
307
Daniel Veillard97b58771998-10-20 06:14:16 +0000308/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000309 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000310 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000311 * @name: The entity name
312 *
313 * Get an entity by name
314 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000315 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000316 */
317xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000318getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000319{
Daniel Veillard27d88741999-05-29 11:51:49 +0000320 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000321 xmlEntityPtr ret;
322
323#ifdef DEBUG_SAX
324 fprintf(stderr, "SAX.getEntity(%s)\n", name);
325#endif
326
327 ret = xmlGetDocEntity(ctxt->myDoc, name);
328 return(ret);
329}
330
Daniel Veillardb05deb71999-08-10 19:04:08 +0000331/**
332 * getParameterEntity:
333 * @ctx: the user data (XML parser context)
334 * @name: The entity name
335 *
336 * Get a parameter entity by name
337 *
338 * Returns the xmlEntityPtr if found.
339 */
340xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000341getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000342{
343 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
344 xmlEntityPtr ret;
345
346#ifdef DEBUG_SAX
347 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
348#endif
349
350 ret = xmlGetParameterEntity(ctxt->myDoc, name);
351 return(ret);
352}
353
Daniel Veillard517752b1999-04-05 12:20:10 +0000354
355/**
356 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000357 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000358 * @name: the entity name
359 * @type: the entity type
360 * @publicId: The public ID of the entity
361 * @systemId: The system ID of the entity
362 * @content: the entity value (without processing).
363 *
364 * An entity definition has been parsed
365 */
366void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000367entityDecl(void *ctx, const xmlChar *name, int type,
368 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000369{
Daniel Veillard27d88741999-05-29 11:51:49 +0000370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000371
372#ifdef DEBUG_SAX
373 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
374 name, type, publicId, systemId, content);
375#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000376 if (ctxt->inSubset == 1)
377 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
378 systemId, content);
379 else if (ctxt->inSubset == 2)
380 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
381 systemId, content);
382 else {
383 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
384 ctxt->sax->error(ctxt,
385 "SAX.entityDecl(%s) called while not in subset\n", name);
386 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000387}
388
389/**
390 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000391 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000392 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000393 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000394 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000395 * @def: the type of default value
396 * @defaultValue: the attribute default value
397 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000398 *
399 * An attribute definition has been parsed
400 */
401void
Daniel Veillardcf461992000-03-14 18:30:20 +0000402attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000403 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000404 xmlEnumerationPtr tree)
405{
Daniel Veillard27d88741999-05-29 11:51:49 +0000406 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000407 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000408 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000409
410#ifdef DEBUG_SAX
411 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000412 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000413#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000414 name = xmlSplitQName(ctxt, fullname, &prefix);
415 if (ctxt->inSubset == 1)
416 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
417 name, prefix, type, def, defaultValue, tree);
418 else if (ctxt->inSubset == 2)
419 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
420 name, prefix, type, def, defaultValue, tree);
421 else {
422 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
423 ctxt->sax->error(ctxt,
424 "SAX.attributeDecl(%s) called while not in subset\n", name);
425 return;
426 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000427 if (attr == 0) ctxt->valid = 0;
428 if (ctxt->validate && ctxt->wellFormed &&
429 ctxt->myDoc && ctxt->myDoc->intSubset)
430 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
431 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000432 if (prefix != NULL)
433 xmlFree(prefix);
434 if (name != NULL)
435 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000436}
437
438/**
439 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000440 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000441 * @name: the element name
442 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000443 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000444 *
445 * An element definition has been parsed
446 */
447void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000448elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000449 xmlElementContentPtr content)
450{
Daniel Veillard27d88741999-05-29 11:51:49 +0000451 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000452 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000453
454#ifdef DEBUG_SAX
455 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000456 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000457#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000458
Daniel Veillardcf461992000-03-14 18:30:20 +0000459 if (ctxt->inSubset == 1)
460 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000461 name, type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000462 else if (ctxt->inSubset == 2)
463 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
464 name, type, content);
465 else {
466 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
467 ctxt->sax->error(ctxt,
468 "SAX.elementDecl(%s) called while not in subset\n", name);
469 return;
470 }
471 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000472 if (ctxt->validate && ctxt->wellFormed &&
473 ctxt->myDoc && ctxt->myDoc->intSubset)
474 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000475}
476
477/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000478 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000479 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000480 * @name: The name of the notation
481 * @publicId: The public ID of the entity
482 * @systemId: The system ID of the entity
483 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000485 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000486void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000487notationDecl(void *ctx, const xmlChar *name,
488 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000489{
Daniel Veillard27d88741999-05-29 11:51:49 +0000490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000491 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000492
Daniel Veillard260a68f1998-08-13 03:39:55 +0000493#ifdef DEBUG_SAX
494 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
495#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000496
Daniel Veillardcf461992000-03-14 18:30:20 +0000497 if (ctxt->inSubset == 1)
498 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000499 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000500 else if (ctxt->inSubset == 2)
501 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
502 publicId, systemId);
503 else {
504 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
505 ctxt->sax->error(ctxt,
506 "SAX.notationDecl(%s) called while not in subset\n", name);
507 return;
508 }
509 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000510 if (ctxt->validate && ctxt->wellFormed &&
511 ctxt->myDoc && ctxt->myDoc->intSubset)
512 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
513 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000514}
515
Daniel Veillard97b58771998-10-20 06:14:16 +0000516/**
517 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000518 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000519 * @name: The name of the entity
520 * @publicId: The public ID of the entity
521 * @systemId: The system ID of the entity
522 * @notationName: the name of the notation
523 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000524 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000525 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000526void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000527unparsedEntityDecl(void *ctx, const xmlChar *name,
528 const xmlChar *publicId, const xmlChar *systemId,
529 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000530{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000531 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000532#ifdef DEBUG_SAX
533 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
534 name, publicId, systemId, notationName);
535#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000536 if (ctxt->validate && ctxt->wellFormed &&
537 ctxt->myDoc && ctxt->myDoc->intSubset)
538 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
539 notationName);
540 xmlAddDocEntity(ctxt->myDoc, name,
541 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
542 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000543}
544
Daniel Veillard97b58771998-10-20 06:14:16 +0000545/**
546 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000547 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000548 * @loc: A SAX Locator
549 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000550 * Receive the document locator at startup, actually xmlDefaultSAXLocator
551 * Everything is available on the context, so this is useless in our case.
552 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000553void
Daniel Veillard27d88741999-05-29 11:51:49 +0000554setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000555{
Daniel Veillard27d88741999-05-29 11:51:49 +0000556 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000557#ifdef DEBUG_SAX
558 fprintf(stderr, "SAX.setDocumentLocator()\n");
559#endif
560}
561
Daniel Veillard97b58771998-10-20 06:14:16 +0000562/**
563 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000564 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000565 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000566 * called when the document start being processed.
567 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000568void
Daniel Veillard27d88741999-05-29 11:51:49 +0000569startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000570{
Daniel Veillard27d88741999-05-29 11:51:49 +0000571 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000572 xmlDocPtr doc;
573
Daniel Veillard260a68f1998-08-13 03:39:55 +0000574#ifdef DEBUG_SAX
575 fprintf(stderr, "SAX.startDocument()\n");
576#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000577 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
578 if (doc != NULL) {
579 if (ctxt->encoding != NULL)
580 doc->encoding = xmlStrdup(ctxt->encoding);
581 else
582 doc->encoding = NULL;
583 doc->standalone = ctxt->standalone;
584 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000585}
586
Daniel Veillard97b58771998-10-20 06:14:16 +0000587/**
588 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000589 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000590 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000591 * called when the document end has been detected.
592 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000593void
Daniel Veillard27d88741999-05-29 11:51:49 +0000594endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000595{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000596 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000597#ifdef DEBUG_SAX
598 fprintf(stderr, "SAX.endDocument()\n");
599#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000600 if (ctxt->validate && ctxt->wellFormed &&
601 ctxt->myDoc && ctxt->myDoc->intSubset)
602 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000603
604 /*
605 * Grab the encoding if it was added on-the-fly
606 */
607 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
608 (ctxt->myDoc->encoding == NULL)) {
609 ctxt->myDoc->encoding = ctxt->encoding;
610 ctxt->encoding = NULL;
611 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000612 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
613 (ctxt->myDoc->encoding == NULL)) {
614 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
615 }
616 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
617 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
618 ctxt->myDoc->charset = ctxt->charset;
619 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000620}
621
Daniel Veillard97b58771998-10-20 06:14:16 +0000622/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000623 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000624 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000625 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000626 * @value: The attribute value
627 *
628 * Handle an attribute that has been read by the parser.
629 * The default handling is to convert the attribute into an
630 * DOM subtree and past it in a new xmlAttr element added to
631 * the element.
632 */
633void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000634attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000635{
Daniel Veillard27d88741999-05-29 11:51:49 +0000636 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000637 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000638 xmlChar *name;
639 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000640 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000641 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000642
643/****************
644#ifdef DEBUG_SAX
645 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
646#endif
647 ****************/
648 /*
649 * Split the full name into a namespace prefix and the tag name
650 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000651 name = xmlSplitQName(ctxt, fullname, &ns);
652
653 /*
654 * Do the last stave of the attribute normalization
655 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000656 if (ctxt->html)
657 nval = NULL;
658 else
659 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
Daniel Veillardcf461992000-03-14 18:30:20 +0000660 ctxt->node, fullname, value);
661 if (nval != NULL)
662 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000663
664 /*
665 * Check whether it's a namespace definition
666 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000667 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000668 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
669 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000670 xmlURIPtr uri;
671
672 uri = xmlParseURI((const char *)value);
673 if (uri == NULL) {
674 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
675 ctxt->sax->warning(ctxt->userData,
676 "nmlns: %s not a valid URI\n", value);
677 } else {
678 if (uri->scheme == NULL) {
679 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
680 ctxt->sax->warning(ctxt->userData,
681 "nmlns: URI %s is not absolute\n", value);
682 }
683 xmlFreeURI(uri);
684 }
685
Daniel Veillard517752b1999-04-05 12:20:10 +0000686 /* a default namespace definition */
687 xmlNewNs(ctxt->node, value, NULL);
688 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000689 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000690 if (nval != NULL)
691 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000692 return;
693 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000694 if ((!ctxt->html) &&
695 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000696 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000697 /*
698 * Validate also for namespace decls, they are attributes from
699 * an XML-1.0 perspective
700 TODO ... doesn't map well with current API
701 if (ctxt->validate && ctxt->wellFormed &&
702 ctxt->myDoc && ctxt->myDoc->intSubset)
703 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
704 ctxt->node, ret, value);
705 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000706 /* a standard namespace definition */
707 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000708 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000709 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000710 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000711 if (nval != NULL)
712 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000713 return;
714 }
715
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000716 if (ns != NULL)
717 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
718 else {
719 namespace = NULL;
720 }
721
Daniel Veillardb96e6431999-08-29 21:02:19 +0000722 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
723 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000724
Daniel Veillardb96e6431999-08-29 21:02:19 +0000725 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000726 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
727 xmlNodePtr tmp;
728
729 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
730 tmp = ret->children;
731 while (tmp != NULL) {
732 tmp->parent = (xmlNodePtr) ret;
733 if (tmp->next == NULL)
734 ret->last = tmp;
735 tmp = tmp->next;
736 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000737 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000738 ret->children = xmlNewDocText(ctxt->myDoc, value);
739 ret->last = ret->children;
740 if (ret->children != NULL)
741 ret->children->parent = (xmlNodePtr) ret;
742 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000743 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000744
Daniel Veillardbe803962000-06-28 23:40:59 +0000745 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000746 ctxt->myDoc && ctxt->myDoc->intSubset) {
747
748 /*
749 * If we don't substitute entities, the validation should be
750 * done on a value with replaced entities anyway.
751 */
752 if (!ctxt->replaceEntities) {
753 xmlChar *val;
754
755 ctxt->depth++;
756 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
757 0,0,0);
758 ctxt->depth--;
759 if (val == NULL)
760 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
761 ctxt->myDoc, ctxt->node, ret, value);
762 else {
763 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
764 ctxt->myDoc, ctxt->node, ret, val);
765 xmlFree(val);
766 }
767 } else {
768 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000769 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000770 }
771 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000772 /*
773 * when validating, the ID registration is done at the attribute
774 * validation level. Otherwise we have to do specific handling here.
775 */
776 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
777 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000778 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
779 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000780 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000781
Daniel Veillardcf461992000-03-14 18:30:20 +0000782 if (nval != NULL)
783 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000784 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000785 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000786 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000787 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000788}
789
790/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000791 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000792 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000793 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000794 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000795 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000796 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000797 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000798void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000799startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000800{
Daniel Veillard27d88741999-05-29 11:51:49 +0000801 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000802 xmlNodePtr ret;
803 xmlNodePtr parent = ctxt->node;
804 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000805 xmlChar *name;
806 xmlChar *prefix;
807 const xmlChar *att;
808 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000809 int i;
810
Daniel Veillard260a68f1998-08-13 03:39:55 +0000811#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000812 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000813#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000814
815 /*
816 * First check on validity:
817 */
818 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
819 ((ctxt->myDoc->intSubset == NULL) ||
820 ((ctxt->myDoc->intSubset->notations == NULL) &&
821 (ctxt->myDoc->intSubset->elements == NULL) &&
822 (ctxt->myDoc->intSubset->attributes == NULL) &&
823 (ctxt->myDoc->intSubset->entities == NULL)))) {
824 if (ctxt->vctxt.error != NULL) {
825 ctxt->vctxt.error(ctxt->vctxt.userData,
826 "Validation failed: no DTD found !\n");
827 }
828 ctxt->validate = 0;
829 }
830
831
Daniel Veillard517752b1999-04-05 12:20:10 +0000832 /*
833 * Split the full name into a namespace prefix and the tag name
834 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000835 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000836
837
838 /*
839 * Note : the namespace resolution is deferred until the end of the
840 * attributes parsing, since local namespace can be defined as
841 * an attribute at this level.
842 */
843 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
844 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000845 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000846#ifdef DEBUG_SAX_TREE
847 fprintf(stderr, "Setting %s as root\n", name);
848#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000849 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000850 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000851 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000852 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000853 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000854
855 /*
856 * We are parsing a new node.
857 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000858#ifdef DEBUG_SAX_TREE
859 fprintf(stderr, "pushing(%s)\n", name);
860#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000861 nodePush(ctxt, ret);
862
863 /*
864 * Link the child element
865 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000866 if (parent != NULL) {
867 if (parent->type == XML_ELEMENT_NODE) {
868#ifdef DEBUG_SAX_TREE
869 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
870#endif
871 xmlAddChild(parent, ret);
872 } else {
873#ifdef DEBUG_SAX_TREE
874 fprintf(stderr, "adding sibling %s to ", name);
875 xmlDebugDumpOneNode(stderr, parent, 0);
876#endif
877 xmlAddSibling(parent, ret);
878 }
879 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000880
881 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000882 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000883 */
884 if (atts != NULL) {
885 i = 0;
886 att = atts[i++];
887 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000888 if (!ctxt->html) {
889 while ((att != NULL) && (value != NULL)) {
890 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
891 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000892
Daniel Veillardbe803962000-06-28 23:40:59 +0000893 att = atts[i++];
894 value = atts[i++];
895 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000896 }
897 }
898
899 /*
900 * Search the namespace, note that since the attributes have been
901 * processed, the local namespaces are available.
902 */
903 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
904 if ((ns == NULL) && (parent != NULL))
905 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
906 xmlSetNs(ret, ns);
907
Daniel Veillardbe803962000-06-28 23:40:59 +0000908 /*
909 * process all the other attributes
910 */
911 if (atts != NULL) {
912 i = 0;
913 att = atts[i++];
914 value = atts[i++];
915 if (ctxt->html) {
916 while (att != NULL) {
917 attribute(ctxt, att, value);
918 att = atts[i++];
919 value = atts[i++];
920 }
921 } else {
922 while ((att != NULL) && (value != NULL)) {
923 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
924 attribute(ctxt, att, value);
925
926 /*
927 * Next ones
928 */
929 att = atts[i++];
930 value = atts[i++];
931 }
932 }
933 }
934
935 /*
936 * If it's the Document root, finish the Dtd validation and
937 * check the document root element for validity
938 */
939 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
940 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
941 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
942 ctxt->vctxt.finishDtd = 1;
943 }
944
Daniel Veillard517752b1999-04-05 12:20:10 +0000945 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000946 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000947 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000948 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000949
Daniel Veillard260a68f1998-08-13 03:39:55 +0000950}
951
Daniel Veillard97b58771998-10-20 06:14:16 +0000952/**
953 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000954 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000955 * @name: The element name
956 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000957 * called when the end of an element has been detected.
958 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000959void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000960endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000961{
Daniel Veillard27d88741999-05-29 11:51:49 +0000962 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000963 xmlParserNodeInfo node_info;
964 xmlNodePtr cur = ctxt->node;
965
Daniel Veillard260a68f1998-08-13 03:39:55 +0000966#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000967 if (name == NULL)
968 fprintf(stderr, "SAX.endElement(NULL)\n");
969 else
970 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000971#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000972
973 /* Capture end position and add node */
974 if (cur != NULL && ctxt->record_info) {
975 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
976 node_info.end_line = ctxt->input->line;
977 node_info.node = cur;
978 xmlParserAddNodeInfo(ctxt, &node_info);
979 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000980 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000981
Daniel Veillardb05deb71999-08-10 19:04:08 +0000982 if (ctxt->validate && ctxt->wellFormed &&
983 ctxt->myDoc && ctxt->myDoc->intSubset)
984 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
985 cur);
986
987
Daniel Veillard517752b1999-04-05 12:20:10 +0000988 /*
989 * end of parsing of this node.
990 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000991#ifdef DEBUG_SAX_TREE
992 fprintf(stderr, "popping(%s)\n", cur->name);
993#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000994 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000995}
996
Daniel Veillard97b58771998-10-20 06:14:16 +0000997/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000998 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000999 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001000 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001001 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001002 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001003 */
1004void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001005reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001006{
Daniel Veillard27d88741999-05-29 11:51:49 +00001007 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001008 xmlNodePtr ret;
1009
Daniel Veillard11e00581998-10-24 18:27:49 +00001010#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001011 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001012#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001013 if (name[0] == '#')
1014 ret = xmlNewCharRef(ctxt->myDoc, name);
1015 else
1016 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001017#ifdef DEBUG_SAX_TREE
1018 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
1019#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001020 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001021}
1022
1023/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001024 * characters:
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 chars 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 +00001033characters(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 xmlNodePtr lastChild;
1037
1038#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001039 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001040#endif
1041 /*
1042 * Handle the data if any. If there is no child
1043 * add it as content, otherwise if the last child is text,
1044 * concatenate it, else create a new node of type text.
1045 */
1046
Daniel Veillard35008381999-10-25 13:15:52 +00001047 if (ctxt->node == NULL) {
1048#ifdef DEBUG_SAX_TREE
1049 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1050#endif
1051 return;
1052 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001053 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001054#ifdef DEBUG_SAX_TREE
1055 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1056#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001057
1058 /*
1059 * Here we needed an accelerator mechanism in case of very large
1060 * elements. Use an attribute in the structure !!!
1061 */
1062 if (lastChild == NULL) {
1063 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001064 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001065#ifndef XML_USE_BUFFER_CONTENT
1066 if (ctxt->node->children != NULL) {
1067 ctxt->nodelen = len;
1068 ctxt->nodemem = len + 1;
1069 }
1070#endif
1071 } else {
1072 if (xmlNodeIsText(lastChild)) {
1073#ifndef XML_USE_BUFFER_CONTENT
1074 /*
1075 * The whole point of maintaining nodelen and nodemem,
1076 * xmlTextConcat is too costly, i.e. compute lenght,
1077 * reallocate a new buffer, move data, append ch. Here
1078 * We try to minimaze realloc() uses and avoid copying
1079 * and recomputing lenght over and over.
1080 */
1081 if (ctxt->nodelen + len >= ctxt->nodemem) {
1082 xmlChar *newbuf;
1083 int size;
1084
1085 size = ctxt->nodemem + len;
1086 size *= 2;
1087 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1088 if (newbuf == NULL) {
1089 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1090 ctxt->sax->error(ctxt->userData,
1091 "SAX.characters(): out of memory\n");
1092 return;
1093 }
1094 ctxt->nodemem = size;
1095 lastChild->content = newbuf;
1096 }
1097 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1098 ctxt->nodelen += len;
1099 lastChild->content[ctxt->nodelen] = 0;
1100#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001101 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001102#endif
1103 } else {
1104 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001105 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001106 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001107#ifndef XML_USE_BUFFER_CONTENT
1108 if (ctxt->node->children != NULL) {
1109 ctxt->nodelen = len;
1110 ctxt->nodemem = len + 1;
1111 }
1112#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001113 }
1114 }
1115}
1116
Daniel Veillard97b58771998-10-20 06:14:16 +00001117/**
1118 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001119 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001120 * @ch: a xmlChar string
1121 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001122 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001123 * receiving some ignorable whitespaces from the parser.
1124 * Question: how much at a time ???
1125 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001126void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001127ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001128{
Daniel Veillard27d88741999-05-29 11:51:49 +00001129 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001130#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001131 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001132#endif
1133}
1134
Daniel Veillard97b58771998-10-20 06:14:16 +00001135/**
1136 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001137 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001138 * @target: the target name
1139 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001140 *
1141 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001142 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001143void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001144processingInstruction(void *ctx, const xmlChar *target,
1145 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001146{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001147 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1148 xmlNodePtr ret;
1149 xmlNodePtr parent = ctxt->node;
1150
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151#ifdef DEBUG_SAX
1152 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1153#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001154
1155 ret = xmlNewPI(target, data);
1156 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001157 parent = ctxt->node;
1158
1159 if (ctxt->inSubset == 1) {
1160 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1161 return;
1162 } else if (ctxt->inSubset == 2) {
1163 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1164 return;
1165 }
1166 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001167#ifdef DEBUG_SAX_TREE
1168 fprintf(stderr, "Setting PI %s as root\n", target);
1169#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001170 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1171 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001172 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001173 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001174#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001175 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001176#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001177 xmlAddChild(parent, ret);
1178 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001179#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001180 fprintf(stderr, "adding PI %s sibling to ", target);
1181 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001182#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001183 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001184 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001185}
1186
Daniel Veillard517752b1999-04-05 12:20:10 +00001187/**
1188 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001189 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001190 * @href: the namespace associated URN
1191 * @prefix: the namespace prefix
1192 *
1193 * An old global namespace has been parsed.
1194 */
1195void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001196globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001197{
Daniel Veillard27d88741999-05-29 11:51:49 +00001198 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001199#ifdef DEBUG_SAX
1200 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1201#endif
1202 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1203}
1204
1205/**
1206 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001207 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001208 * @name: the namespace prefix
1209 *
1210 * Set the current element namespace.
1211 */
Daniel Veillard06047432000-04-24 11:33:38 +00001212
Daniel Veillard517752b1999-04-05 12:20:10 +00001213void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001214setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001215{
Daniel Veillard27d88741999-05-29 11:51:49 +00001216 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001217 xmlNsPtr ns;
1218 xmlNodePtr parent;
1219
1220#ifdef DEBUG_SAX
1221 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1222#endif
1223 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1224 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1225 if (ctxt->nodeNr >= 2) {
1226 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1227 if (parent != NULL)
1228 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1229 }
1230 }
1231 xmlSetNs(ctxt->node, ns);
1232}
1233
1234/**
1235 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001236 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001237 *
1238 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001239 *
1240 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001241 */
Daniel Veillard06047432000-04-24 11:33:38 +00001242
Daniel Veillard517752b1999-04-05 12:20:10 +00001243xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001244getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001245{
Daniel Veillard27d88741999-05-29 11:51:49 +00001246 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001247 xmlNsPtr ret;
1248
1249#ifdef DEBUG_SAX
1250 fprintf(stderr, "SAX.getNamespace()\n");
1251#endif
1252 ret = ctxt->node->ns;
1253 return(ret);
1254}
1255
1256/**
1257 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001258 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001259 * @namespace: the namespace to check against
1260 *
1261 * Check that the current element namespace is the same as the
1262 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001263 *
1264 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001265 */
Daniel Veillard06047432000-04-24 11:33:38 +00001266
Daniel Veillard517752b1999-04-05 12:20:10 +00001267int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001268checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001269{
Daniel Veillard27d88741999-05-29 11:51:49 +00001270 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001271 xmlNodePtr cur = ctxt->node;
1272
1273#ifdef DEBUG_SAX
1274 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1275#endif
1276
1277 /*
1278 * Check that the Name in the ETag is the same as in the STag.
1279 */
1280 if (namespace == NULL) {
1281 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1282 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1283 ctxt->sax->error(ctxt,
1284 "End tags for %s don't hold the namespace %s\n",
1285 cur->name, cur->ns->prefix);
1286 ctxt->wellFormed = 0;
1287 }
1288 } else {
1289 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1290 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1291 ctxt->sax->error(ctxt,
1292 "End tags %s holds a prefix %s not used by the open tag\n",
1293 cur->name, namespace);
1294 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001295 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001296 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1297 ctxt->sax->error(ctxt,
1298 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1299 cur->name, cur->ns->prefix, namespace);
1300 ctxt->wellFormed = 0;
1301 } else
1302 return(1);
1303 }
1304 return(0);
1305}
1306
1307/**
1308 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001309 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001310 * @href: the namespace associated URN
1311 * @prefix: the namespace prefix
1312 *
1313 * A namespace has been parsed.
1314 */
1315void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001316namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001317{
Daniel Veillard27d88741999-05-29 11:51:49 +00001318 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001319#ifdef DEBUG_SAX
1320 if (prefix == NULL)
1321 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1322 else
1323 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1324#endif
1325 xmlNewNs(ctxt->node, href, prefix);
1326}
1327
1328/**
1329 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001330 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001331 * @value: the comment content
1332 *
1333 * A comment has been parsed.
1334 */
1335void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001336comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001337{
Daniel Veillard27d88741999-05-29 11:51:49 +00001338 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001339 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001340 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001341
Daniel Veillard517752b1999-04-05 12:20:10 +00001342#ifdef DEBUG_SAX
1343 fprintf(stderr, "SAX.comment(%s)\n", value);
1344#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001345 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001346 if (ret == NULL) return;
1347
Daniel Veillardcf461992000-03-14 18:30:20 +00001348 if (ctxt->inSubset == 1) {
1349 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1350 return;
1351 } else if (ctxt->inSubset == 2) {
1352 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1353 return;
1354 }
1355 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001356#ifdef DEBUG_SAX_TREE
1357 fprintf(stderr, "Setting comment as root\n");
1358#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001359 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1360 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001361 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001362 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001363#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001364 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001365#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001366 xmlAddChild(parent, ret);
1367 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001368#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001369 fprintf(stderr, "adding comment sibling to ");
1370 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001371#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001372 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001373 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001374}
1375
1376/**
1377 * cdataBlock:
1378 * @ctx: the user data (XML parser context)
1379 * @value: The pcdata content
1380 * @len: the block length
1381 *
1382 * called when a pcdata block has been parsed
1383 */
1384void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001385cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001386{
1387 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001388 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001389
1390#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001391 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001392#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001393 lastChild = xmlGetLastChild(ctxt->node);
1394#ifdef DEBUG_SAX_TREE
1395 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1396#endif
1397 if ((lastChild != NULL) &&
1398 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1399 xmlTextConcat(lastChild, value, len);
1400 } else {
1401 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1402 xmlAddChild(ctxt->node, ret);
1403 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001404}
1405
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001406/*
1407 * Default handler for XML, builds the DOM tree
1408 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001409xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001410 internalSubset,
1411 isStandalone,
1412 hasInternalSubset,
1413 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001414 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001415 getEntity,
1416 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001417 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001418 attributeDecl,
1419 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001420 unparsedEntityDecl,
1421 setDocumentLocator,
1422 startDocument,
1423 endDocument,
1424 startElement,
1425 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001426 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001427 characters,
1428 ignorableWhitespace,
1429 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001430 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001431 xmlParserWarning,
1432 xmlParserError,
1433 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001434 getParameterEntity,
1435 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001436 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001437};
1438
Daniel Veillard97b58771998-10-20 06:14:16 +00001439/**
1440 * xmlDefaultSAXHandlerInit:
1441 *
1442 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001443 */
1444void
1445xmlDefaultSAXHandlerInit(void)
1446{
Daniel Veillard517752b1999-04-05 12:20:10 +00001447 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001448 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001449 xmlDefaultSAXHandler.isStandalone = isStandalone;
1450 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1451 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001452 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001453 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001454 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001455 xmlDefaultSAXHandler.entityDecl = entityDecl;
1456 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1457 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001458 xmlDefaultSAXHandler.notationDecl = notationDecl;
1459 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1460 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1461 xmlDefaultSAXHandler.startDocument = startDocument;
1462 xmlDefaultSAXHandler.endDocument = endDocument;
1463 xmlDefaultSAXHandler.startElement = startElement;
1464 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001465 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001466 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001467 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001468 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1469 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001470 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001471 if (xmlGetWarningsDefaultValue == 0)
1472 xmlDefaultSAXHandler.warning = NULL;
1473 else
1474 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001475 xmlDefaultSAXHandler.error = xmlParserError;
1476 xmlDefaultSAXHandler.fatalError = xmlParserError;
1477}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001478
1479/*
1480 * Default handler for HTML, builds the DOM tree
1481 */
1482xmlSAXHandler htmlDefaultSAXHandler = {
1483 NULL,
1484 NULL,
1485 NULL,
1486 NULL,
1487 NULL,
1488 getEntity,
1489 NULL,
1490 NULL,
1491 NULL,
1492 NULL,
1493 NULL,
1494 setDocumentLocator,
1495 startDocument,
1496 endDocument,
1497 startElement,
1498 endElement,
1499 NULL,
1500 characters,
1501 ignorableWhitespace,
1502 NULL,
1503 comment,
1504 xmlParserWarning,
1505 xmlParserError,
1506 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001507 getParameterEntity,
1508 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001509 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001510};
1511
1512/**
1513 * htmlDefaultSAXHandlerInit:
1514 *
1515 * Initialize the default SAX handler
1516 */
1517void
1518htmlDefaultSAXHandlerInit(void)
1519{
1520 htmlDefaultSAXHandler.internalSubset = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00001521 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001522 htmlDefaultSAXHandler.isStandalone = NULL;
1523 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1524 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1525 htmlDefaultSAXHandler.resolveEntity = NULL;
1526 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001527 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001528 htmlDefaultSAXHandler.entityDecl = NULL;
1529 htmlDefaultSAXHandler.attributeDecl = NULL;
1530 htmlDefaultSAXHandler.elementDecl = NULL;
1531 htmlDefaultSAXHandler.notationDecl = NULL;
1532 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1533 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1534 htmlDefaultSAXHandler.startDocument = startDocument;
1535 htmlDefaultSAXHandler.endDocument = endDocument;
1536 htmlDefaultSAXHandler.startElement = startElement;
1537 htmlDefaultSAXHandler.endElement = endElement;
1538 htmlDefaultSAXHandler.reference = NULL;
1539 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001540 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001541 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1542 htmlDefaultSAXHandler.processingInstruction = NULL;
1543 htmlDefaultSAXHandler.comment = comment;
1544 htmlDefaultSAXHandler.warning = xmlParserWarning;
1545 htmlDefaultSAXHandler.error = xmlParserError;
1546 htmlDefaultSAXHandler.fatalError = xmlParserError;
1547}