blob: 43e847db993af8b6350f09b37d6e80b224e0fd8d [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 Veillard32bc74e2000-07-14 14:49:25 +000024#include <libxml/xml-error.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
164 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
165 name, ExternalID, SystemID);
166#endif
Daniel Veillardd83eb822000-06-30 18:39:56 +0000167
168 if (ctxt->myDoc == NULL)
169 return;
170 dtd = xmlGetIntSubset(ctxt->myDoc);
171 if (dtd != NULL) {
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000172 if (ctxt->html)
173 return;
Daniel Veillardd83eb822000-06-30 18:39:56 +0000174 xmlUnlinkNode((xmlNodePtr) dtd);
175 xmlFreeDtd(dtd);
176 ctxt->myDoc->intSubset = NULL;
177 }
178 ctxt->myDoc->intSubset =
179 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000180}
181
182/**
183 * externalSubset:
184 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000185 * @name: the root element name
186 * @ExternalID: the external ID
187 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000188 *
189 * Callback on external subset declaration.
190 */
191void
192externalSubset(void *ctx, const xmlChar *name,
193 const xmlChar *ExternalID, const xmlChar *SystemID)
194{
195 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
196#ifdef DEBUG_SAX
197 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
198 name, ExternalID, SystemID);
199#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000200 if (((ExternalID != NULL) || (SystemID != NULL)) &&
201 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
202 /*
203 * Try to fetch and parse the external subset.
204 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000205 xmlParserInputPtr oldinput;
206 int oldinputNr;
207 int oldinputMax;
208 xmlParserInputPtr *oldinputTab;
209 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000210 xmlParserInputPtr input = NULL;
211 xmlCharEncoding enc;
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000212 int oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000213
Daniel Veillardb05deb71999-08-10 19:04:08 +0000214 /*
215 * Ask the Entity resolver to load the damn thing
216 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000217 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
218 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000219 SystemID);
220 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000221 return;
222 }
223
Daniel Veillardcf461992000-03-14 18:30:20 +0000224 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
225
Daniel Veillardb05deb71999-08-10 19:04:08 +0000226 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000227 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000228 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000229 oldinput = ctxt->input;
230 oldinputNr = ctxt->inputNr;
231 oldinputMax = ctxt->inputMax;
232 oldinputTab = ctxt->inputTab;
233 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000234 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000235
236 ctxt->inputTab = (xmlParserInputPtr *)
237 xmlMalloc(5 * sizeof(xmlParserInputPtr));
238 if (ctxt->inputTab == NULL) {
239 ctxt->errNo = XML_ERR_NO_MEMORY;
240 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
241 ctxt->sax->error(ctxt->userData,
242 "externalSubset: out of memory\n");
243 ctxt->errNo = XML_ERR_NO_MEMORY;
244 ctxt->input = oldinput;
245 ctxt->inputNr = oldinputNr;
246 ctxt->inputMax = oldinputMax;
247 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000248 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000249 return;
250 }
251 ctxt->inputNr = 0;
252 ctxt->inputMax = 5;
253 ctxt->input = NULL;
254 xmlPushInput(ctxt, input);
255
256 /*
257 * On the fly encoding conversion if needed
258 */
259 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
260 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000261
262 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000263 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000264 input->line = 1;
265 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000266 input->base = ctxt->input->cur;
267 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000268 input->free = NULL;
269
270 /*
271 * let's parse that entity knowing it's an external subset.
272 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000273 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000274
Daniel Veillardcf461992000-03-14 18:30:20 +0000275 /*
276 * Free up the external entities
277 */
278
279 while (ctxt->inputNr > 1)
280 xmlPopInput(ctxt);
281 xmlFreeInputStream(ctxt->input);
282 xmlFree(ctxt->inputTab);
283
284 /*
285 * Restore the parsing context of the main entity
286 */
287 ctxt->input = oldinput;
288 ctxt->inputNr = oldinputNr;
289 ctxt->inputMax = oldinputMax;
290 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000291 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000292 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000293 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000294}
295
296/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000297 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000298 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000299 * @publicId: The public ID of the entity
300 * @systemId: The system ID of the entity
301 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000302 * The entity loader, to control the loading of external entities,
303 * the application can either:
304 * - override this resolveEntity() callback in the SAX block
305 * - or better use the xmlSetExternalEntityLoader() function to
306 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000307 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000308 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000309 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000310xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000311resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000312{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000313 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000314
315#ifdef DEBUG_SAX
316 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
317#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000318
Daniel Veillard686d6b62000-01-03 11:08:02 +0000319 return(xmlLoadExternalEntity((const char *) systemId,
320 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000321}
322
Daniel Veillard97b58771998-10-20 06:14:16 +0000323/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000324 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000325 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000326 * @name: The entity name
327 *
328 * Get an entity by name
329 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000330 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000331 */
332xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000333getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000334{
Daniel Veillard27d88741999-05-29 11:51:49 +0000335 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000336 xmlEntityPtr ret;
337
338#ifdef DEBUG_SAX
339 fprintf(stderr, "SAX.getEntity(%s)\n", name);
340#endif
341
342 ret = xmlGetDocEntity(ctxt->myDoc, name);
Daniel Veillard87b95392000-08-12 21:12:04 +0000343 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
344 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
345 /*
346 * for validation purposes we really need to fetch and
347 * parse the external entity
348 */
349 int parse;
350 xmlNodePtr children;
351
352 parse = xmlParseCtxtExternalEntity(ctxt,
353 ret->SystemID, ret->ExternalID, &children);
354 xmlAddChildList((xmlNodePtr) ret, children);
355 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000356 return(ret);
357}
358
Daniel Veillardb05deb71999-08-10 19:04:08 +0000359/**
360 * getParameterEntity:
361 * @ctx: the user data (XML parser context)
362 * @name: The entity name
363 *
364 * Get a parameter entity by name
365 *
366 * Returns the xmlEntityPtr if found.
367 */
368xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000369getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000370{
371 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
372 xmlEntityPtr ret;
373
374#ifdef DEBUG_SAX
375 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
376#endif
377
378 ret = xmlGetParameterEntity(ctxt->myDoc, name);
379 return(ret);
380}
381
Daniel Veillard517752b1999-04-05 12:20:10 +0000382
383/**
384 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000385 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000386 * @name: the entity name
387 * @type: the entity type
388 * @publicId: The public ID of the entity
389 * @systemId: The system ID of the entity
390 * @content: the entity value (without processing).
391 *
392 * An entity definition has been parsed
393 */
394void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000395entityDecl(void *ctx, const xmlChar *name, int type,
396 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000397{
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000398 xmlEntityPtr ent;
Daniel Veillard27d88741999-05-29 11:51:49 +0000399 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000400
401#ifdef DEBUG_SAX
402 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
403 name, type, publicId, systemId, content);
404#endif
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000405 if (ctxt->inSubset == 1) {
406 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
Daniel Veillardcf461992000-03-14 18:30:20 +0000407 systemId, content);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000408 if ((ent == NULL) && (ctxt->pedantic) &&
409 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
410 ctxt->sax->warning(ctxt,
411 "Entity(%s) already defined in the internal subset\n", name);
412 } else if (ctxt->inSubset == 2) {
413 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
Daniel Veillardcf461992000-03-14 18:30:20 +0000414 systemId, content);
Daniel Veillardf0cc7cc2000-08-26 21:40:43 +0000415 if ((ent == NULL) && (ctxt->pedantic) &&
416 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
417 ctxt->sax->warning(ctxt,
418 "Entity(%s) already defined in the external subset\n", name);
419 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +0000420 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
421 ctxt->sax->error(ctxt,
422 "SAX.entityDecl(%s) called while not in subset\n", name);
423 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000424}
425
426/**
427 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000428 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000429 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000430 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000431 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000432 * @def: the type of default value
433 * @defaultValue: the attribute default value
434 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000435 *
436 * An attribute definition has been parsed
437 */
438void
Daniel Veillardcf461992000-03-14 18:30:20 +0000439attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000440 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000441 xmlEnumerationPtr tree)
442{
Daniel Veillard27d88741999-05-29 11:51:49 +0000443 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000444 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000445 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000446
447#ifdef DEBUG_SAX
448 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000449 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000450#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000451 name = xmlSplitQName(ctxt, fullname, &prefix);
452 if (ctxt->inSubset == 1)
453 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000454 name, prefix, (xmlAttributeType) type,
455 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000456 else if (ctxt->inSubset == 2)
457 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000458 name, prefix, (xmlAttributeType) type,
459 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000460 else {
461 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
462 ctxt->sax->error(ctxt,
463 "SAX.attributeDecl(%s) called while not in subset\n", name);
464 return;
465 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000466 if (attr == 0) ctxt->valid = 0;
467 if (ctxt->validate && ctxt->wellFormed &&
468 ctxt->myDoc && ctxt->myDoc->intSubset)
469 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
470 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000471 if (prefix != NULL)
472 xmlFree(prefix);
473 if (name != NULL)
474 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000475}
476
477/**
478 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000479 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000480 * @name: the element name
481 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000482 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000483 *
484 * An element definition has been parsed
485 */
486void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000487elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000488 xmlElementContentPtr content)
489{
Daniel Veillard27d88741999-05-29 11:51:49 +0000490 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000491 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000492
493#ifdef DEBUG_SAX
494 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000495 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000496#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000497
Daniel Veillardcf461992000-03-14 18:30:20 +0000498 if (ctxt->inSubset == 1)
499 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000500 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000501 else if (ctxt->inSubset == 2)
502 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000503 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000504 else {
505 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
506 ctxt->sax->error(ctxt,
507 "SAX.elementDecl(%s) called while not in subset\n", name);
508 return;
509 }
510 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000511 if (ctxt->validate && ctxt->wellFormed &&
512 ctxt->myDoc && ctxt->myDoc->intSubset)
513 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000514}
515
516/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000517 * notationDecl:
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 notation
520 * @publicId: The public ID of the entity
521 * @systemId: The system ID of the entity
522 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000523 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000524 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000525void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000526notationDecl(void *ctx, const xmlChar *name,
527 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000528{
Daniel Veillard27d88741999-05-29 11:51:49 +0000529 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000530 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000531
Daniel Veillard260a68f1998-08-13 03:39:55 +0000532#ifdef DEBUG_SAX
533 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
534#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000535
Daniel Veillardcf461992000-03-14 18:30:20 +0000536 if (ctxt->inSubset == 1)
537 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000538 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000539 else if (ctxt->inSubset == 2)
540 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
541 publicId, systemId);
542 else {
543 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
544 ctxt->sax->error(ctxt,
545 "SAX.notationDecl(%s) called while not in subset\n", name);
546 return;
547 }
548 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000549 if (ctxt->validate && ctxt->wellFormed &&
550 ctxt->myDoc && ctxt->myDoc->intSubset)
551 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
552 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000553}
554
Daniel Veillard97b58771998-10-20 06:14:16 +0000555/**
556 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000557 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000558 * @name: The name of the entity
559 * @publicId: The public ID of the entity
560 * @systemId: The system ID of the entity
561 * @notationName: the name of the notation
562 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000563 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000564 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000565void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000566unparsedEntityDecl(void *ctx, const xmlChar *name,
567 const xmlChar *publicId, const xmlChar *systemId,
568 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000569{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000570 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000571#ifdef DEBUG_SAX
572 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
573 name, publicId, systemId, notationName);
574#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000575 if (ctxt->validate && ctxt->wellFormed &&
576 ctxt->myDoc && ctxt->myDoc->intSubset)
577 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
578 notationName);
579 xmlAddDocEntity(ctxt->myDoc, name,
580 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
581 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000582}
583
Daniel Veillard97b58771998-10-20 06:14:16 +0000584/**
585 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000586 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000587 * @loc: A SAX Locator
588 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000589 * Receive the document locator at startup, actually xmlDefaultSAXLocator
590 * Everything is available on the context, so this is useless in our case.
591 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000592void
Daniel Veillard27d88741999-05-29 11:51:49 +0000593setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000594{
Daniel Veillard27d88741999-05-29 11:51:49 +0000595 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000596#ifdef DEBUG_SAX
597 fprintf(stderr, "SAX.setDocumentLocator()\n");
598#endif
599}
600
Daniel Veillard97b58771998-10-20 06:14:16 +0000601/**
602 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000603 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000604 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000605 * called when the document start being processed.
606 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000607void
Daniel Veillard27d88741999-05-29 11:51:49 +0000608startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000609{
Daniel Veillard27d88741999-05-29 11:51:49 +0000610 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000611 xmlDocPtr doc;
612
Daniel Veillard260a68f1998-08-13 03:39:55 +0000613#ifdef DEBUG_SAX
614 fprintf(stderr, "SAX.startDocument()\n");
615#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000616 if (ctxt->html) {
617 if (ctxt->myDoc == NULL)
Daniel Veillard87b95392000-08-12 21:12:04 +0000618#ifdef LIBXML_HTML_ENABLED
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000619 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
Daniel Veillard87b95392000-08-12 21:12:04 +0000620#else
621 fprintf(stderr, "libxml2 built without HTML support\n");
622#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000623 } else {
624 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
625 if (doc != NULL) {
626 if (ctxt->encoding != NULL)
627 doc->encoding = xmlStrdup(ctxt->encoding);
628 else
629 doc->encoding = NULL;
630 doc->standalone = ctxt->standalone;
631 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000632 }
Daniel Veillard87b95392000-08-12 21:12:04 +0000633 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
634 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
635 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename);
636 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000637}
638
Daniel Veillard97b58771998-10-20 06:14:16 +0000639/**
640 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000641 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000642 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000643 * called when the document end has been detected.
644 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000645void
Daniel Veillard27d88741999-05-29 11:51:49 +0000646endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000647{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000648 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000649#ifdef DEBUG_SAX
650 fprintf(stderr, "SAX.endDocument()\n");
651#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000652 if (ctxt->validate && ctxt->wellFormed &&
653 ctxt->myDoc && ctxt->myDoc->intSubset)
654 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000655
656 /*
657 * Grab the encoding if it was added on-the-fly
658 */
659 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
660 (ctxt->myDoc->encoding == NULL)) {
661 ctxt->myDoc->encoding = ctxt->encoding;
662 ctxt->encoding = NULL;
663 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000664 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
665 (ctxt->myDoc->encoding == NULL)) {
666 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
667 }
668 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
669 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
670 ctxt->myDoc->charset = ctxt->charset;
671 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000672}
673
Daniel Veillard97b58771998-10-20 06:14:16 +0000674/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000675 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000676 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000677 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000678 * @value: The attribute value
679 *
680 * Handle an attribute that has been read by the parser.
681 * The default handling is to convert the attribute into an
682 * DOM subtree and past it in a new xmlAttr element added to
683 * the element.
684 */
685void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000686attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000687{
Daniel Veillard27d88741999-05-29 11:51:49 +0000688 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000689 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000690 xmlChar *name;
691 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000692 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000693 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000694
695/****************
696#ifdef DEBUG_SAX
697 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
698#endif
699 ****************/
700 /*
701 * Split the full name into a namespace prefix and the tag name
702 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000703 name = xmlSplitQName(ctxt, fullname, &ns);
704
705 /*
706 * Do the last stave of the attribute normalization
707 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000708 if (ctxt->html)
709 nval = NULL;
710 else
711 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
Daniel Veillardcf461992000-03-14 18:30:20 +0000712 ctxt->node, fullname, value);
713 if (nval != NULL)
714 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000715
716 /*
717 * Check whether it's a namespace definition
718 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000719 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000720 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
721 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000722 xmlURIPtr uri;
723
724 uri = xmlParseURI((const char *)value);
725 if (uri == NULL) {
726 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
727 ctxt->sax->warning(ctxt->userData,
728 "nmlns: %s not a valid URI\n", value);
729 } else {
730 if (uri->scheme == NULL) {
731 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
732 ctxt->sax->warning(ctxt->userData,
733 "nmlns: URI %s is not absolute\n", value);
734 }
735 xmlFreeURI(uri);
736 }
737
Daniel Veillard517752b1999-04-05 12:20:10 +0000738 /* a default namespace definition */
739 xmlNewNs(ctxt->node, value, NULL);
740 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000741 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000742 if (nval != NULL)
743 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000744 return;
745 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000746 if ((!ctxt->html) &&
747 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000748 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000749 /*
750 * Validate also for namespace decls, they are attributes from
751 * an XML-1.0 perspective
752 TODO ... doesn't map well with current API
753 if (ctxt->validate && ctxt->wellFormed &&
754 ctxt->myDoc && ctxt->myDoc->intSubset)
755 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
756 ctxt->node, ret, value);
757 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000758 /* a standard namespace definition */
759 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000760 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000761 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000762 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000763 if (nval != NULL)
764 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000765 return;
766 }
767
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000768 if (ns != NULL)
769 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
770 else {
771 namespace = NULL;
772 }
773
Daniel Veillardb96e6431999-08-29 21:02:19 +0000774 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
775 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000776
Daniel Veillardb96e6431999-08-29 21:02:19 +0000777 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000778 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
779 xmlNodePtr tmp;
780
781 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
782 tmp = ret->children;
783 while (tmp != NULL) {
784 tmp->parent = (xmlNodePtr) ret;
785 if (tmp->next == NULL)
786 ret->last = tmp;
787 tmp = tmp->next;
788 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000789 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000790 ret->children = xmlNewDocText(ctxt->myDoc, value);
791 ret->last = ret->children;
792 if (ret->children != NULL)
793 ret->children->parent = (xmlNodePtr) ret;
794 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000795 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000796
Daniel Veillardbe803962000-06-28 23:40:59 +0000797 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000798 ctxt->myDoc && ctxt->myDoc->intSubset) {
799
800 /*
801 * If we don't substitute entities, the validation should be
802 * done on a value with replaced entities anyway.
803 */
804 if (!ctxt->replaceEntities) {
805 xmlChar *val;
806
807 ctxt->depth++;
808 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
809 0,0,0);
810 ctxt->depth--;
811 if (val == NULL)
812 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
813 ctxt->myDoc, ctxt->node, ret, value);
814 else {
815 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
816 ctxt->myDoc, ctxt->node, ret, val);
817 xmlFree(val);
818 }
819 } else {
820 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000821 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000822 }
823 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000824 /*
825 * when validating, the ID registration is done at the attribute
826 * validation level. Otherwise we have to do specific handling here.
827 */
828 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
829 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000830 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
831 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000832 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000833
Daniel Veillardcf461992000-03-14 18:30:20 +0000834 if (nval != NULL)
835 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000836 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000837 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000838 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000839 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000840}
841
842/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000843 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000844 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000845 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000846 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000847 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000848 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000849 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000850void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000851startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000852{
Daniel Veillard27d88741999-05-29 11:51:49 +0000853 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000854 xmlNodePtr ret;
855 xmlNodePtr parent = ctxt->node;
856 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000857 xmlChar *name;
858 xmlChar *prefix;
859 const xmlChar *att;
860 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000861 int i;
862
Daniel Veillard260a68f1998-08-13 03:39:55 +0000863#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000864 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000865#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000866
867 /*
868 * First check on validity:
869 */
870 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
871 ((ctxt->myDoc->intSubset == NULL) ||
872 ((ctxt->myDoc->intSubset->notations == NULL) &&
873 (ctxt->myDoc->intSubset->elements == NULL) &&
874 (ctxt->myDoc->intSubset->attributes == NULL) &&
875 (ctxt->myDoc->intSubset->entities == NULL)))) {
876 if (ctxt->vctxt.error != NULL) {
877 ctxt->vctxt.error(ctxt->vctxt.userData,
878 "Validation failed: no DTD found !\n");
879 }
880 ctxt->validate = 0;
881 }
882
883
Daniel Veillard517752b1999-04-05 12:20:10 +0000884 /*
885 * Split the full name into a namespace prefix and the tag name
886 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000887 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000888
889
890 /*
891 * Note : the namespace resolution is deferred until the end of the
892 * attributes parsing, since local namespace can be defined as
893 * an attribute at this level.
894 */
895 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
896 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000897 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000898#ifdef DEBUG_SAX_TREE
899 fprintf(stderr, "Setting %s as root\n", name);
900#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000901 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000902 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000903 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000904 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000905 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000906
907 /*
908 * We are parsing a new node.
909 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000910#ifdef DEBUG_SAX_TREE
911 fprintf(stderr, "pushing(%s)\n", name);
912#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000913 nodePush(ctxt, ret);
914
915 /*
916 * Link the child element
917 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000918 if (parent != NULL) {
919 if (parent->type == XML_ELEMENT_NODE) {
920#ifdef DEBUG_SAX_TREE
921 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
922#endif
923 xmlAddChild(parent, ret);
924 } else {
925#ifdef DEBUG_SAX_TREE
926 fprintf(stderr, "adding sibling %s to ", name);
927 xmlDebugDumpOneNode(stderr, parent, 0);
928#endif
929 xmlAddSibling(parent, ret);
930 }
931 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000932
933 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000934 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000935 */
936 if (atts != NULL) {
937 i = 0;
938 att = atts[i++];
939 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000940 if (!ctxt->html) {
941 while ((att != NULL) && (value != NULL)) {
942 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
943 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000944
Daniel Veillardbe803962000-06-28 23:40:59 +0000945 att = atts[i++];
946 value = atts[i++];
947 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000948 }
949 }
950
951 /*
952 * Search the namespace, note that since the attributes have been
953 * processed, the local namespaces are available.
954 */
955 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
956 if ((ns == NULL) && (parent != NULL))
957 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
958 xmlSetNs(ret, ns);
959
Daniel Veillardbe803962000-06-28 23:40:59 +0000960 /*
961 * process all the other attributes
962 */
963 if (atts != NULL) {
964 i = 0;
965 att = atts[i++];
966 value = atts[i++];
967 if (ctxt->html) {
968 while (att != NULL) {
969 attribute(ctxt, att, value);
970 att = atts[i++];
971 value = atts[i++];
972 }
973 } else {
974 while ((att != NULL) && (value != NULL)) {
975 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
976 attribute(ctxt, att, value);
977
978 /*
979 * Next ones
980 */
981 att = atts[i++];
982 value = atts[i++];
983 }
984 }
985 }
986
987 /*
988 * If it's the Document root, finish the Dtd validation and
989 * check the document root element for validity
990 */
991 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
992 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
993 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
994 ctxt->vctxt.finishDtd = 1;
995 }
996
Daniel Veillard517752b1999-04-05 12:20:10 +0000997 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000998 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000999 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00001000 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +00001001
Daniel Veillard260a68f1998-08-13 03:39:55 +00001002}
1003
Daniel Veillard97b58771998-10-20 06:14:16 +00001004/**
1005 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001006 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001007 * @name: The element name
1008 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001009 * called when the end of an element has been detected.
1010 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001011void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001012endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +00001013{
Daniel Veillard27d88741999-05-29 11:51:49 +00001014 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001015 xmlParserNodeInfo node_info;
1016 xmlNodePtr cur = ctxt->node;
1017
Daniel Veillard260a68f1998-08-13 03:39:55 +00001018#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001019 if (name == NULL)
1020 fprintf(stderr, "SAX.endElement(NULL)\n");
1021 else
1022 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001023#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001024
1025 /* Capture end position and add node */
1026 if (cur != NULL && ctxt->record_info) {
1027 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1028 node_info.end_line = ctxt->input->line;
1029 node_info.node = cur;
1030 xmlParserAddNodeInfo(ctxt, &node_info);
1031 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001032 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +00001033
Daniel Veillardb05deb71999-08-10 19:04:08 +00001034 if (ctxt->validate && ctxt->wellFormed &&
1035 ctxt->myDoc && ctxt->myDoc->intSubset)
1036 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1037 cur);
1038
1039
Daniel Veillard517752b1999-04-05 12:20:10 +00001040 /*
1041 * end of parsing of this node.
1042 */
Daniel Veillardb96e6431999-08-29 21:02:19 +00001043#ifdef DEBUG_SAX_TREE
1044 fprintf(stderr, "popping(%s)\n", cur->name);
1045#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001046 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001047}
1048
Daniel Veillard97b58771998-10-20 06:14:16 +00001049/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001050 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001051 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001052 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001053 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001054 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001055 */
1056void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001057reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001058{
Daniel Veillard27d88741999-05-29 11:51:49 +00001059 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001060 xmlNodePtr ret;
1061
Daniel Veillard11e00581998-10-24 18:27:49 +00001062#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001063 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001064#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001065 if (name[0] == '#')
1066 ret = xmlNewCharRef(ctxt->myDoc, name);
1067 else
1068 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001069#ifdef DEBUG_SAX_TREE
1070 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
1071#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001072 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001073}
1074
1075/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001076 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001077 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001078 * @ch: a xmlChar string
1079 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001080 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001081 * receiving some chars from the parser.
1082 * Question: how much at a time ???
1083 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001084void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001085characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001086{
Daniel Veillard27d88741999-05-29 11:51:49 +00001087 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001088 xmlNodePtr lastChild;
1089
1090#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001091 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001092#endif
1093 /*
1094 * Handle the data if any. If there is no child
1095 * add it as content, otherwise if the last child is text,
1096 * concatenate it, else create a new node of type text.
1097 */
1098
Daniel Veillard35008381999-10-25 13:15:52 +00001099 if (ctxt->node == NULL) {
1100#ifdef DEBUG_SAX_TREE
1101 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1102#endif
1103 return;
1104 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001106#ifdef DEBUG_SAX_TREE
1107 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1108#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001109
1110 /*
1111 * Here we needed an accelerator mechanism in case of very large
1112 * elements. Use an attribute in the structure !!!
1113 */
1114 if (lastChild == NULL) {
1115 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001116 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001117#ifndef XML_USE_BUFFER_CONTENT
1118 if (ctxt->node->children != NULL) {
1119 ctxt->nodelen = len;
1120 ctxt->nodemem = len + 1;
1121 }
1122#endif
1123 } else {
1124 if (xmlNodeIsText(lastChild)) {
1125#ifndef XML_USE_BUFFER_CONTENT
1126 /*
1127 * The whole point of maintaining nodelen and nodemem,
1128 * xmlTextConcat is too costly, i.e. compute lenght,
1129 * reallocate a new buffer, move data, append ch. Here
1130 * We try to minimaze realloc() uses and avoid copying
1131 * and recomputing lenght over and over.
1132 */
1133 if (ctxt->nodelen + len >= ctxt->nodemem) {
1134 xmlChar *newbuf;
1135 int size;
1136
1137 size = ctxt->nodemem + len;
1138 size *= 2;
1139 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1140 if (newbuf == NULL) {
1141 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1142 ctxt->sax->error(ctxt->userData,
1143 "SAX.characters(): out of memory\n");
1144 return;
1145 }
1146 ctxt->nodemem = size;
1147 lastChild->content = newbuf;
1148 }
1149 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1150 ctxt->nodelen += len;
1151 lastChild->content[ctxt->nodelen] = 0;
1152#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001153 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001154#endif
1155 } else {
1156 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001157 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001158 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001159#ifndef XML_USE_BUFFER_CONTENT
1160 if (ctxt->node->children != NULL) {
1161 ctxt->nodelen = len;
1162 ctxt->nodemem = len + 1;
1163 }
1164#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001165 }
1166 }
1167}
1168
Daniel Veillard97b58771998-10-20 06:14:16 +00001169/**
1170 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001171 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001172 * @ch: a xmlChar string
1173 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001174 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001175 * receiving some ignorable whitespaces from the parser.
1176 * Question: how much at a time ???
1177 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001178void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001179ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001180{
Daniel Veillard27d88741999-05-29 11:51:49 +00001181 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001182#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001183 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001184#endif
1185}
1186
Daniel Veillard97b58771998-10-20 06:14:16 +00001187/**
1188 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001189 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001190 * @target: the target name
1191 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001192 *
1193 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001194 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001195void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001196processingInstruction(void *ctx, const xmlChar *target,
1197 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001198{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001199 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1200 xmlNodePtr ret;
1201 xmlNodePtr parent = ctxt->node;
1202
Daniel Veillard260a68f1998-08-13 03:39:55 +00001203#ifdef DEBUG_SAX
1204 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1205#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001206
1207 ret = xmlNewPI(target, data);
1208 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001209 parent = ctxt->node;
1210
1211 if (ctxt->inSubset == 1) {
1212 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1213 return;
1214 } else if (ctxt->inSubset == 2) {
1215 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1216 return;
1217 }
1218 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001219#ifdef DEBUG_SAX_TREE
1220 fprintf(stderr, "Setting PI %s as root\n", target);
1221#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001222 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1223 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001224 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001225 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001226#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001227 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001228#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001229 xmlAddChild(parent, ret);
1230 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001231#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001232 fprintf(stderr, "adding PI %s sibling to ", target);
1233 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001234#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001235 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001236 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001237}
1238
Daniel Veillard517752b1999-04-05 12:20:10 +00001239/**
1240 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001241 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001242 * @href: the namespace associated URN
1243 * @prefix: the namespace prefix
1244 *
1245 * An old global namespace has been parsed.
1246 */
1247void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001248globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001249{
Daniel Veillard27d88741999-05-29 11:51:49 +00001250 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001251#ifdef DEBUG_SAX
1252 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1253#endif
1254 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1255}
1256
1257/**
1258 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001259 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001260 * @name: the namespace prefix
1261 *
1262 * Set the current element namespace.
1263 */
Daniel Veillard06047432000-04-24 11:33:38 +00001264
Daniel Veillard517752b1999-04-05 12:20:10 +00001265void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001266setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001267{
Daniel Veillard27d88741999-05-29 11:51:49 +00001268 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001269 xmlNsPtr ns;
1270 xmlNodePtr parent;
1271
1272#ifdef DEBUG_SAX
1273 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1274#endif
1275 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1276 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1277 if (ctxt->nodeNr >= 2) {
1278 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1279 if (parent != NULL)
1280 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1281 }
1282 }
1283 xmlSetNs(ctxt->node, ns);
1284}
1285
1286/**
1287 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001288 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001289 *
1290 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001291 *
1292 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001293 */
Daniel Veillard06047432000-04-24 11:33:38 +00001294
Daniel Veillard517752b1999-04-05 12:20:10 +00001295xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001296getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001297{
Daniel Veillard27d88741999-05-29 11:51:49 +00001298 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001299 xmlNsPtr ret;
1300
1301#ifdef DEBUG_SAX
1302 fprintf(stderr, "SAX.getNamespace()\n");
1303#endif
1304 ret = ctxt->node->ns;
1305 return(ret);
1306}
1307
1308/**
1309 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001310 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001311 * @namespace: the namespace to check against
1312 *
1313 * Check that the current element namespace is the same as the
1314 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001315 *
1316 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001317 */
Daniel Veillard06047432000-04-24 11:33:38 +00001318
Daniel Veillard517752b1999-04-05 12:20:10 +00001319int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001320checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001321{
Daniel Veillard27d88741999-05-29 11:51:49 +00001322 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001323 xmlNodePtr cur = ctxt->node;
1324
1325#ifdef DEBUG_SAX
1326 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1327#endif
1328
1329 /*
1330 * Check that the Name in the ETag is the same as in the STag.
1331 */
1332 if (namespace == NULL) {
1333 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1334 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1335 ctxt->sax->error(ctxt,
1336 "End tags for %s don't hold the namespace %s\n",
1337 cur->name, cur->ns->prefix);
1338 ctxt->wellFormed = 0;
1339 }
1340 } else {
1341 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1342 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1343 ctxt->sax->error(ctxt,
1344 "End tags %s holds a prefix %s not used by the open tag\n",
1345 cur->name, namespace);
1346 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001347 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001348 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1349 ctxt->sax->error(ctxt,
1350 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1351 cur->name, cur->ns->prefix, namespace);
1352 ctxt->wellFormed = 0;
1353 } else
1354 return(1);
1355 }
1356 return(0);
1357}
1358
1359/**
1360 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001361 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001362 * @href: the namespace associated URN
1363 * @prefix: the namespace prefix
1364 *
1365 * A namespace has been parsed.
1366 */
1367void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001368namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
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#ifdef DEBUG_SAX
1372 if (prefix == NULL)
1373 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1374 else
1375 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1376#endif
1377 xmlNewNs(ctxt->node, href, prefix);
1378}
1379
1380/**
1381 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001382 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001383 * @value: the comment content
1384 *
1385 * A comment has been parsed.
1386 */
1387void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001388comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001389{
Daniel Veillard27d88741999-05-29 11:51:49 +00001390 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001391 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001392 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001393
Daniel Veillard517752b1999-04-05 12:20:10 +00001394#ifdef DEBUG_SAX
1395 fprintf(stderr, "SAX.comment(%s)\n", value);
1396#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001397 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001398 if (ret == NULL) return;
1399
Daniel Veillardcf461992000-03-14 18:30:20 +00001400 if (ctxt->inSubset == 1) {
1401 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1402 return;
1403 } else if (ctxt->inSubset == 2) {
1404 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1405 return;
1406 }
1407 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001408#ifdef DEBUG_SAX_TREE
1409 fprintf(stderr, "Setting comment as root\n");
1410#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001411 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1412 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001413 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001414 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001415#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001416 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001417#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001418 xmlAddChild(parent, ret);
1419 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001420#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001421 fprintf(stderr, "adding comment sibling to ");
1422 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001423#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001424 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001425 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001426}
1427
1428/**
1429 * cdataBlock:
1430 * @ctx: the user data (XML parser context)
1431 * @value: The pcdata content
1432 * @len: the block length
1433 *
1434 * called when a pcdata block has been parsed
1435 */
1436void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001437cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001438{
1439 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001440 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001441
1442#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001443 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001444#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001445 lastChild = xmlGetLastChild(ctxt->node);
1446#ifdef DEBUG_SAX_TREE
1447 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1448#endif
1449 if ((lastChild != NULL) &&
1450 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1451 xmlTextConcat(lastChild, value, len);
1452 } else {
1453 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1454 xmlAddChild(ctxt->node, ret);
1455 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001456}
1457
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001458/*
1459 * Default handler for XML, builds the DOM tree
1460 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001461xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001462 internalSubset,
1463 isStandalone,
1464 hasInternalSubset,
1465 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001466 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001467 getEntity,
1468 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001469 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001470 attributeDecl,
1471 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001472 unparsedEntityDecl,
1473 setDocumentLocator,
1474 startDocument,
1475 endDocument,
1476 startElement,
1477 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001478 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001479 characters,
1480 ignorableWhitespace,
1481 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001482 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001483 xmlParserWarning,
1484 xmlParserError,
1485 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001486 getParameterEntity,
1487 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001488 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001489};
1490
Daniel Veillard97b58771998-10-20 06:14:16 +00001491/**
1492 * xmlDefaultSAXHandlerInit:
1493 *
1494 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001495 */
1496void
1497xmlDefaultSAXHandlerInit(void)
1498{
Daniel Veillard517752b1999-04-05 12:20:10 +00001499 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001500 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001501 xmlDefaultSAXHandler.isStandalone = isStandalone;
1502 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1503 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001504 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001505 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001506 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001507 xmlDefaultSAXHandler.entityDecl = entityDecl;
1508 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1509 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001510 xmlDefaultSAXHandler.notationDecl = notationDecl;
1511 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1512 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1513 xmlDefaultSAXHandler.startDocument = startDocument;
1514 xmlDefaultSAXHandler.endDocument = endDocument;
1515 xmlDefaultSAXHandler.startElement = startElement;
1516 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001517 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001518 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001519 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001520 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1521 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001522 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001523 if (xmlGetWarningsDefaultValue == 0)
1524 xmlDefaultSAXHandler.warning = NULL;
1525 else
1526 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001527 xmlDefaultSAXHandler.error = xmlParserError;
1528 xmlDefaultSAXHandler.fatalError = xmlParserError;
1529}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001530
1531/*
1532 * Default handler for HTML, builds the DOM tree
1533 */
1534xmlSAXHandler htmlDefaultSAXHandler = {
Daniel Veillardd83eb822000-06-30 18:39:56 +00001535 internalSubset,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001536 NULL,
1537 NULL,
1538 NULL,
1539 NULL,
1540 getEntity,
1541 NULL,
1542 NULL,
1543 NULL,
1544 NULL,
1545 NULL,
1546 setDocumentLocator,
1547 startDocument,
1548 endDocument,
1549 startElement,
1550 endElement,
1551 NULL,
1552 characters,
1553 ignorableWhitespace,
1554 NULL,
1555 comment,
1556 xmlParserWarning,
1557 xmlParserError,
1558 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001559 getParameterEntity,
1560 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001561 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001562};
1563
1564/**
1565 * htmlDefaultSAXHandlerInit:
1566 *
1567 * Initialize the default SAX handler
1568 */
1569void
1570htmlDefaultSAXHandlerInit(void)
1571{
Daniel Veillardd83eb822000-06-30 18:39:56 +00001572 htmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001573 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001574 htmlDefaultSAXHandler.isStandalone = NULL;
1575 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1576 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1577 htmlDefaultSAXHandler.resolveEntity = NULL;
1578 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001579 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001580 htmlDefaultSAXHandler.entityDecl = NULL;
1581 htmlDefaultSAXHandler.attributeDecl = NULL;
1582 htmlDefaultSAXHandler.elementDecl = NULL;
1583 htmlDefaultSAXHandler.notationDecl = NULL;
1584 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1585 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1586 htmlDefaultSAXHandler.startDocument = startDocument;
1587 htmlDefaultSAXHandler.endDocument = endDocument;
1588 htmlDefaultSAXHandler.startElement = startElement;
1589 htmlDefaultSAXHandler.endElement = endElement;
1590 htmlDefaultSAXHandler.reference = NULL;
1591 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001592 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001593 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1594 htmlDefaultSAXHandler.processingInstruction = NULL;
1595 htmlDefaultSAXHandler.comment = comment;
1596 htmlDefaultSAXHandler.warning = xmlParserWarning;
1597 htmlDefaultSAXHandler.error = xmlParserError;
1598 htmlDefaultSAXHandler.fatalError = xmlParserError;
1599}