blob: ecc5331b7dc155c770719d7984ab5f4ad90efc29 [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) {
172 xmlUnlinkNode((xmlNodePtr) dtd);
173 xmlFreeDtd(dtd);
174 ctxt->myDoc->intSubset = NULL;
175 }
176 ctxt->myDoc->intSubset =
177 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000178}
179
180/**
181 * externalSubset:
182 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000183 * @name: the root element name
184 * @ExternalID: the external ID
185 * @SystemID: the SYSTEM ID (e.g. filename or URL)
Daniel Veillardcf461992000-03-14 18:30:20 +0000186 *
187 * Callback on external subset declaration.
188 */
189void
190externalSubset(void *ctx, const xmlChar *name,
191 const xmlChar *ExternalID, const xmlChar *SystemID)
192{
193 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
194#ifdef DEBUG_SAX
195 fprintf(stderr, "SAX.externalSubset(%s, %s, %s)\n",
196 name, ExternalID, SystemID);
197#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000198 if (((ExternalID != NULL) || (SystemID != NULL)) &&
199 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
200 /*
201 * Try to fetch and parse the external subset.
202 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000203 xmlParserInputPtr oldinput;
204 int oldinputNr;
205 int oldinputMax;
206 xmlParserInputPtr *oldinputTab;
207 int oldwellFormed;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000208 xmlParserInputPtr input = NULL;
209 xmlCharEncoding enc;
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000210 int oldcharset;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000211
Daniel Veillardb05deb71999-08-10 19:04:08 +0000212 /*
213 * Ask the Entity resolver to load the damn thing
214 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000215 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
216 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000217 SystemID);
218 if (input == NULL) {
Daniel Veillardb05deb71999-08-10 19:04:08 +0000219 return;
220 }
221
Daniel Veillardcf461992000-03-14 18:30:20 +0000222 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
223
Daniel Veillardb05deb71999-08-10 19:04:08 +0000224 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000225 * make sure we won't destroy the main document context
Daniel Veillardb05deb71999-08-10 19:04:08 +0000226 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000227 oldinput = ctxt->input;
228 oldinputNr = ctxt->inputNr;
229 oldinputMax = ctxt->inputMax;
230 oldinputTab = ctxt->inputTab;
231 oldwellFormed = ctxt->wellFormed;
Daniel Veillardbe803962000-06-28 23:40:59 +0000232 oldcharset = ctxt->charset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000233
234 ctxt->inputTab = (xmlParserInputPtr *)
235 xmlMalloc(5 * sizeof(xmlParserInputPtr));
236 if (ctxt->inputTab == NULL) {
237 ctxt->errNo = XML_ERR_NO_MEMORY;
238 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
239 ctxt->sax->error(ctxt->userData,
240 "externalSubset: out of memory\n");
241 ctxt->errNo = XML_ERR_NO_MEMORY;
242 ctxt->input = oldinput;
243 ctxt->inputNr = oldinputNr;
244 ctxt->inputMax = oldinputMax;
245 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000246 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000247 return;
248 }
249 ctxt->inputNr = 0;
250 ctxt->inputMax = 5;
251 ctxt->input = NULL;
252 xmlPushInput(ctxt, input);
253
254 /*
255 * On the fly encoding conversion if needed
256 */
257 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
258 xmlSwitchEncoding(ctxt, enc);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000259
260 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000261 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000262 input->line = 1;
263 input->col = 1;
Daniel Veillardcf461992000-03-14 18:30:20 +0000264 input->base = ctxt->input->cur;
265 input->cur = ctxt->input->cur;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000266 input->free = NULL;
267
268 /*
269 * let's parse that entity knowing it's an external subset.
270 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000271 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000272
Daniel Veillardcf461992000-03-14 18:30:20 +0000273 /*
274 * Free up the external entities
275 */
276
277 while (ctxt->inputNr > 1)
278 xmlPopInput(ctxt);
279 xmlFreeInputStream(ctxt->input);
280 xmlFree(ctxt->inputTab);
281
282 /*
283 * Restore the parsing context of the main entity
284 */
285 ctxt->input = oldinput;
286 ctxt->inputNr = oldinputNr;
287 ctxt->inputMax = oldinputMax;
288 ctxt->inputTab = oldinputTab;
Daniel Veillardbe803962000-06-28 23:40:59 +0000289 ctxt->charset = oldcharset;
Daniel Veillardcf461992000-03-14 18:30:20 +0000290 /* ctxt->wellFormed = oldwellFormed; */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000291 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000292}
293
294/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000295 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000296 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000297 * @publicId: The public ID of the entity
298 * @systemId: The system ID of the entity
299 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000300 * The entity loader, to control the loading of external entities,
301 * the application can either:
302 * - override this resolveEntity() callback in the SAX block
303 * - or better use the xmlSetExternalEntityLoader() function to
304 * set up it's own entity resolution routine
Daniel Veillard97b58771998-10-20 06:14:16 +0000305 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000306 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000307 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000308xmlParserInputPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000309resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000310{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000311 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000312
313#ifdef DEBUG_SAX
314 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
315#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000316
Daniel Veillard686d6b62000-01-03 11:08:02 +0000317 return(xmlLoadExternalEntity((const char *) systemId,
318 (const char *) publicId, ctxt));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000319}
320
Daniel Veillard97b58771998-10-20 06:14:16 +0000321/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000322 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000323 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000324 * @name: The entity name
325 *
326 * Get an entity by name
327 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000328 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000329 */
330xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000331getEntity(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000332{
Daniel Veillard27d88741999-05-29 11:51:49 +0000333 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000334 xmlEntityPtr ret;
335
336#ifdef DEBUG_SAX
337 fprintf(stderr, "SAX.getEntity(%s)\n", name);
338#endif
339
340 ret = xmlGetDocEntity(ctxt->myDoc, name);
Daniel Veillard87b95392000-08-12 21:12:04 +0000341 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
342 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
343 /*
344 * for validation purposes we really need to fetch and
345 * parse the external entity
346 */
347 int parse;
348 xmlNodePtr children;
349
350 parse = xmlParseCtxtExternalEntity(ctxt,
351 ret->SystemID, ret->ExternalID, &children);
352 xmlAddChildList((xmlNodePtr) ret, children);
353 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000354 return(ret);
355}
356
Daniel Veillardb05deb71999-08-10 19:04:08 +0000357/**
358 * getParameterEntity:
359 * @ctx: the user data (XML parser context)
360 * @name: The entity name
361 *
362 * Get a parameter entity by name
363 *
364 * Returns the xmlEntityPtr if found.
365 */
366xmlEntityPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000367getParameterEntity(void *ctx, const xmlChar *name)
Daniel Veillardb05deb71999-08-10 19:04:08 +0000368{
369 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
370 xmlEntityPtr ret;
371
372#ifdef DEBUG_SAX
373 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
374#endif
375
376 ret = xmlGetParameterEntity(ctxt->myDoc, name);
377 return(ret);
378}
379
Daniel Veillard517752b1999-04-05 12:20:10 +0000380
381/**
382 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000383 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000384 * @name: the entity name
385 * @type: the entity type
386 * @publicId: The public ID of the entity
387 * @systemId: The system ID of the entity
388 * @content: the entity value (without processing).
389 *
390 * An entity definition has been parsed
391 */
392void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000393entityDecl(void *ctx, const xmlChar *name, int type,
394 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
Daniel Veillard517752b1999-04-05 12:20:10 +0000395{
Daniel Veillard27d88741999-05-29 11:51:49 +0000396 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000397
398#ifdef DEBUG_SAX
399 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
400 name, type, publicId, systemId, content);
401#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000402 if (ctxt->inSubset == 1)
403 xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
404 systemId, content);
405 else if (ctxt->inSubset == 2)
406 xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
407 systemId, content);
408 else {
409 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
410 ctxt->sax->error(ctxt,
411 "SAX.entityDecl(%s) called while not in subset\n", name);
412 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000413}
414
415/**
416 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000417 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000418 * @elem: the name of the element
Daniel Veillardcf461992000-03-14 18:30:20 +0000419 * @fullname: the attribute name
Daniel Veillard517752b1999-04-05 12:20:10 +0000420 * @type: the attribute type
Daniel Veillard06047432000-04-24 11:33:38 +0000421 * @def: the type of default value
422 * @defaultValue: the attribute default value
423 * @tree: the tree of enumerated value set
Daniel Veillard517752b1999-04-05 12:20:10 +0000424 *
425 * An attribute definition has been parsed
426 */
427void
Daniel Veillardcf461992000-03-14 18:30:20 +0000428attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000429 int type, int def, const xmlChar *defaultValue,
Daniel Veillard517752b1999-04-05 12:20:10 +0000430 xmlEnumerationPtr tree)
431{
Daniel Veillard27d88741999-05-29 11:51:49 +0000432 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000433 xmlAttributePtr attr;
Daniel Veillardcf461992000-03-14 18:30:20 +0000434 xmlChar *name = NULL, *prefix = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000435
436#ifdef DEBUG_SAX
437 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000438 elem, fullname, type, def, defaultValue);
Daniel Veillard517752b1999-04-05 12:20:10 +0000439#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000440 name = xmlSplitQName(ctxt, fullname, &prefix);
441 if (ctxt->inSubset == 1)
442 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000443 name, prefix, (xmlAttributeType) type,
444 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000445 else if (ctxt->inSubset == 2)
446 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000447 name, prefix, (xmlAttributeType) type,
448 (xmlAttributeDefault) def, defaultValue, tree);
Daniel Veillardcf461992000-03-14 18:30:20 +0000449 else {
450 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
451 ctxt->sax->error(ctxt,
452 "SAX.attributeDecl(%s) called while not in subset\n", name);
453 return;
454 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000455 if (attr == 0) ctxt->valid = 0;
456 if (ctxt->validate && ctxt->wellFormed &&
457 ctxt->myDoc && ctxt->myDoc->intSubset)
458 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
459 attr);
Daniel Veillardcf461992000-03-14 18:30:20 +0000460 if (prefix != NULL)
461 xmlFree(prefix);
462 if (name != NULL)
463 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000464}
465
466/**
467 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000468 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000469 * @name: the element name
470 * @type: the element type
Daniel Veillard06047432000-04-24 11:33:38 +0000471 * @content: the element value tree
Daniel Veillard517752b1999-04-05 12:20:10 +0000472 *
473 * An element definition has been parsed
474 */
475void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000476elementDecl(void *ctx, const xmlChar *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000477 xmlElementContentPtr content)
478{
Daniel Veillard27d88741999-05-29 11:51:49 +0000479 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000480 xmlElementPtr elem = NULL;
Daniel Veillard517752b1999-04-05 12:20:10 +0000481
482#ifdef DEBUG_SAX
483 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
Daniel Veillardcf461992000-03-14 18:30:20 +0000484 fullname, type);
Daniel Veillard517752b1999-04-05 12:20:10 +0000485#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000486
Daniel Veillardcf461992000-03-14 18:30:20 +0000487 if (ctxt->inSubset == 1)
488 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000489 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000490 else if (ctxt->inSubset == 2)
491 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
Daniel Veillard32bc74e2000-07-14 14:49:25 +0000492 name, (xmlElementTypeVal) type, content);
Daniel Veillardcf461992000-03-14 18:30:20 +0000493 else {
494 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
495 ctxt->sax->error(ctxt,
496 "SAX.elementDecl(%s) called while not in subset\n", name);
497 return;
498 }
499 if (elem == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000500 if (ctxt->validate && ctxt->wellFormed &&
501 ctxt->myDoc && ctxt->myDoc->intSubset)
502 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000503}
504
505/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000506 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000507 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000508 * @name: The name of the notation
509 * @publicId: The public ID of the entity
510 * @systemId: The system ID of the entity
511 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000512 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000513 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000514void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000515notationDecl(void *ctx, const xmlChar *name,
516 const xmlChar *publicId, const xmlChar *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000517{
Daniel Veillard27d88741999-05-29 11:51:49 +0000518 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardcf461992000-03-14 18:30:20 +0000519 xmlNotationPtr nota = NULL;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000520
Daniel Veillard260a68f1998-08-13 03:39:55 +0000521#ifdef DEBUG_SAX
522 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
523#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000524
Daniel Veillardcf461992000-03-14 18:30:20 +0000525 if (ctxt->inSubset == 1)
526 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000527 publicId, systemId);
Daniel Veillardcf461992000-03-14 18:30:20 +0000528 else if (ctxt->inSubset == 2)
529 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
530 publicId, systemId);
531 else {
532 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
533 ctxt->sax->error(ctxt,
534 "SAX.notationDecl(%s) called while not in subset\n", name);
535 return;
536 }
537 if (nota == NULL) ctxt->valid = 0;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000538 if (ctxt->validate && ctxt->wellFormed &&
539 ctxt->myDoc && ctxt->myDoc->intSubset)
540 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
541 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000542}
543
Daniel Veillard97b58771998-10-20 06:14:16 +0000544/**
545 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000546 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000547 * @name: The name of the entity
548 * @publicId: The public ID of the entity
549 * @systemId: The system ID of the entity
550 * @notationName: the name of the notation
551 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000552 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000553 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000554void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000555unparsedEntityDecl(void *ctx, const xmlChar *name,
556 const xmlChar *publicId, const xmlChar *systemId,
557 const xmlChar *notationName)
Daniel Veillard97b58771998-10-20 06:14:16 +0000558{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000559 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000560#ifdef DEBUG_SAX
561 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
562 name, publicId, systemId, notationName);
563#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000564 if (ctxt->validate && ctxt->wellFormed &&
565 ctxt->myDoc && ctxt->myDoc->intSubset)
566 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
567 notationName);
568 xmlAddDocEntity(ctxt->myDoc, name,
569 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
570 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000571}
572
Daniel Veillard97b58771998-10-20 06:14:16 +0000573/**
574 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000575 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000576 * @loc: A SAX Locator
577 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000578 * Receive the document locator at startup, actually xmlDefaultSAXLocator
579 * Everything is available on the context, so this is useless in our case.
580 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000581void
Daniel Veillard27d88741999-05-29 11:51:49 +0000582setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000583{
Daniel Veillard27d88741999-05-29 11:51:49 +0000584 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000585#ifdef DEBUG_SAX
586 fprintf(stderr, "SAX.setDocumentLocator()\n");
587#endif
588}
589
Daniel Veillard97b58771998-10-20 06:14:16 +0000590/**
591 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000592 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000593 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000594 * called when the document start being processed.
595 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000596void
Daniel Veillard27d88741999-05-29 11:51:49 +0000597startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000598{
Daniel Veillard27d88741999-05-29 11:51:49 +0000599 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000600 xmlDocPtr doc;
601
Daniel Veillard260a68f1998-08-13 03:39:55 +0000602#ifdef DEBUG_SAX
603 fprintf(stderr, "SAX.startDocument()\n");
604#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000605 if (ctxt->html) {
606 if (ctxt->myDoc == NULL)
Daniel Veillard87b95392000-08-12 21:12:04 +0000607#ifdef LIBXML_HTML_ENABLED
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000608 ctxt->myDoc = htmlNewDoc(NULL, NULL);
Daniel Veillard87b95392000-08-12 21:12:04 +0000609#else
610 fprintf(stderr, "libxml2 built without HTML support\n");
611#endif
Daniel Veillard3f6f7f62000-06-30 17:58:25 +0000612 } else {
613 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
614 if (doc != NULL) {
615 if (ctxt->encoding != NULL)
616 doc->encoding = xmlStrdup(ctxt->encoding);
617 else
618 doc->encoding = NULL;
619 doc->standalone = ctxt->standalone;
620 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000621 }
Daniel Veillard87b95392000-08-12 21:12:04 +0000622 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
623 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
624 ctxt->myDoc->URL = xmlStrdup((xmlChar *) ctxt->input->filename);
625 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000626}
627
Daniel Veillard97b58771998-10-20 06:14:16 +0000628/**
629 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000630 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000631 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000632 * called when the document end has been detected.
633 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000634void
Daniel Veillard27d88741999-05-29 11:51:49 +0000635endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000636{
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000637 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000638#ifdef DEBUG_SAX
639 fprintf(stderr, "SAX.endDocument()\n");
640#endif
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000641 if (ctxt->validate && ctxt->wellFormed &&
642 ctxt->myDoc && ctxt->myDoc->intSubset)
643 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
Daniel Veillard496a1cf2000-05-03 14:20:55 +0000644
645 /*
646 * Grab the encoding if it was added on-the-fly
647 */
648 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
649 (ctxt->myDoc->encoding == NULL)) {
650 ctxt->myDoc->encoding = ctxt->encoding;
651 ctxt->encoding = NULL;
652 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000653 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
654 (ctxt->myDoc->encoding == NULL)) {
655 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
656 }
657 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
658 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
659 ctxt->myDoc->charset = ctxt->charset;
660 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000661}
662
Daniel Veillard97b58771998-10-20 06:14:16 +0000663/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000664 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000665 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000666 * @fullname: The attribute name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000667 * @value: The attribute value
668 *
669 * Handle an attribute that has been read by the parser.
670 * The default handling is to convert the attribute into an
671 * DOM subtree and past it in a new xmlAttr element added to
672 * the element.
673 */
674void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000675attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000676{
Daniel Veillard27d88741999-05-29 11:51:49 +0000677 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000678 xmlAttrPtr ret;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000679 xmlChar *name;
680 xmlChar *ns;
Daniel Veillardcf461992000-03-14 18:30:20 +0000681 xmlChar *nval;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000682 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000683
684/****************
685#ifdef DEBUG_SAX
686 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
687#endif
688 ****************/
689 /*
690 * Split the full name into a namespace prefix and the tag name
691 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000692 name = xmlSplitQName(ctxt, fullname, &ns);
693
694 /*
695 * Do the last stave of the attribute normalization
696 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000697 if (ctxt->html)
698 nval = NULL;
699 else
700 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
Daniel Veillardcf461992000-03-14 18:30:20 +0000701 ctxt->node, fullname, value);
702 if (nval != NULL)
703 value = nval;
Daniel Veillard517752b1999-04-05 12:20:10 +0000704
705 /*
706 * Check whether it's a namespace definition
707 */
Daniel Veillardbe803962000-06-28 23:40:59 +0000708 if ((!ctxt->html) && (ns == NULL) &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000709 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
710 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
Daniel Veillardbe803962000-06-28 23:40:59 +0000711 xmlURIPtr uri;
712
713 uri = xmlParseURI((const char *)value);
714 if (uri == NULL) {
715 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
716 ctxt->sax->warning(ctxt->userData,
717 "nmlns: %s not a valid URI\n", value);
718 } else {
719 if (uri->scheme == NULL) {
720 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
721 ctxt->sax->warning(ctxt->userData,
722 "nmlns: URI %s is not absolute\n", value);
723 }
724 xmlFreeURI(uri);
725 }
726
Daniel Veillard517752b1999-04-05 12:20:10 +0000727 /* a default namespace definition */
728 xmlNewNs(ctxt->node, value, NULL);
729 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000730 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000731 if (nval != NULL)
732 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000733 return;
734 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000735 if ((!ctxt->html) &&
736 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
Daniel Veillard517752b1999-04-05 12:20:10 +0000737 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000738 /*
739 * Validate also for namespace decls, they are attributes from
740 * an XML-1.0 perspective
741 TODO ... doesn't map well with current API
742 if (ctxt->validate && ctxt->wellFormed &&
743 ctxt->myDoc && ctxt->myDoc->intSubset)
744 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
745 ctxt->node, ret, value);
746 */
Daniel Veillard517752b1999-04-05 12:20:10 +0000747 /* a standard namespace definition */
748 xmlNewNs(ctxt->node, value, name);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000749 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000750 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000751 xmlFree(name);
Daniel Veillardcf461992000-03-14 18:30:20 +0000752 if (nval != NULL)
753 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000754 return;
755 }
756
Daniel Veillard5cb5ab81999-12-21 15:35:29 +0000757 if (ns != NULL)
758 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
759 else {
760 namespace = NULL;
761 }
762
Daniel Veillardb96e6431999-08-29 21:02:19 +0000763 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
764 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000765
Daniel Veillardb96e6431999-08-29 21:02:19 +0000766 if (ret != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000767 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
768 xmlNodePtr tmp;
769
770 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
771 tmp = ret->children;
772 while (tmp != NULL) {
773 tmp->parent = (xmlNodePtr) ret;
774 if (tmp->next == NULL)
775 ret->last = tmp;
776 tmp = tmp->next;
777 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000778 } else if (value != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000779 ret->children = xmlNewDocText(ctxt->myDoc, value);
780 ret->last = ret->children;
781 if (ret->children != NULL)
782 ret->children->parent = (xmlNodePtr) ret;
783 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000784 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000785
Daniel Veillardbe803962000-06-28 23:40:59 +0000786 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000787 ctxt->myDoc && ctxt->myDoc->intSubset) {
788
789 /*
790 * If we don't substitute entities, the validation should be
791 * done on a value with replaced entities anyway.
792 */
793 if (!ctxt->replaceEntities) {
794 xmlChar *val;
795
796 ctxt->depth++;
797 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
798 0,0,0);
799 ctxt->depth--;
800 if (val == NULL)
801 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
802 ctxt->myDoc, ctxt->node, ret, value);
803 else {
804 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
805 ctxt->myDoc, ctxt->node, ret, val);
806 xmlFree(val);
807 }
808 } else {
809 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
Daniel Veillardb05deb71999-08-10 19:04:08 +0000810 ctxt->node, ret, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000811 }
812 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000813 /*
814 * when validating, the ID registration is done at the attribute
815 * validation level. Otherwise we have to do specific handling here.
816 */
817 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
818 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000819 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
820 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000821 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000822
Daniel Veillardcf461992000-03-14 18:30:20 +0000823 if (nval != NULL)
824 xmlFree(nval);
Daniel Veillard517752b1999-04-05 12:20:10 +0000825 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000826 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000827 if (ns != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000828 xmlFree(ns);
Daniel Veillard517752b1999-04-05 12:20:10 +0000829}
830
831/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000832 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000833 * @ctx: the user data (XML parser context)
Daniel Veillard06047432000-04-24 11:33:38 +0000834 * @fullname: The element name, including namespace prefix
Daniel Veillard517752b1999-04-05 12:20:10 +0000835 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000836 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000837 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000838 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000839void
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000840startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000841{
Daniel Veillard27d88741999-05-29 11:51:49 +0000842 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000843 xmlNodePtr ret;
844 xmlNodePtr parent = ctxt->node;
845 xmlNsPtr ns;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000846 xmlChar *name;
847 xmlChar *prefix;
848 const xmlChar *att;
849 const xmlChar *value;
Daniel Veillard517752b1999-04-05 12:20:10 +0000850 int i;
851
Daniel Veillard260a68f1998-08-13 03:39:55 +0000852#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000853 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000854#endif
Daniel Veillard7f7d1111999-09-22 09:46:25 +0000855
856 /*
857 * First check on validity:
858 */
859 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
860 ((ctxt->myDoc->intSubset == NULL) ||
861 ((ctxt->myDoc->intSubset->notations == NULL) &&
862 (ctxt->myDoc->intSubset->elements == NULL) &&
863 (ctxt->myDoc->intSubset->attributes == NULL) &&
864 (ctxt->myDoc->intSubset->entities == NULL)))) {
865 if (ctxt->vctxt.error != NULL) {
866 ctxt->vctxt.error(ctxt->vctxt.userData,
867 "Validation failed: no DTD found !\n");
868 }
869 ctxt->validate = 0;
870 }
871
872
Daniel Veillard517752b1999-04-05 12:20:10 +0000873 /*
874 * Split the full name into a namespace prefix and the tag name
875 */
Daniel Veillardcf461992000-03-14 18:30:20 +0000876 name = xmlSplitQName(ctxt, fullname, &prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000877
878
879 /*
880 * Note : the namespace resolution is deferred until the end of the
881 * attributes parsing, since local namespace can be defined as
882 * an attribute at this level.
883 */
884 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
885 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000886 if (ctxt->myDoc->children == NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000887#ifdef DEBUG_SAX_TREE
888 fprintf(stderr, "Setting %s as root\n", name);
889#endif
Daniel Veillardcf461992000-03-14 18:30:20 +0000890 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000891 } else if (parent == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +0000892 parent = ctxt->myDoc->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000893 }
Daniel Veillardbe803962000-06-28 23:40:59 +0000894 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +0000895
896 /*
897 * We are parsing a new node.
898 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000899#ifdef DEBUG_SAX_TREE
900 fprintf(stderr, "pushing(%s)\n", name);
901#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000902 nodePush(ctxt, ret);
903
904 /*
905 * Link the child element
906 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000907 if (parent != NULL) {
908 if (parent->type == XML_ELEMENT_NODE) {
909#ifdef DEBUG_SAX_TREE
910 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
911#endif
912 xmlAddChild(parent, ret);
913 } else {
914#ifdef DEBUG_SAX_TREE
915 fprintf(stderr, "adding sibling %s to ", name);
916 xmlDebugDumpOneNode(stderr, parent, 0);
917#endif
918 xmlAddSibling(parent, ret);
919 }
920 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000921
922 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000923 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000924 */
925 if (atts != NULL) {
926 i = 0;
927 att = atts[i++];
928 value = atts[i++];
Daniel Veillardbe803962000-06-28 23:40:59 +0000929 if (!ctxt->html) {
930 while ((att != NULL) && (value != NULL)) {
931 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
932 attribute(ctxt, att, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000933
Daniel Veillardbe803962000-06-28 23:40:59 +0000934 att = atts[i++];
935 value = atts[i++];
936 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000937 }
938 }
939
940 /*
941 * Search the namespace, note that since the attributes have been
942 * processed, the local namespaces are available.
943 */
944 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
945 if ((ns == NULL) && (parent != NULL))
946 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
947 xmlSetNs(ret, ns);
948
Daniel Veillardbe803962000-06-28 23:40:59 +0000949 /*
950 * process all the other attributes
951 */
952 if (atts != NULL) {
953 i = 0;
954 att = atts[i++];
955 value = atts[i++];
956 if (ctxt->html) {
957 while (att != NULL) {
958 attribute(ctxt, att, value);
959 att = atts[i++];
960 value = atts[i++];
961 }
962 } else {
963 while ((att != NULL) && (value != NULL)) {
964 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
965 attribute(ctxt, att, value);
966
967 /*
968 * Next ones
969 */
970 att = atts[i++];
971 value = atts[i++];
972 }
973 }
974 }
975
976 /*
977 * If it's the Document root, finish the Dtd validation and
978 * check the document root element for validity
979 */
980 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
981 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
982 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
983 ctxt->vctxt.finishDtd = 1;
984 }
985
Daniel Veillard517752b1999-04-05 12:20:10 +0000986 if (prefix != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000987 xmlFree(prefix);
Daniel Veillard517752b1999-04-05 12:20:10 +0000988 if (name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +0000989 xmlFree(name);
Daniel Veillard517752b1999-04-05 12:20:10 +0000990
Daniel Veillard260a68f1998-08-13 03:39:55 +0000991}
992
Daniel Veillard97b58771998-10-20 06:14:16 +0000993/**
994 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000995 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000996 * @name: The element name
997 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000998 * called when the end of an element has been detected.
999 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001000void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001001endElement(void *ctx, const xmlChar *name)
Daniel Veillard97b58771998-10-20 06:14:16 +00001002{
Daniel Veillard27d88741999-05-29 11:51:49 +00001003 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001004 xmlParserNodeInfo node_info;
1005 xmlNodePtr cur = ctxt->node;
1006
Daniel Veillard260a68f1998-08-13 03:39:55 +00001007#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001008 if (name == NULL)
1009 fprintf(stderr, "SAX.endElement(NULL)\n");
1010 else
1011 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001012#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001013
1014 /* Capture end position and add node */
1015 if (cur != NULL && ctxt->record_info) {
1016 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1017 node_info.end_line = ctxt->input->line;
1018 node_info.node = cur;
1019 xmlParserAddNodeInfo(ctxt, &node_info);
1020 }
Daniel Veillardbe803962000-06-28 23:40:59 +00001021 ctxt->nodemem = -1;
Daniel Veillard517752b1999-04-05 12:20:10 +00001022
Daniel Veillardb05deb71999-08-10 19:04:08 +00001023 if (ctxt->validate && ctxt->wellFormed &&
1024 ctxt->myDoc && ctxt->myDoc->intSubset)
1025 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1026 cur);
1027
1028
Daniel Veillard517752b1999-04-05 12:20:10 +00001029 /*
1030 * end of parsing of this node.
1031 */
Daniel Veillardb96e6431999-08-29 21:02:19 +00001032#ifdef DEBUG_SAX_TREE
1033 fprintf(stderr, "popping(%s)\n", cur->name);
1034#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001035 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001036}
1037
Daniel Veillard97b58771998-10-20 06:14:16 +00001038/**
Daniel Veillard517752b1999-04-05 12:20:10 +00001039 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001040 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001041 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +00001042 *
Daniel Veillard517752b1999-04-05 12:20:10 +00001043 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +00001044 */
1045void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001046reference(void *ctx, const xmlChar *name)
Daniel Veillard11e00581998-10-24 18:27:49 +00001047{
Daniel Veillard27d88741999-05-29 11:51:49 +00001048 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001049 xmlNodePtr ret;
1050
Daniel Veillard11e00581998-10-24 18:27:49 +00001051#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001052 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +00001053#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001054 if (name[0] == '#')
1055 ret = xmlNewCharRef(ctxt->myDoc, name);
1056 else
1057 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001058#ifdef DEBUG_SAX_TREE
1059 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
1060#endif
Daniel Veillard517752b1999-04-05 12:20:10 +00001061 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +00001062}
1063
1064/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001065 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001066 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001067 * @ch: a xmlChar string
1068 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001069 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001070 * receiving some chars from the parser.
1071 * Question: how much at a time ???
1072 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001073void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001074characters(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001075{
Daniel Veillard27d88741999-05-29 11:51:49 +00001076 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001077 xmlNodePtr lastChild;
1078
1079#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001080 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001081#endif
1082 /*
1083 * Handle the data if any. If there is no child
1084 * add it as content, otherwise if the last child is text,
1085 * concatenate it, else create a new node of type text.
1086 */
1087
Daniel Veillard35008381999-10-25 13:15:52 +00001088 if (ctxt->node == NULL) {
1089#ifdef DEBUG_SAX_TREE
1090 fprintf(stderr, "add chars: ctxt->node == NULL !\n");
1091#endif
1092 return;
1093 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001094 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001095#ifdef DEBUG_SAX_TREE
1096 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1097#endif
Daniel Veillardbe803962000-06-28 23:40:59 +00001098
1099 /*
1100 * Here we needed an accelerator mechanism in case of very large
1101 * elements. Use an attribute in the structure !!!
1102 */
1103 if (lastChild == NULL) {
1104 /* first node, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001105 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001106#ifndef XML_USE_BUFFER_CONTENT
1107 if (ctxt->node->children != NULL) {
1108 ctxt->nodelen = len;
1109 ctxt->nodemem = len + 1;
1110 }
1111#endif
1112 } else {
1113 if (xmlNodeIsText(lastChild)) {
1114#ifndef XML_USE_BUFFER_CONTENT
1115 /*
1116 * The whole point of maintaining nodelen and nodemem,
1117 * xmlTextConcat is too costly, i.e. compute lenght,
1118 * reallocate a new buffer, move data, append ch. Here
1119 * We try to minimaze realloc() uses and avoid copying
1120 * and recomputing lenght over and over.
1121 */
1122 if (ctxt->nodelen + len >= ctxt->nodemem) {
1123 xmlChar *newbuf;
1124 int size;
1125
1126 size = ctxt->nodemem + len;
1127 size *= 2;
1128 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1129 if (newbuf == NULL) {
1130 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1131 ctxt->sax->error(ctxt->userData,
1132 "SAX.characters(): out of memory\n");
1133 return;
1134 }
1135 ctxt->nodemem = size;
1136 lastChild->content = newbuf;
1137 }
1138 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1139 ctxt->nodelen += len;
1140 lastChild->content[ctxt->nodelen] = 0;
1141#else
Daniel Veillard517752b1999-04-05 12:20:10 +00001142 xmlTextConcat(lastChild, ch, len);
Daniel Veillardbe803962000-06-28 23:40:59 +00001143#endif
1144 } else {
1145 /* Mixed content, first time */
Daniel Veillard517752b1999-04-05 12:20:10 +00001146 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001147 xmlAddChild(ctxt->node, lastChild);
Daniel Veillardbe803962000-06-28 23:40:59 +00001148#ifndef XML_USE_BUFFER_CONTENT
1149 if (ctxt->node->children != NULL) {
1150 ctxt->nodelen = len;
1151 ctxt->nodemem = len + 1;
1152 }
1153#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001154 }
1155 }
1156}
1157
Daniel Veillard97b58771998-10-20 06:14:16 +00001158/**
1159 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001160 * @ctx: the user data (XML parser context)
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001161 * @ch: a xmlChar string
1162 * @len: the number of xmlChar
Daniel Veillard97b58771998-10-20 06:14:16 +00001163 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00001164 * receiving some ignorable whitespaces from the parser.
1165 * Question: how much at a time ???
1166 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001167void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001168ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +00001169{
Daniel Veillard27d88741999-05-29 11:51:49 +00001170 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001171#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +00001172 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001173#endif
1174}
1175
Daniel Veillard97b58771998-10-20 06:14:16 +00001176/**
1177 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001178 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +00001179 * @target: the target name
1180 * @data: the PI data's
Daniel Veillard97b58771998-10-20 06:14:16 +00001181 *
1182 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001183 */
Daniel Veillard97b58771998-10-20 06:14:16 +00001184void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001185processingInstruction(void *ctx, const xmlChar *target,
1186 const xmlChar *data)
Daniel Veillard97b58771998-10-20 06:14:16 +00001187{
Daniel Veillardb96e6431999-08-29 21:02:19 +00001188 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1189 xmlNodePtr ret;
1190 xmlNodePtr parent = ctxt->node;
1191
Daniel Veillard260a68f1998-08-13 03:39:55 +00001192#ifdef DEBUG_SAX
1193 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
1194#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001195
1196 ret = xmlNewPI(target, data);
1197 if (ret == NULL) return;
Daniel Veillardcf461992000-03-14 18:30:20 +00001198 parent = ctxt->node;
1199
1200 if (ctxt->inSubset == 1) {
1201 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1202 return;
1203 } else if (ctxt->inSubset == 2) {
1204 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1205 return;
1206 }
1207 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001208#ifdef DEBUG_SAX_TREE
1209 fprintf(stderr, "Setting PI %s as root\n", target);
1210#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001211 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1212 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001213 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001214 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001215#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001216 fprintf(stderr, "adding PI %s child to %s\n", target, parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001217#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001218 xmlAddChild(parent, ret);
1219 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001220#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001221 fprintf(stderr, "adding PI %s sibling to ", target);
1222 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001223#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001224 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001225 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001226}
1227
Daniel Veillard517752b1999-04-05 12:20:10 +00001228/**
1229 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001230 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001231 * @href: the namespace associated URN
1232 * @prefix: the namespace prefix
1233 *
1234 * An old global namespace has been parsed.
1235 */
1236void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001237globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001238{
Daniel Veillard27d88741999-05-29 11:51:49 +00001239 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001240#ifdef DEBUG_SAX
1241 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
1242#endif
1243 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1244}
1245
1246/**
1247 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001248 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001249 * @name: the namespace prefix
1250 *
1251 * Set the current element namespace.
1252 */
Daniel Veillard06047432000-04-24 11:33:38 +00001253
Daniel Veillard517752b1999-04-05 12:20:10 +00001254void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001255setNamespace(void *ctx, const xmlChar *name)
Daniel Veillard517752b1999-04-05 12:20:10 +00001256{
Daniel Veillard27d88741999-05-29 11:51:49 +00001257 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001258 xmlNsPtr ns;
1259 xmlNodePtr parent;
1260
1261#ifdef DEBUG_SAX
1262 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
1263#endif
1264 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1265 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1266 if (ctxt->nodeNr >= 2) {
1267 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1268 if (parent != NULL)
1269 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1270 }
1271 }
1272 xmlSetNs(ctxt->node, ns);
1273}
1274
1275/**
1276 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001277 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001278 *
1279 * Get the current element namespace.
Daniel Veillard06047432000-04-24 11:33:38 +00001280 *
1281 * Returns the xmlNsPtr or NULL if none
Daniel Veillard517752b1999-04-05 12:20:10 +00001282 */
Daniel Veillard06047432000-04-24 11:33:38 +00001283
Daniel Veillard517752b1999-04-05 12:20:10 +00001284xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +00001285getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +00001286{
Daniel Veillard27d88741999-05-29 11:51:49 +00001287 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001288 xmlNsPtr ret;
1289
1290#ifdef DEBUG_SAX
1291 fprintf(stderr, "SAX.getNamespace()\n");
1292#endif
1293 ret = ctxt->node->ns;
1294 return(ret);
1295}
1296
1297/**
1298 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001299 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001300 * @namespace: the namespace to check against
1301 *
1302 * Check that the current element namespace is the same as the
1303 * one read upon parsing.
Daniel Veillard06047432000-04-24 11:33:38 +00001304 *
1305 * Returns 1 if true 0 otherwise
Daniel Veillard517752b1999-04-05 12:20:10 +00001306 */
Daniel Veillard06047432000-04-24 11:33:38 +00001307
Daniel Veillard517752b1999-04-05 12:20:10 +00001308int
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001309checkNamespace(void *ctx, xmlChar *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +00001310{
Daniel Veillard27d88741999-05-29 11:51:49 +00001311 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001312 xmlNodePtr cur = ctxt->node;
1313
1314#ifdef DEBUG_SAX
1315 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
1316#endif
1317
1318 /*
1319 * Check that the Name in the ETag is the same as in the STag.
1320 */
1321 if (namespace == NULL) {
1322 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1323 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1324 ctxt->sax->error(ctxt,
1325 "End tags for %s don't hold the namespace %s\n",
1326 cur->name, cur->ns->prefix);
1327 ctxt->wellFormed = 0;
1328 }
1329 } else {
1330 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1331 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1332 ctxt->sax->error(ctxt,
1333 "End tags %s holds a prefix %s not used by the open tag\n",
1334 cur->name, namespace);
1335 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001336 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +00001337 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1338 ctxt->sax->error(ctxt,
1339 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1340 cur->name, cur->ns->prefix, namespace);
1341 ctxt->wellFormed = 0;
1342 } else
1343 return(1);
1344 }
1345 return(0);
1346}
1347
1348/**
1349 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001350 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001351 * @href: the namespace associated URN
1352 * @prefix: the namespace prefix
1353 *
1354 * A namespace has been parsed.
1355 */
1356void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001357namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001358{
Daniel Veillard27d88741999-05-29 11:51:49 +00001359 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001360#ifdef DEBUG_SAX
1361 if (prefix == NULL)
1362 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1363 else
1364 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1365#endif
1366 xmlNewNs(ctxt->node, href, prefix);
1367}
1368
1369/**
1370 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001371 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001372 * @value: the comment content
1373 *
1374 * A comment has been parsed.
1375 */
1376void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001377comment(void *ctx, const xmlChar *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001378{
Daniel Veillard27d88741999-05-29 11:51:49 +00001379 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001380 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001381 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001382
Daniel Veillard517752b1999-04-05 12:20:10 +00001383#ifdef DEBUG_SAX
1384 fprintf(stderr, "SAX.comment(%s)\n", value);
1385#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001386 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001387 if (ret == NULL) return;
1388
Daniel Veillardcf461992000-03-14 18:30:20 +00001389 if (ctxt->inSubset == 1) {
1390 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1391 return;
1392 } else if (ctxt->inSubset == 2) {
1393 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1394 return;
1395 }
1396 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001397#ifdef DEBUG_SAX_TREE
1398 fprintf(stderr, "Setting comment as root\n");
1399#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001400 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1401 return;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001402 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001403 if (parent->type == XML_ELEMENT_NODE) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001404#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001405 fprintf(stderr, "adding comment child to %s\n", parent->name);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001406#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001407 xmlAddChild(parent, ret);
1408 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001409#ifdef DEBUG_SAX_TREE
Daniel Veillardcf461992000-03-14 18:30:20 +00001410 fprintf(stderr, "adding comment sibling to ");
1411 xmlDebugDumpOneNode(stderr, parent, 0);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001412#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001413 xmlAddSibling(parent, ret);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001414 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001415}
1416
1417/**
1418 * cdataBlock:
1419 * @ctx: the user data (XML parser context)
1420 * @value: The pcdata content
1421 * @len: the block length
1422 *
1423 * called when a pcdata block has been parsed
1424 */
1425void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001426cdataBlock(void *ctx, const xmlChar *value, int len)
Daniel Veillardb05deb71999-08-10 19:04:08 +00001427{
1428 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001429 xmlNodePtr ret, lastChild;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001430
1431#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001432 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001433#endif
Daniel Veillarddbfd6411999-12-28 16:35:14 +00001434 lastChild = xmlGetLastChild(ctxt->node);
1435#ifdef DEBUG_SAX_TREE
1436 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
1437#endif
1438 if ((lastChild != NULL) &&
1439 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1440 xmlTextConcat(lastChild, value, len);
1441 } else {
1442 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1443 xmlAddChild(ctxt->node, ret);
1444 }
Daniel Veillard517752b1999-04-05 12:20:10 +00001445}
1446
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001447/*
1448 * Default handler for XML, builds the DOM tree
1449 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001450xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001451 internalSubset,
1452 isStandalone,
1453 hasInternalSubset,
1454 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001455 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001456 getEntity,
1457 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001458 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001459 attributeDecl,
1460 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001461 unparsedEntityDecl,
1462 setDocumentLocator,
1463 startDocument,
1464 endDocument,
1465 startElement,
1466 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001467 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001468 characters,
1469 ignorableWhitespace,
1470 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001471 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001472 xmlParserWarning,
1473 xmlParserError,
1474 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001475 getParameterEntity,
1476 cdataBlock,
Daniel Veillardcf461992000-03-14 18:30:20 +00001477 externalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001478};
1479
Daniel Veillard97b58771998-10-20 06:14:16 +00001480/**
1481 * xmlDefaultSAXHandlerInit:
1482 *
1483 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001484 */
1485void
1486xmlDefaultSAXHandlerInit(void)
1487{
Daniel Veillard517752b1999-04-05 12:20:10 +00001488 xmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001489 xmlDefaultSAXHandler.externalSubset = externalSubset;
Daniel Veillard517752b1999-04-05 12:20:10 +00001490 xmlDefaultSAXHandler.isStandalone = isStandalone;
1491 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1492 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001493 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001494 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001495 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001496 xmlDefaultSAXHandler.entityDecl = entityDecl;
1497 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1498 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001499 xmlDefaultSAXHandler.notationDecl = notationDecl;
1500 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1501 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1502 xmlDefaultSAXHandler.startDocument = startDocument;
1503 xmlDefaultSAXHandler.endDocument = endDocument;
1504 xmlDefaultSAXHandler.startElement = startElement;
1505 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001506 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001507 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001508 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001509 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1510 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001511 xmlDefaultSAXHandler.comment = comment;
Daniel Veillardcf461992000-03-14 18:30:20 +00001512 if (xmlGetWarningsDefaultValue == 0)
1513 xmlDefaultSAXHandler.warning = NULL;
1514 else
1515 xmlDefaultSAXHandler.warning = xmlParserWarning;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001516 xmlDefaultSAXHandler.error = xmlParserError;
1517 xmlDefaultSAXHandler.fatalError = xmlParserError;
1518}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001519
1520/*
1521 * Default handler for HTML, builds the DOM tree
1522 */
1523xmlSAXHandler htmlDefaultSAXHandler = {
Daniel Veillardd83eb822000-06-30 18:39:56 +00001524 internalSubset,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001525 NULL,
1526 NULL,
1527 NULL,
1528 NULL,
1529 getEntity,
1530 NULL,
1531 NULL,
1532 NULL,
1533 NULL,
1534 NULL,
1535 setDocumentLocator,
1536 startDocument,
1537 endDocument,
1538 startElement,
1539 endElement,
1540 NULL,
1541 characters,
1542 ignorableWhitespace,
1543 NULL,
1544 comment,
1545 xmlParserWarning,
1546 xmlParserError,
1547 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001548 getParameterEntity,
1549 NULL,
Daniel Veillardcf461992000-03-14 18:30:20 +00001550 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001551};
1552
1553/**
1554 * htmlDefaultSAXHandlerInit:
1555 *
1556 * Initialize the default SAX handler
1557 */
1558void
1559htmlDefaultSAXHandlerInit(void)
1560{
Daniel Veillardd83eb822000-06-30 18:39:56 +00001561 htmlDefaultSAXHandler.internalSubset = internalSubset;
Daniel Veillardcf461992000-03-14 18:30:20 +00001562 htmlDefaultSAXHandler.externalSubset = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001563 htmlDefaultSAXHandler.isStandalone = NULL;
1564 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1565 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1566 htmlDefaultSAXHandler.resolveEntity = NULL;
1567 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001568 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001569 htmlDefaultSAXHandler.entityDecl = NULL;
1570 htmlDefaultSAXHandler.attributeDecl = NULL;
1571 htmlDefaultSAXHandler.elementDecl = NULL;
1572 htmlDefaultSAXHandler.notationDecl = NULL;
1573 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1574 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1575 htmlDefaultSAXHandler.startDocument = startDocument;
1576 htmlDefaultSAXHandler.endDocument = endDocument;
1577 htmlDefaultSAXHandler.startElement = startElement;
1578 htmlDefaultSAXHandler.endElement = endElement;
1579 htmlDefaultSAXHandler.reference = NULL;
1580 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001581 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001582 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1583 htmlDefaultSAXHandler.processingInstruction = NULL;
1584 htmlDefaultSAXHandler.comment = comment;
1585 htmlDefaultSAXHandler.warning = xmlParserWarning;
1586 htmlDefaultSAXHandler.error = xmlParserError;
1587 htmlDefaultSAXHandler.fatalError = xmlParserError;
1588}