blob: 7fa94d646c89d56a5134dd44c0a45905231e8fdf [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 Veillard32bc74e2000-07-14 14:49:25 +000017#include <string.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000018#include <libxml/xmlmemory.h>
19#include <libxml/tree.h>
20#include <libxml/parser.h>
21#include <libxml/parserInternals.h>
22#include <libxml/valid.h>
23#include <libxml/entities.h>
Daniel Veillardb71379b2000-10-09 12:30:39 +000024#include <libxml/xmlerror.h>
Daniel Veillard361d8452000-04-03 19:48:13 +000025#include <libxml/debugXML.h>
26#include <libxml/xmlIO.h>
27#include <libxml/SAX.h>
Daniel Veillardbe803962000-06-28 23:40:59 +000028#include <libxml/uri.h>
Daniel Veillardd83eb822000-06-30 18:39:56 +000029#include <libxml/HTMLtree.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000030
31/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000032/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000033
Daniel Veillard97b58771998-10-20 06:14:16 +000034/**
35 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000036 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000037 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000038 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000039 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000040 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000041 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000042const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000043getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000044{
Daniel Veillard27d88741999-05-29 11:51:49 +000045 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000046 return(NULL);
47}
48
Daniel Veillard97b58771998-10-20 06:14:16 +000049/**
50 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000051 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000052 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000053 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000054 * http://www.sgmlsource.com/dtds/memo.dtd
55 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +000056 * Returns a xmlChar *
Daniel Veillard260a68f1998-08-13 03:39:55 +000057 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +000058const xmlChar *
Daniel Veillard27d88741999-05-29 11:51:49 +000059getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000060{
Daniel Veillard27d88741999-05-29 11:51:49 +000061 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000062 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000063}
64
Daniel Veillard97b58771998-10-20 06:14:16 +000065/**
66 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000067 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000068 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000070 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000071 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000072 */
Daniel Veillard97b58771998-10-20 06:14:16 +000073int
Daniel Veillard27d88741999-05-29 11:51:49 +000074getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000075{
Daniel Veillard27d88741999-05-29 11:51:49 +000076 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000077 return(ctxt->input->line);
78}
Daniel Veillard97b58771998-10-20 06:14:16 +000079
80/**
81 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000082 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000083 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000084 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000085 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000086 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000087 */
Daniel Veillard97b58771998-10-20 06:14:16 +000088int
Daniel Veillard27d88741999-05-29 11:51:49 +000089getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000090{
Daniel Veillard27d88741999-05-29 11:51:49 +000091 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000092 return(ctxt->input->col);
93}
94
95/*
96 * The default SAX Locator.
97 */
98
99xmlSAXLocator xmlDefaultSAXLocator = {
100 getPublicId, getSystemId, getLineNumber, getColumnNumber
101};
102
Daniel Veillard97b58771998-10-20 06:14:16 +0000103/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000104 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000105 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000106 *
107 * Is this document tagged standalone ?
108 *
109 * Returns 1 if true
110 */
111int
Daniel Veillard27d88741999-05-29 11:51:49 +0000112isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000113{
Daniel Veillard27d88741999-05-29 11:51:49 +0000114 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000115 return(ctxt->myDoc->standalone == 1);
116}
117
118/**
119 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000120 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000121 *
122 * Does this document has an internal subset
123 *
124 * Returns 1 if true
125 */
126int
Daniel Veillard27d88741999-05-29 11:51:49 +0000127hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000128{
Daniel Veillard27d88741999-05-29 11:51:49 +0000129 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000130 return(ctxt->myDoc->intSubset != NULL);
131}
132
133/**
134 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000135 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000136 *
137 * Does this document has an external subset
138 *
139 * Returns 1 if true
140 */
141int
Daniel Veillard27d88741999-05-29 11:51:49 +0000142hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000143{
Daniel Veillard27d88741999-05-29 11:51:49 +0000144 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000145 return(ctxt->myDoc->extSubset != NULL);
146}
147
148/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000149 * internalSubset:
Daniel Veillard06047432000-04-24 11:33:38 +0000150 * @ctx: the user data (XML parser context)
151 * @name: the root element name
152 * @ExternalID: the external ID
153 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000154 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000155 * Callback on internal subset declaration.
Daniel Veillard517752b1999-04-05 12:20:10 +0000156 */
157void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000158internalSubset(void *ctx, const xmlChar *name,
159 const xmlChar *ExternalID, const xmlChar *SystemID)
Daniel Veillard517752b1999-04-05 12:20:10 +0000160{
Daniel Veillard27d88741999-05-29 11:51:49 +0000161 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardd83eb822000-06-30 18:39:56 +0000162 xmlDtdPtr dtd;
Daniel Veillard517752b1999-04-05 12:20:10 +0000163#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000164 xmlGenericError(xmlGenericErrorContext,
165 "SAX.internalSubset(%s, %s, %s)\n",
Daniel Veillard517752b1999-04-05 12:20:10 +0000166 name, ExternalID, SystemID);
167#endif
Daniel Veillardd83eb822000-06-30 18:39:56 +0000168
169 if (ctxt->myDoc == NULL)
170 return;
171 dtd = xmlGetIntSubset(ctxt->myDoc);
172 if (dtd != NULL) {
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000173 if (ctxt->html)
174 return;
Daniel Veillardd83eb822000-06-30 18:39:56 +0000175 xmlUnlinkNode((xmlNodePtr) dtd);
176 xmlFreeDtd(dtd);
177 ctxt->myDoc->intSubset = NULL;
178 }
179 ctxt->myDoc->intSubset =
180 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000181}
182
183/**
184 * externalSubset:
185 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000186 * @name: the root element name
187 * @ExternalID: the external ID
188 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000189 *
190 * Callback on external subset declaration.
191 */
192void
193externalSubset(void *ctx, const xmlChar *name,
194 const xmlChar *ExternalID, const xmlChar *SystemID)
195{
196 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
197#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000198 xmlGenericError(xmlGenericErrorContext,
199 "SAX.externalSubset(%s, %s, %s)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000200 name, ExternalID, SystemID);
201#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000202 if (((ExternalID != NULL) || (SystemID != NULL)) &&
Daniel Veillard0f2a53c2001-02-05 17:57:33 +0000203 (((ctxt->validate) || (ctxt->loadsubset)) &&
204 (ctxt->wellFormed && ctxt->myDoc))) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000205 /*
206 * Try to fetch and parse the external subset.
207 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000208 xmlParserInputPtr oldinput;
209 int oldinputNr;
210 int oldinputMax;
211 xmlParserInputPtr *oldinputTab;
212 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000213 xmlParserInputPtr input = NULL;
214 xmlCharEncoding enc;
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000215 int oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000216
Daniel Veillardb05deb71999-08-10 19:04:08 +0000217 /*
218 * Ask the Entity resolver to load the damn thing
219 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000220 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
221 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000222 SystemID);
223 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000224 return;
225 }
226
Daniel Veillardcf461992000-03-14 18:30:20 +0000227 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
228
Daniel Veillardb05deb71999-08-10 19:04:08 +0000229 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000230 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000231 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000232 oldinput = ctxt->input;
233 oldinputNr = ctxt->inputNr;
234 oldinputMax = ctxt->inputMax;
235 oldinputTab = ctxt->inputTab;
236 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000237 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000238
239 ctxt->inputTab = (xmlParserInputPtr *)
240 xmlMalloc(5 * sizeof(xmlParserInputPtr));
241 if (ctxt->inputTab == NULL) {
242 ctxt->errNo = XML_ERR_NO_MEMORY;
243 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
244 ctxt->sax->error(ctxt->userData,
245 "externalSubset: out of memory\n");
246 ctxt->errNo = XML_ERR_NO_MEMORY;
247 ctxt->input = oldinput;
248 ctxt->inputNr = oldinputNr;
249 ctxt->inputMax = oldinputMax;
250 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000251 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000252 return;
253 }
254 ctxt->inputNr = 0;
255 ctxt->inputMax = 5;
256 ctxt->input = NULL;
257 xmlPushInput(ctxt, input);
258
259 /*
260 * On the fly encoding conversion if needed
261 */
262 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
263 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000264
265 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000266 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000267 input->line = 1;
268 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000269 input->base = ctxt->input->cur;
270 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000271 input->free = NULL;
272
273 /*
274 * let's parse that entity knowing it's an external subset.
275 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000276 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000277
Daniel Veillardcf461992000-03-14 18:30:20 +0000278 /*
279 * Free up the external entities
280 */
281
282 while (ctxt->inputNr > 1)
283 xmlPopInput(ctxt);
284 xmlFreeInputStream(ctxt->input);
285 xmlFree(ctxt->inputTab);
286
287 /*
288 * Restore the parsing context of the main entity
289 */
290 ctxt->input = oldinput;
291 ctxt->inputNr = oldinputNr;
292 ctxt->inputMax = oldinputMax;
293 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000294 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000295 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000296 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000297}
298
299/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000300 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000301 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000302 * @publicId: The public ID of the entity
303 * @systemId: The system ID of the entity
304 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000305 * The entity loader, to control the loading of external entities,
306 * the application can either:
307 * - override this resolveEntity() callback in the SAX block
308 * - or better use the xmlSetExternalEntityLoader() function to
309 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000310 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000311 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000312 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000313xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000314resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000315{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000316 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard39c7d712000-09-10 16:14:55 +0000317 xmlParserInputPtr ret;
Daniel Veillard04698d92000-09-17 16:00:22 +0000318 xmlChar *URI;
Daniel Veillard39c7d712000-09-10 16:14:55 +0000319 const char *base = NULL;
320
321 if (ctxt->input != NULL)
322 base = ctxt->input->filename;
323 if (base == NULL)
324 base = ctxt->directory;
325
Daniel Veillard04698d92000-09-17 16:00:22 +0000326 URI = xmlBuildURI(systemId, (const xmlChar *) base);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000327
328#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000329 xmlGenericError(xmlGenericErrorContext,
330 "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000331#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000332
Daniel Veillard39c7d712000-09-10 16:14:55 +0000333 ret = xmlLoadExternalEntity((const char *) URI,
334 (const char *) publicId, ctxt);
335 if (URI != NULL)
336 xmlFree(URI);
337 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000338}
339
Daniel Veillard97b58771998-10-20 06:14:16 +0000340/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000341 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000342 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000343 * @name: The entity name
344 *
345 * Get an entity by name
346 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000347 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000348 */
349xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000350getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000351{
Daniel Veillard27d88741999-05-29 11:51:49 +0000352 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000353 xmlEntityPtr ret;
354
355#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000356 xmlGenericError(xmlGenericErrorContext,
357 "SAX.getEntity(%s)\n", name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000358#endif
359
360 ret = xmlGetDocEntity(ctxt->myDoc, name);
Daniel Veillard87b95392000-08-12 21:12:04 +0000361 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
362 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
363 /*
364 * for validation purposes we really need to fetch and
365 * parse the external entity
366 */
367 int parse;
368 xmlNodePtr children;
369
370 parse = xmlParseCtxtExternalEntity(ctxt,
371 ret->SystemID, ret->ExternalID, &children);
372 xmlAddChildList((xmlNodePtr) ret, children);
373 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000374 return(ret);
375}
376
Daniel Veillardb05deb71999-08-10 19:04:08 +0000377/**
378 * getParameterEntity:
379 * @ctx: the user data (XML parser context)
380 * @name: The entity name
381 *
382 * Get a parameter entity by name
383 *
384 * Returns the xmlEntityPtr if found.
385 */
386xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000387getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000388{
389 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
390 xmlEntityPtr ret;
391
392#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000393 xmlGenericError(xmlGenericErrorContext,
394 "SAX.getParameterEntity(%s)\n", name);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000395#endif
396
397 ret = xmlGetParameterEntity(ctxt->myDoc, name);
398 return(ret);
399}
400
Daniel Veillard517752b1999-04-05 12:20:10 +0000401
402/**
403 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000404 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000405 * @name: the entity name
406 * @type: the entity type
407 * @publicId: The public ID of the entity
408 * @systemId: The system ID of the entity
409 * @content: the entity value (without processing).
410 *
411 * An entity definition has been parsed
412 */
413void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000414entityDecl(void *ctx, const xmlChar *name, int type,
415 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000416{
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000417 xmlEntityPtr ent;
Daniel Veillard27d88741999-05-29 11:51:49 +0000418 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000419
420#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000421 xmlGenericError(xmlGenericErrorContext,
422 "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
Daniel Veillard517752b1999-04-05 12:20:10 +0000423 name, type, publicId, systemId, content);
424#endif
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000425 if (ctxt->inSubset == 1) {
426 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
Daniel Veillardcf461992000-03-14 18:30:20 +0000427 systemId, content);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000428 if ((ent == NULL) && (ctxt->pedantic) &&
429 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
430 ctxt->sax->warning(ctxt,
431 "Entity(%s) already defined in the internal subset\n", name);
Daniel Veillard39c7d712000-09-10 16:14:55 +0000432 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
Daniel Veillard04698d92000-09-17 16:00:22 +0000433 xmlChar *URI;
Daniel Veillard39c7d712000-09-10 16:14:55 +0000434 const char *base = NULL;
435
436 if (ctxt->input != NULL)
437 base = ctxt->input->filename;
438 if (base == NULL)
439 base = ctxt->directory;
440
Daniel Veillard04698d92000-09-17 16:00:22 +0000441 URI = xmlBuildURI(systemId, (const xmlChar *) base);
Daniel Veillard39c7d712000-09-10 16:14:55 +0000442 ent->URI = URI;
443 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000444 } else if (ctxt->inSubset == 2) {
445 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
Daniel Veillardcf461992000-03-14 18:30:20 +0000446 systemId, content);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000447 if ((ent == NULL) && (ctxt->pedantic) &&
448 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
449 ctxt->sax->warning(ctxt,
450 "Entity(%s) already defined in the external subset\n", name);
Daniel Veillard39c7d712000-09-10 16:14:55 +0000451 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
Daniel Veillard04698d92000-09-17 16:00:22 +0000452 xmlChar *URI;
Daniel Veillard39c7d712000-09-10 16:14:55 +0000453 const char *base = NULL;
454
455 if (ctxt->input != NULL)
456 base = ctxt->input->filename;
457 if (base == NULL)
458 base = ctxt->directory;
459
Daniel Veillard04698d92000-09-17 16:00:22 +0000460 URI = xmlBuildURI(systemId, (const xmlChar *) base);
Daniel Veillard39c7d712000-09-10 16:14:55 +0000461 ent->URI = URI;
462 }
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000463 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +0000464 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
465 ctxt->sax->error(ctxt,
466 "SAX.entityDecl(%s) called while not in subset\n", name);
467 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000468}
469
470/**
471 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000472 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000473 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000474 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000475 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000476 * @def: the type of default value
477 * @defaultValue: the attribute default value
478 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000479 *
480 * An attribute definition has been parsed
481 */
482void
Daniel Veillardcf461992000-03-14 18:30:20 +0000483attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000484 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000485 xmlEnumerationPtr tree)
486{
Daniel Veillard27d88741999-05-29 11:51:49 +0000487 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000488 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000489 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000490
491#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000492 xmlGenericError(xmlGenericErrorContext,
493 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000494 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000495#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000496 name = xmlSplitQName(ctxt, fullname, &prefix);
497 if (ctxt->inSubset == 1)
498 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000499 name, prefix, (xmlAttributeType) type,
500 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000501 else if (ctxt->inSubset == 2)
502 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000503 name, prefix, (xmlAttributeType) type,
504 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000505 else {
506 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
507 ctxt->sax->error(ctxt,
508 "SAX.attributeDecl(%s) called while not in subset\n", name);
509 return;
510 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000511 if (attr == 0) ctxt->valid = 0;
512 if (ctxt->validate && ctxt->wellFormed &&
513 ctxt->myDoc && ctxt->myDoc->intSubset)
514 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
515 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000516 if (prefix != NULL)
517 xmlFree(prefix);
518 if (name != NULL)
519 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000520}
521
522/**
523 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000524 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000525 * @name: the element name
526 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000527 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000528 *
529 * An element definition has been parsed
530 */
531void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000532elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000533 xmlElementContentPtr content)
534{
Daniel Veillard27d88741999-05-29 11:51:49 +0000535 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000536 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000537
538#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000539 xmlGenericError(xmlGenericErrorContext,
540 "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000541 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000542#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000543
Daniel Veillardcf461992000-03-14 18:30:20 +0000544 if (ctxt->inSubset == 1)
545 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000546 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000547 else if (ctxt->inSubset == 2)
548 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000549 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000550 else {
551 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
552 ctxt->sax->error(ctxt,
553 "SAX.elementDecl(%s) called while not in subset\n", name);
554 return;
555 }
556 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000557 if (ctxt->validate && ctxt->wellFormed &&
558 ctxt->myDoc && ctxt->myDoc->intSubset)
559 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000560}
561
562/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000563 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000564 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000565 * @name: The name of the notation
566 * @publicId: The public ID of the entity
567 * @systemId: The system ID of the entity
568 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000569 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000570 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000571void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000572notationDecl(void *ctx, const xmlChar *name,
573 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000574{
Daniel Veillard27d88741999-05-29 11:51:49 +0000575 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000576 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000577
Daniel Veillard260a68f1998-08-13 03:39:55 +0000578#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000579 xmlGenericError(xmlGenericErrorContext,
580 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000581#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000582
Daniel Veillardcf461992000-03-14 18:30:20 +0000583 if (ctxt->inSubset == 1)
584 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000585 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000586 else if (ctxt->inSubset == 2)
587 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
588 publicId, systemId);
589 else {
590 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
591 ctxt->sax->error(ctxt,
592 "SAX.notationDecl(%s) called while not in subset\n", name);
593 return;
594 }
595 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000596 if (ctxt->validate && ctxt->wellFormed &&
597 ctxt->myDoc && ctxt->myDoc->intSubset)
598 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
599 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000600}
601
Daniel Veillard97b58771998-10-20 06:14:16 +0000602/**
603 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000604 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000605 * @name: The name of the entity
606 * @publicId: The public ID of the entity
607 * @systemId: The system ID of the entity
608 * @notationName: the name of the notation
609 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000610 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000611 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000612void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000613unparsedEntityDecl(void *ctx, const xmlChar *name,
614 const xmlChar *publicId, const xmlChar *systemId,
615 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000616{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000617 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000618#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000619 xmlGenericError(xmlGenericErrorContext,
620 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
Daniel Veillard260a68f1998-08-13 03:39:55 +0000621 name, publicId, systemId, notationName);
622#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000623 if (ctxt->validate && ctxt->wellFormed &&
624 ctxt->myDoc && ctxt->myDoc->intSubset)
625 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
626 notationName);
627 xmlAddDocEntity(ctxt->myDoc, name,
628 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
629 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000630}
631
Daniel Veillard97b58771998-10-20 06:14:16 +0000632/**
633 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000634 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000635 * @loc: A SAX Locator
636 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000637 * Receive the document locator at startup, actually xmlDefaultSAXLocator
638 * Everything is available on the context, so this is useless in our case.
639 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000640void
Daniel Veillard27d88741999-05-29 11:51:49 +0000641setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000642{
Daniel Veillard27d88741999-05-29 11:51:49 +0000643 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000644#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000645 xmlGenericError(xmlGenericErrorContext,
646 "SAX.setDocumentLocator()\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000647#endif
648}
649
Daniel Veillard97b58771998-10-20 06:14:16 +0000650/**
651 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000652 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000653 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000654 * called when the document start being processed.
655 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000656void
Daniel Veillard27d88741999-05-29 11:51:49 +0000657startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000658{
Daniel Veillard27d88741999-05-29 11:51:49 +0000659 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000660 xmlDocPtr doc;
661
Daniel Veillard260a68f1998-08-13 03:39:55 +0000662#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000663 xmlGenericError(xmlGenericErrorContext,
664 "SAX.startDocument()\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000665#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000666 if (ctxt->html) {
667 if (ctxt->myDoc == NULL)
Daniel Veillard87b95392000-08-12 21:12:04 +0000668#ifdef LIBXML_HTML_ENABLED
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000669 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
Daniel Veillard87b95392000-08-12 21:12:04 +0000670#else
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000671 xmlGenericError(xmlGenericErrorContext,
672 "libxml2 built without HTML support\n");
Daniel Veillard87b95392000-08-12 21:12:04 +0000673#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000674 } else {
675 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
676 if (doc != NULL) {
677 if (ctxt->encoding != NULL)
678 doc->encoding = xmlStrdup(ctxt->encoding);
679 else
680 doc->encoding = NULL;
681 doc->standalone = ctxt->standalone;
682 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000683 }
Daniel Veillard87b95392000-08-12 21:12:04 +0000684 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
685 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
686 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename);
687 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000688}
689
Daniel Veillard97b58771998-10-20 06:14:16 +0000690/**
691 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000692 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000693 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000694 * called when the document end has been detected.
695 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000696void
Daniel Veillard27d88741999-05-29 11:51:49 +0000697endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000698{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000699 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000700#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000701 xmlGenericError(xmlGenericErrorContext,
702 "SAX.endDocument()\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000703#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000704 if (ctxt->validate && ctxt->wellFormed &&
705 ctxt->myDoc && ctxt->myDoc->intSubset)
706 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000707
708 /*
709 * Grab the encoding if it was added on-the-fly
710 */
711 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
712 (ctxt->myDoc->encoding == NULL)) {
713 ctxt->myDoc->encoding = ctxt->encoding;
714 ctxt->encoding = NULL;
715 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000716 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
717 (ctxt->myDoc->encoding == NULL)) {
718 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
719 }
720 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
721 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
722 ctxt->myDoc->charset = ctxt->charset;
723 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000724}
725
Daniel Veillard97b58771998-10-20 06:14:16 +0000726/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000727 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000728 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000729 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000730 * @value: The attribute value
731 *
732 * Handle an attribute that has been read by the parser.
733 * The default handling is to convert the attribute into an
734 * DOM subtree and past it in a new xmlAttr element added to
735 * the element.
736 */
737void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000738attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000739{
Daniel Veillard27d88741999-05-29 11:51:49 +0000740 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000741 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000742 xmlChar *name;
743 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000744 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000745 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000746
747/****************
748#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000749 xmlGenericError(xmlGenericErrorContext,
750 "SAX.attribute(%s, %s)\n", fullname, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000751#endif
752 ****************/
753 /*
754 * Split the full name into a namespace prefix and the tag name
755 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000756 name = xmlSplitQName(ctxt, fullname, &ns);
757
758 /*
Daniel Veillard47e12f22000-10-15 14:24:25 +0000759 * Do the last stage of the attribute normalization
760 * Needed for HTML too:
761 * http://www.w3.org/TR/html4/types.html#h-6.2
Daniel Veillardcf461992000-03-14 18:30:20 +0000762 */
Daniel Veillard47e12f22000-10-15 14:24:25 +0000763 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
764 fullname, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000765 if (nval != NULL)
766 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000767
768 /*
769 * Check whether it's a namespace definition
770 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000771 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000772 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
773 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000774 xmlURIPtr uri;
775
776 uri = xmlParseURI((const char *)value);
777 if (uri == NULL) {
778 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
779 ctxt->sax->warning(ctxt->userData,
780 "nmlns: %s not a valid URI\n", value);
781 } else {
782 if (uri->scheme == NULL) {
783 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
784 ctxt->sax->warning(ctxt->userData,
785 "nmlns: URI %s is not absolute\n", value);
786 }
787 xmlFreeURI(uri);
788 }
789
Daniel Veillard517752b1999-04-05 12:20:10 +0000790 /* a default namespace definition */
791 xmlNewNs(ctxt->node, value, NULL);
792 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000793 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000794 if (nval != NULL)
795 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000796 return;
797 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000798 if ((!ctxt->html) &&
799 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000800 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000801 /*
802 * Validate also for namespace decls, they are attributes from
803 * an XML-1.0 perspective
804 TODO ... doesn't map well with current API
805 if (ctxt->validate && ctxt->wellFormed &&
806 ctxt->myDoc && ctxt->myDoc->intSubset)
807 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
808 ctxt->node, ret, value);
809 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000810 /* a standard namespace definition */
811 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000812 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000813 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000814 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000815 if (nval != NULL)
816 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000817 return;
818 }
819
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000820 if (ns != NULL)
821 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
822 else {
823 namespace = NULL;
824 }
825
Daniel Veillardb96e6431999-08-29 21:02:19 +0000826 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
827 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000828
Daniel Veillardb96e6431999-08-29 21:02:19 +0000829 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000830 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
831 xmlNodePtr tmp;
832
833 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
834 tmp = ret->children;
835 while (tmp != NULL) {
836 tmp->parent = (xmlNodePtr) ret;
837 if (tmp->next == NULL)
838 ret->last = tmp;
839 tmp = tmp->next;
840 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000841 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000842 ret->children = xmlNewDocText(ctxt->myDoc, value);
843 ret->last = ret->children;
844 if (ret->children != NULL)
845 ret->children->parent = (xmlNodePtr) ret;
846 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000847 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000848
Daniel Veillardbe803962000-06-28 23:40:59 +0000849 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000850 ctxt->myDoc && ctxt->myDoc->intSubset) {
851
852 /*
853 * If we don't substitute entities, the validation should be
854 * done on a value with replaced entities anyway.
855 */
856 if (!ctxt->replaceEntities) {
857 xmlChar *val;
858
859 ctxt->depth++;
860 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
861 0,0,0);
862 ctxt->depth--;
863 if (val == NULL)
864 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
865 ctxt->myDoc, ctxt->node, ret, value);
866 else {
867 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
868 ctxt->myDoc, ctxt->node, ret, val);
869 xmlFree(val);
870 }
871 } else {
872 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000873 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000874 }
875 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000876 /*
877 * when validating, the ID registration is done at the attribute
878 * validation level. Otherwise we have to do specific handling here.
879 */
880 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
881 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000882 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
883 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000884 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000885
Daniel Veillardcf461992000-03-14 18:30:20 +0000886 if (nval != NULL)
887 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000888 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000889 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000890 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000891 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000892}
893
894/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000895 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000896 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000897 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000898 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000899 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000900 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000901 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000902void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000903startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000904{
Daniel Veillard27d88741999-05-29 11:51:49 +0000905 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000906 xmlNodePtr ret;
907 xmlNodePtr parent = ctxt->node;
908 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000909 xmlChar *name;
910 xmlChar *prefix;
911 const xmlChar *att;
912 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000913 int i;
914
Daniel Veillard260a68f1998-08-13 03:39:55 +0000915#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000916 xmlGenericError(xmlGenericErrorContext,
917 "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000918#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000919
920 /*
921 * First check on validity:
922 */
923 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
924 ((ctxt->myDoc->intSubset == NULL) ||
925 ((ctxt->myDoc->intSubset->notations == NULL) &&
926 (ctxt->myDoc->intSubset->elements == NULL) &&
927 (ctxt->myDoc->intSubset->attributes == NULL) &&
928 (ctxt->myDoc->intSubset->entities == NULL)))) {
929 if (ctxt->vctxt.error != NULL) {
930 ctxt->vctxt.error(ctxt->vctxt.userData,
931 "Validation failed: no DTD found !\n");
932 }
933 ctxt->validate = 0;
934 }
935
936
Daniel Veillard517752b1999-04-05 12:20:10 +0000937 /*
938 * Split the full name into a namespace prefix and the tag name
939 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000940 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000941
942
943 /*
944 * Note : the namespace resolution is deferred until the end of the
945 * attributes parsing, since local namespace can be defined as
946 * an attribute at this level.
947 */
948 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
949 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000950 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000951#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000952 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000953#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000954 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000955 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000956 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000957 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000958 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000959
960 /*
961 * We are parsing a new node.
962 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000963#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000964 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000965#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000966 nodePush(ctxt, ret);
967
968 /*
969 * Link the child element
970 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000971 if (parent != NULL) {
972 if (parent->type == XML_ELEMENT_NODE) {
973#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000974 xmlGenericError(xmlGenericErrorContext,
975 "adding child %s to %s\n", name, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000976#endif
977 xmlAddChild(parent, ret);
978 } else {
979#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +0000980 xmlGenericError(xmlGenericErrorContext,
981 "adding sibling %s to ", name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000982 xmlDebugDumpOneNode(stderr, parent, 0);
983#endif
984 xmlAddSibling(parent, ret);
985 }
986 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000987
988 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000989 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000990 */
991 if (atts != NULL) {
992 i = 0;
993 att = atts[i++];
994 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000995 if (!ctxt->html) {
996 while ((att != NULL) && (value != NULL)) {
997 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
998 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000999
Daniel Veillardbe803962000-06-28 23:40:59 +00001000 att = atts[i++];
1001 value = atts[i++];
1002 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001003 }
1004 }
1005
1006 /*
1007 * Search the namespace, note that since the attributes have been
1008 * processed, the local namespaces are available.
1009 */
1010 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1011 if ((ns == NULL) && (parent != NULL))
1012 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
Daniel Veillarde0854c32000-08-27 21:12:29 +00001013 if ((prefix != NULL) && (ns == NULL)) {
1014 ns = xmlNewNs(ret, NULL, prefix);
1015 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1016 ctxt->sax->warning(ctxt->userData,
1017 "Namespace prefix %s is not defined\n", prefix);
1018 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001019 xmlSetNs(ret, ns);
1020
Daniel Veillardbe803962000-06-28 23:40:59 +00001021 /*
1022 * process all the other attributes
1023 */
1024 if (atts != NULL) {
1025 i = 0;
1026 att = atts[i++];
1027 value = atts[i++];
1028 if (ctxt->html) {
1029 while (att != NULL) {
1030 attribute(ctxt, att, value);
1031 att = atts[i++];
1032 value = atts[i++];
1033 }
1034 } else {
1035 while ((att != NULL) && (value != NULL)) {
1036 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1037 attribute(ctxt, att, value);
1038
1039 /*
1040 * Next ones
1041 */
1042 att = atts[i++];
1043 value = atts[i++];
1044 }
1045 }
1046 }
1047
1048 /*
1049 * If it's the Document root, finish the Dtd validation and
1050 * check the document root element for validity
1051 */
1052 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1053 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1054 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1055 ctxt->vctxt.finishDtd = 1;
1056 }
1057
Daniel Veillard517752b1999-04-05 12:20:10 +00001058 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001059 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +00001060 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001061 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +00001062
Daniel Veillard260a68f1998-08-13 03:39:55 +00001063}
1064
Daniel Veillard97b58771998-10-20 06:14:16 +00001065/**
1066 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001067 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001068 * @name: The element name
1069 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001070 * called when the end of an element has been detected.
1071 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001072void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001073endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +00001074{
Daniel Veillard27d88741999-05-29 11:51:49 +00001075 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001076 xmlParserNodeInfo node_info;
1077 xmlNodePtr cur = ctxt->node;
1078
Daniel Veillard260a68f1998-08-13 03:39:55 +00001079#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001080 if (name == NULL)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001081 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
Daniel Veillard517752b1999-04-05 12:20:10 +00001082 else
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001083 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001084#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001085
1086 /* Capture end position and add node */
1087 if (cur != NULL && ctxt->record_info) {
1088 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1089 node_info.end_line = ctxt->input->line;
1090 node_info.node = cur;
1091 xmlParserAddNodeInfo(ctxt, &node_info);
1092 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001093 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +00001094
Daniel Veillardb05deb71999-08-10 19:04:08 +00001095 if (ctxt->validate && ctxt->wellFormed &&
1096 ctxt->myDoc && ctxt->myDoc->intSubset)
1097 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1098 cur);
1099
1100
Daniel Veillard517752b1999-04-05 12:20:10 +00001101 /*
1102 * end of parsing of this node.
1103 */
Daniel Veillardb96e6431999-08-29 21:02:19 +00001104#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001105 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001106#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001107 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001108}
1109
Daniel Veillard97b58771998-10-20 06:14:16 +00001110/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001111 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001112 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001113 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001114 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001115 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001116 */
1117void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001118reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001119{
Daniel Veillard27d88741999-05-29 11:51:49 +00001120 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001121 xmlNodePtr ret;
1122
Daniel Veillard11e00581998-10-24 18:27:49 +00001123#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001124 xmlGenericError(xmlGenericErrorContext,
1125 "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001126#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001127 if (name[0] == '#')
1128 ret = xmlNewCharRef(ctxt->myDoc, name);
1129 else
1130 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001131#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001132 xmlGenericError(xmlGenericErrorContext,
1133 "add reference %s to %s \n", name, ctxt->node->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001134#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001135 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001136}
1137
1138/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001139 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001140 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001141 * @ch: a xmlChar string
1142 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001143 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001144 * receiving some chars from the parser.
1145 * Question: how much at a time ???
1146 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001147void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001148characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001149{
Daniel Veillard27d88741999-05-29 11:51:49 +00001150 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001151 xmlNodePtr lastChild;
1152
1153#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001154 xmlGenericError(xmlGenericErrorContext,
1155 "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001156#endif
1157 /*
1158 * Handle the data if any. If there is no child
1159 * add it as content, otherwise if the last child is text,
1160 * concatenate it, else create a new node of type text.
1161 */
1162
Daniel Veillard35008381999-10-25 13:15:52 +00001163 if (ctxt->node == NULL) {
1164#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001165 xmlGenericError(xmlGenericErrorContext,
1166 "add chars: ctxt->node == NULL !\n");
Daniel Veillard35008381999-10-25 13:15:52 +00001167#endif
1168 return;
1169 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001170 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001171#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001172 xmlGenericError(xmlGenericErrorContext,
1173 "add chars to %s \n", ctxt->node->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001174#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001175
1176 /*
1177 * Here we needed an accelerator mechanism in case of very large
1178 * elements. Use an attribute in the structure !!!
1179 */
1180 if (lastChild == NULL) {
1181 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001182 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001183#ifndef XML_USE_BUFFER_CONTENT
1184 if (ctxt->node->children != NULL) {
1185 ctxt->nodelen = len;
1186 ctxt->nodemem = len + 1;
1187 }
1188#endif
1189 } else {
Daniel Veillarde0854c32000-08-27 21:12:29 +00001190 if ((xmlNodeIsText(lastChild)) && (ctxt->nodemem != 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +00001191#ifndef XML_USE_BUFFER_CONTENT
1192 /*
1193 * The whole point of maintaining nodelen and nodemem,
1194 * xmlTextConcat is too costly, i.e. compute lenght,
1195 * reallocate a new buffer, move data, append ch. Here
1196 * We try to minimaze realloc() uses and avoid copying
1197 * and recomputing lenght over and over.
1198 */
1199 if (ctxt->nodelen + len >= ctxt->nodemem) {
1200 xmlChar *newbuf;
1201 int size;
1202
1203 size = ctxt->nodemem + len;
1204 size *= 2;
1205 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1206 if (newbuf == NULL) {
1207 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1208 ctxt->sax->error(ctxt->userData,
1209 "SAX.characters(): out of memory\n");
1210 return;
1211 }
1212 ctxt->nodemem = size;
1213 lastChild->content = newbuf;
1214 }
1215 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1216 ctxt->nodelen += len;
1217 lastChild->content[ctxt->nodelen] = 0;
1218#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001219 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001220#endif
1221 } else {
1222 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001223 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001224 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001225#ifndef XML_USE_BUFFER_CONTENT
1226 if (ctxt->node->children != NULL) {
1227 ctxt->nodelen = len;
1228 ctxt->nodemem = len + 1;
1229 }
1230#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001231 }
1232 }
1233}
1234
Daniel Veillard97b58771998-10-20 06:14:16 +00001235/**
1236 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001237 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001238 * @ch: a xmlChar string
1239 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001240 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001241 * receiving some ignorable whitespaces from the parser.
1242 * Question: how much at a time ???
1243 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001244void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001245ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001246{
Daniel Veillard27d88741999-05-29 11:51:49 +00001247 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001248#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001249 xmlGenericError(xmlGenericErrorContext,
1250 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001251#endif
1252}
1253
Daniel Veillard97b58771998-10-20 06:14:16 +00001254/**
1255 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001256 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001257 * @target: the target name
1258 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001259 *
1260 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001261 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001262void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001263processingInstruction(void *ctx, const xmlChar *target,
1264 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001265{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001266 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1267 xmlNodePtr ret;
1268 xmlNodePtr parent = ctxt->node;
1269
Daniel Veillard260a68f1998-08-13 03:39:55 +00001270#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001271 xmlGenericError(xmlGenericErrorContext,
1272 "SAX.processingInstruction(%s, %s)\n", target, data);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001273#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001274
1275 ret = xmlNewPI(target, data);
1276 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001277 parent = ctxt->node;
1278
1279 if (ctxt->inSubset == 1) {
1280 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1281 return;
1282 } else if (ctxt->inSubset == 2) {
1283 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1284 return;
1285 }
1286 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001287#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001288 xmlGenericError(xmlGenericErrorContext,
1289 "Setting PI %s as root\n", target);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001290#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001291 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1292 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001293 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001294 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001295#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001296 xmlGenericError(xmlGenericErrorContext,
1297 "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001298#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001299 xmlAddChild(parent, ret);
1300 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001301#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001302 xmlGenericError(xmlGenericErrorContext,
1303 "adding PI %s sibling to ", target);
Daniel Veillardcf461992000-03-14 18:30:20 +00001304 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001305#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001306 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001307 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001308}
1309
Daniel Veillard517752b1999-04-05 12:20:10 +00001310/**
1311 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001312 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001313 * @href: the namespace associated URN
1314 * @prefix: the namespace prefix
1315 *
1316 * An old global namespace has been parsed.
1317 */
1318void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001319globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001320{
Daniel Veillard27d88741999-05-29 11:51:49 +00001321 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001322#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001323 xmlGenericError(xmlGenericErrorContext,
1324 "SAX.globalNamespace(%s, %s)\n", href, prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +00001325#endif
1326 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1327}
1328
1329/**
1330 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001331 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001332 * @name: the namespace prefix
1333 *
1334 * Set the current element namespace.
1335 */
Daniel Veillard06047432000-04-24 11:33:38 +00001336
Daniel Veillard517752b1999-04-05 12:20:10 +00001337void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001338setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001339{
Daniel Veillard27d88741999-05-29 11:51:49 +00001340 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001341 xmlNsPtr ns;
1342 xmlNodePtr parent;
1343
1344#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001345 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
Daniel Veillard517752b1999-04-05 12:20:10 +00001346#endif
1347 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1348 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1349 if (ctxt->nodeNr >= 2) {
1350 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1351 if (parent != NULL)
1352 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1353 }
1354 }
1355 xmlSetNs(ctxt->node, ns);
1356}
1357
1358/**
1359 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001360 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001361 *
1362 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001363 *
1364 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001365 */
Daniel Veillard06047432000-04-24 11:33:38 +00001366
Daniel Veillard517752b1999-04-05 12:20:10 +00001367xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001368getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001369{
Daniel Veillard27d88741999-05-29 11:51:49 +00001370 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001371 xmlNsPtr ret;
1372
1373#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001374 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
Daniel Veillard517752b1999-04-05 12:20:10 +00001375#endif
1376 ret = ctxt->node->ns;
1377 return(ret);
1378}
1379
1380/**
1381 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001382 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001383 * @namespace: the namespace to check against
1384 *
1385 * Check that the current element namespace is the same as the
1386 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001387 *
1388 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001389 */
Daniel Veillard06047432000-04-24 11:33:38 +00001390
Daniel Veillard517752b1999-04-05 12:20:10 +00001391int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001392checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001393{
Daniel Veillard27d88741999-05-29 11:51:49 +00001394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001395 xmlNodePtr cur = ctxt->node;
1396
1397#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001398 xmlGenericError(xmlGenericErrorContext,
1399 "SAX.checkNamespace(%s)\n", namespace);
Daniel Veillard517752b1999-04-05 12:20:10 +00001400#endif
1401
1402 /*
1403 * Check that the Name in the ETag is the same as in the STag.
1404 */
1405 if (namespace == NULL) {
1406 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1407 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1408 ctxt->sax->error(ctxt,
1409 "End tags for %s don't hold the namespace %s\n",
1410 cur->name, cur->ns->prefix);
1411 ctxt->wellFormed = 0;
1412 }
1413 } else {
1414 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1415 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1416 ctxt->sax->error(ctxt,
1417 "End tags %s holds a prefix %s not used by the open tag\n",
1418 cur->name, namespace);
1419 ctxt->wellFormed = 0;
Daniel Veillard8b5dd832000-10-01 20:28:44 +00001420 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001421 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1422 ctxt->sax->error(ctxt,
1423 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1424 cur->name, cur->ns->prefix, namespace);
1425 ctxt->wellFormed = 0;
1426 } else
1427 return(1);
1428 }
1429 return(0);
1430}
1431
1432/**
1433 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001434 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001435 * @href: the namespace associated URN
1436 * @prefix: the namespace prefix
1437 *
1438 * A namespace has been parsed.
1439 */
1440void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001441namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001442{
Daniel Veillard27d88741999-05-29 11:51:49 +00001443 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001444#ifdef DEBUG_SAX
1445 if (prefix == NULL)
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001446 xmlGenericError(xmlGenericErrorContext,
1447 "SAX.namespaceDecl(%s, NULL)\n", href);
Daniel Veillard517752b1999-04-05 12:20:10 +00001448 else
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001449 xmlGenericError(xmlGenericErrorContext,
1450 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +00001451#endif
1452 xmlNewNs(ctxt->node, href, prefix);
1453}
1454
1455/**
1456 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001457 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001458 * @value: the comment content
1459 *
1460 * A comment has been parsed.
1461 */
1462void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001463comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001464{
Daniel Veillard27d88741999-05-29 11:51:49 +00001465 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001466 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001467 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001468
Daniel Veillard517752b1999-04-05 12:20:10 +00001469#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001470 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
Daniel Veillard517752b1999-04-05 12:20:10 +00001471#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001472 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001473 if (ret == NULL) return;
1474
Daniel Veillardcf461992000-03-14 18:30:20 +00001475 if (ctxt->inSubset == 1) {
1476 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1477 return;
1478 } else if (ctxt->inSubset == 2) {
1479 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1480 return;
1481 }
1482 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001483#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001484 xmlGenericError(xmlGenericErrorContext,
1485 "Setting comment as root\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00001486#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001487 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1488 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001489 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001490 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001491#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001492 xmlGenericError(xmlGenericErrorContext,
1493 "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001494#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001495 xmlAddChild(parent, ret);
1496 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001497#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001498 xmlGenericError(xmlGenericErrorContext,
1499 "adding comment sibling to ");
Daniel Veillardcf461992000-03-14 18:30:20 +00001500 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001501#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001502 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001503 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001504}
1505
1506/**
1507 * cdataBlock:
1508 * @ctx: the user data (XML parser context)
1509 * @value: The pcdata content
1510 * @len: the block length
1511 *
1512 * called when a pcdata block has been parsed
1513 */
1514void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001515cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001516{
1517 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001518 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001519
1520#ifdef DEBUG_SAX
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001521 xmlGenericError(xmlGenericErrorContext,
1522 "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001523#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001524 lastChild = xmlGetLastChild(ctxt->node);
1525#ifdef DEBUG_SAX_TREE
Daniel Veillardd6d7f7b2000-10-25 19:56:55 +00001526 xmlGenericError(xmlGenericErrorContext,
1527 "add chars to %s \n", ctxt->node->name);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001528#endif
1529 if ((lastChild != NULL) &&
1530 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1531 xmlTextConcat(lastChild, value, len);
1532 } else {
1533 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1534 xmlAddChild(ctxt->node, ret);
1535 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001536}
1537
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001538/*
1539 * Default handler for XML, builds the DOM tree
1540 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001541xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001542 internalSubset,
1543 isStandalone,
1544 hasInternalSubset,
1545 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001546 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001547 getEntity,
1548 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001549 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001550 attributeDecl,
1551 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001552 unparsedEntityDecl,
1553 setDocumentLocator,
1554 startDocument,
1555 endDocument,
1556 startElement,
1557 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001558 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001559 characters,
1560 ignorableWhitespace,
1561 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001562 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001563 xmlParserWarning,
1564 xmlParserError,
1565 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001566 getParameterEntity,
1567 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001568 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001569};
1570
Daniel Veillard97b58771998-10-20 06:14:16 +00001571/**
1572 * xmlDefaultSAXHandlerInit:
1573 *
1574 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001575 */
1576void
1577xmlDefaultSAXHandlerInit(void)
1578{
Daniel Veillard517752b1999-04-05 12:20:10 +00001579 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001580 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001581 xmlDefaultSAXHandler.isStandalone = isStandalone;
1582 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1583 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001584 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001585 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001586 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001587 xmlDefaultSAXHandler.entityDecl = entityDecl;
1588 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1589 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001590 xmlDefaultSAXHandler.notationDecl = notationDecl;
1591 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1592 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1593 xmlDefaultSAXHandler.startDocument = startDocument;
1594 xmlDefaultSAXHandler.endDocument = endDocument;
1595 xmlDefaultSAXHandler.startElement = startElement;
1596 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001597 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001598 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001599 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001600 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1601 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001602 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001603 if (xmlGetWarningsDefaultValue == 0)
1604 xmlDefaultSAXHandler.warning = NULL;
1605 else
1606 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001607 xmlDefaultSAXHandler.error = xmlParserError;
1608 xmlDefaultSAXHandler.fatalError = xmlParserError;
1609}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001610
1611/*
1612 * Default handler for HTML, builds the DOM tree
1613 */
1614xmlSAXHandler htmlDefaultSAXHandler = {
Daniel Veillardd83eb822000-06-30 18:39:56 +00001615 internalSubset,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001616 NULL,
1617 NULL,
1618 NULL,
1619 NULL,
1620 getEntity,
1621 NULL,
1622 NULL,
1623 NULL,
1624 NULL,
1625 NULL,
1626 setDocumentLocator,
1627 startDocument,
1628 endDocument,
1629 startElement,
1630 endElement,
1631 NULL,
1632 characters,
1633 ignorableWhitespace,
1634 NULL,
1635 comment,
1636 xmlParserWarning,
1637 xmlParserError,
1638 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001639 getParameterEntity,
Daniel Veillard7eda8452000-10-14 23:38:43 +00001640 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001641 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001642};
1643
1644/**
1645 * htmlDefaultSAXHandlerInit:
1646 *
1647 * Initialize the default SAX handler
1648 */
1649void
1650htmlDefaultSAXHandlerInit(void)
1651{
Daniel Veillardd83eb822000-06-30 18:39:56 +00001652 htmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001653 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001654 htmlDefaultSAXHandler.isStandalone = NULL;
1655 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1656 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1657 htmlDefaultSAXHandler.resolveEntity = NULL;
1658 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001659 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001660 htmlDefaultSAXHandler.entityDecl = NULL;
1661 htmlDefaultSAXHandler.attributeDecl = NULL;
1662 htmlDefaultSAXHandler.elementDecl = NULL;
1663 htmlDefaultSAXHandler.notationDecl = NULL;
1664 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1665 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1666 htmlDefaultSAXHandler.startDocument = startDocument;
1667 htmlDefaultSAXHandler.endDocument = endDocument;
1668 htmlDefaultSAXHandler.startElement = startElement;
1669 htmlDefaultSAXHandler.endElement = endElement;
1670 htmlDefaultSAXHandler.reference = NULL;
1671 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardbf432752000-11-12 15:56:56 +00001672 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001673 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1674 htmlDefaultSAXHandler.processingInstruction = NULL;
1675 htmlDefaultSAXHandler.comment = comment;
1676 htmlDefaultSAXHandler.warning = xmlParserWarning;
1677 htmlDefaultSAXHandler.error = xmlParserError;
1678 htmlDefaultSAXHandler.fatalError = xmlParserError;
1679}
Daniel Veillard39c7d712000-09-10 16:14:55 +00001680
1681/*
1682 * Default handler for HTML, builds the DOM tree
1683 */
1684xmlSAXHandler sgmlDefaultSAXHandler = {
1685 internalSubset,
1686 NULL,
1687 NULL,
1688 NULL,
1689 NULL,
1690 getEntity,
1691 NULL,
1692 NULL,
1693 NULL,
1694 NULL,
1695 NULL,
1696 setDocumentLocator,
1697 startDocument,
1698 endDocument,
1699 startElement,
1700 endElement,
1701 NULL,
1702 characters,
1703 ignorableWhitespace,
1704 NULL,
1705 comment,
1706 xmlParserWarning,
1707 xmlParserError,
1708 xmlParserError,
1709 getParameterEntity,
1710 NULL,
1711 NULL,
1712};
1713
1714/**
1715 * sgmlDefaultSAXHandlerInit:
1716 *
1717 * Initialize the default SAX handler
1718 */
1719void
1720sgmlDefaultSAXHandlerInit(void)
1721{
1722 sgmlDefaultSAXHandler.internalSubset = internalSubset;
1723 sgmlDefaultSAXHandler.externalSubset = NULL;
1724 sgmlDefaultSAXHandler.isStandalone = NULL;
1725 sgmlDefaultSAXHandler.hasInternalSubset = NULL;
1726 sgmlDefaultSAXHandler.hasExternalSubset = NULL;
1727 sgmlDefaultSAXHandler.resolveEntity = NULL;
1728 sgmlDefaultSAXHandler.getEntity = getEntity;
1729 sgmlDefaultSAXHandler.getParameterEntity = NULL;
1730 sgmlDefaultSAXHandler.entityDecl = NULL;
1731 sgmlDefaultSAXHandler.attributeDecl = NULL;
1732 sgmlDefaultSAXHandler.elementDecl = NULL;
1733 sgmlDefaultSAXHandler.notationDecl = NULL;
1734 sgmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1735 sgmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1736 sgmlDefaultSAXHandler.startDocument = startDocument;
1737 sgmlDefaultSAXHandler.endDocument = endDocument;
1738 sgmlDefaultSAXHandler.startElement = startElement;
1739 sgmlDefaultSAXHandler.endElement = endElement;
1740 sgmlDefaultSAXHandler.reference = NULL;
1741 sgmlDefaultSAXHandler.characters = characters;
1742 sgmlDefaultSAXHandler.cdataBlock = NULL;
1743 sgmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1744 sgmlDefaultSAXHandler.processingInstruction = NULL;
1745 sgmlDefaultSAXHandler.comment = comment;
1746 sgmlDefaultSAXHandler.warning = xmlParserWarning;
1747 sgmlDefaultSAXHandler.error = xmlParserError;
1748 sgmlDefaultSAXHandler.fatalError = xmlParserError;
1749}