blob: 60e6ff8543aac7971dac3f47e0523a201e54d016 [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
9#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000010#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000011#include "tree.h"
12#include "parser.h"
Daniel Veillard517752b1999-04-05 12:20:10 +000013#include "parserInternals.h"
14#include "valid.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000015#include "entities.h"
Daniel Veillardd109e371999-03-05 06:26:45 +000016#include "xml-error.h"
Daniel Veillardb96e6431999-08-29 21:02:19 +000017#include "debugXML.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000018
19/* #define DEBUG_SAX */
Daniel Veillardb96e6431999-08-29 21:02:19 +000020/* #define DEBUG_SAX_TREE */
Daniel Veillard260a68f1998-08-13 03:39:55 +000021
Daniel Veillard97b58771998-10-20 06:14:16 +000022/**
23 * getPublicId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000024 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000025 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000026 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000027 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000028 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000029 */
Daniel Veillard97b58771998-10-20 06:14:16 +000030const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000031getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000032{
Daniel Veillard27d88741999-05-29 11:51:49 +000033 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000034 return(NULL);
35}
36
Daniel Veillard97b58771998-10-20 06:14:16 +000037/**
38 * getSystemId:
Daniel Veillard011b63c1999-06-02 17:44:04 +000039 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000040 *
Daniel Veillard011b63c1999-06-02 17:44:04 +000041 * Return the system ID, basically URL or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000042 * http://www.sgmlsource.com/dtds/memo.dtd
43 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000044 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000045 */
Daniel Veillard97b58771998-10-20 06:14:16 +000046const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000047getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000048{
Daniel Veillard27d88741999-05-29 11:51:49 +000049 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb96e6431999-08-29 21:02:19 +000050 return(BAD_CAST ctxt->input->filename);
Daniel Veillard260a68f1998-08-13 03:39:55 +000051}
52
Daniel Veillard97b58771998-10-20 06:14:16 +000053/**
54 * getLineNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000055 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000056 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000057 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000058 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000059 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000060 */
Daniel Veillard97b58771998-10-20 06:14:16 +000061int
Daniel Veillard27d88741999-05-29 11:51:49 +000062getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000063{
Daniel Veillard27d88741999-05-29 11:51:49 +000064 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000065 return(ctxt->input->line);
66}
Daniel Veillard97b58771998-10-20 06:14:16 +000067
68/**
69 * getColumnNumber:
Daniel Veillard011b63c1999-06-02 17:44:04 +000070 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +000071 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000072 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000073 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000074 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000075 */
Daniel Veillard97b58771998-10-20 06:14:16 +000076int
Daniel Veillard27d88741999-05-29 11:51:49 +000077getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000078{
Daniel Veillard27d88741999-05-29 11:51:49 +000079 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000080 return(ctxt->input->col);
81}
82
83/*
84 * The default SAX Locator.
85 */
86
87xmlSAXLocator xmlDefaultSAXLocator = {
88 getPublicId, getSystemId, getLineNumber, getColumnNumber
89};
90
Daniel Veillard97b58771998-10-20 06:14:16 +000091/**
Daniel Veillard517752b1999-04-05 12:20:10 +000092 * isStandalone:
Daniel Veillard011b63c1999-06-02 17:44:04 +000093 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +000094 *
95 * Is this document tagged standalone ?
96 *
97 * Returns 1 if true
98 */
99int
Daniel Veillard27d88741999-05-29 11:51:49 +0000100isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000101{
Daniel Veillard27d88741999-05-29 11:51:49 +0000102 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000103 return(ctxt->myDoc->standalone == 1);
104}
105
106/**
107 * hasInternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000108 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000109 *
110 * Does this document has an internal subset
111 *
112 * Returns 1 if true
113 */
114int
Daniel Veillard27d88741999-05-29 11:51:49 +0000115hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000116{
Daniel Veillard27d88741999-05-29 11:51:49 +0000117 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000118 return(ctxt->myDoc->intSubset != NULL);
119}
120
121/**
122 * hasExternalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000123 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000124 *
125 * Does this document has an external subset
126 *
127 * Returns 1 if true
128 */
129int
Daniel Veillard27d88741999-05-29 11:51:49 +0000130hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000131{
Daniel Veillard27d88741999-05-29 11:51:49 +0000132 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000133 return(ctxt->myDoc->extSubset != NULL);
134}
135
136/**
Daniel Veillardb05deb71999-08-10 19:04:08 +0000137 * internalSubset:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000138 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000139 *
140 * Does this document has an internal subset
141 */
142void
Daniel Veillard27d88741999-05-29 11:51:49 +0000143internalSubset(void *ctx, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000144 const CHAR *ExternalID, const CHAR *SystemID)
145{
Daniel Veillard27d88741999-05-29 11:51:49 +0000146 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000147#ifdef DEBUG_SAX
148 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
149 name, ExternalID, SystemID);
150#endif
151 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000152 if (((ExternalID != NULL) || (SystemID != NULL)) &&
153 (ctxt->validate && ctxt->wellFormed && ctxt->myDoc)) {
154 /*
155 * Try to fetch and parse the external subset.
156 */
157 xmlDtdPtr ret = NULL;
158 xmlParserCtxtPtr dtdCtxt;
159 xmlParserInputPtr input = NULL;
160 xmlCharEncoding enc;
161
162 dtdCtxt = xmlNewParserCtxt();
163 if (dtdCtxt == NULL) return;
164
165 /*
166 * Ask the Entity resolver to load the damn thing
167 */
168 if ((ctxt->directory != NULL) && (dtdCtxt->directory == NULL))
Daniel Veillardb96e6431999-08-29 21:02:19 +0000169 dtdCtxt->directory = (char *) xmlStrdup(BAD_CAST ctxt->directory);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000170
171 if ((dtdCtxt->sax != NULL) && (dtdCtxt->sax->resolveEntity != NULL))
172 input = dtdCtxt->sax->resolveEntity(dtdCtxt->userData, ExternalID,
173 SystemID);
174 if (input == NULL) {
175 xmlFreeParserCtxt(dtdCtxt);
176 return;
177 }
178
179 /*
180 * plug some encoding conversion routines here. !!!
181 */
182 xmlPushInput(dtdCtxt, input);
183 enc = xmlDetectCharEncoding(dtdCtxt->input->cur);
184 xmlSwitchEncoding(dtdCtxt, enc);
185
186 if (input->filename == NULL)
Daniel Veillardb96e6431999-08-29 21:02:19 +0000187 input->filename = (char *) xmlStrdup(SystemID);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000188 input->line = 1;
189 input->col = 1;
190 input->base = dtdCtxt->input->cur;
191 input->cur = dtdCtxt->input->cur;
192 input->free = NULL;
193
194 /*
195 * let's parse that entity knowing it's an external subset.
196 */
197 xmlParseExternalSubset(dtdCtxt, ExternalID, SystemID);
198
199 if (dtdCtxt->myDoc != NULL) {
200 if (dtdCtxt->wellFormed) {
201 ret = dtdCtxt->myDoc->intSubset;
202 dtdCtxt->myDoc->intSubset = NULL;
203 } else {
204 ret = NULL;
205 }
206 xmlFreeDoc(dtdCtxt->myDoc);
207 dtdCtxt->myDoc = NULL;
208 }
209 xmlFreeParserCtxt(dtdCtxt);
210
211 ctxt->myDoc->extSubset = ret;
Daniel Veillard011b63c1999-06-02 17:44:04 +0000212 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000213}
214
215/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000216 * resolveEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000217 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000218 * @publicId: The public ID of the entity
219 * @systemId: The system ID of the entity
220 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000221 * Special entity resolver, better left to the parser, it has
222 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000223 * The default behaviour is to NOT resolve the entities, in that case
224 * the ENTITY_REF nodes are built in the structure (and the parameter
225 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000226 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000227 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000228 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000229xmlParserInputPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000230resolveEntity(void *ctx, const CHAR *publicId, const CHAR *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000231{
Daniel Veillard011b63c1999-06-02 17:44:04 +0000232 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000233
234#ifdef DEBUG_SAX
235 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
236#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000237
Daniel Veillard517752b1999-04-05 12:20:10 +0000238 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000239 * TODO : resolveEntity, handling of http://.. or ftp://..
Daniel Veillard517752b1999-04-05 12:20:10 +0000240 */
Daniel Veillard011b63c1999-06-02 17:44:04 +0000241 if (systemId != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000242 if (!xmlStrncmp(systemId, BAD_CAST "http://", 7)) {
243 } else if (!xmlStrncmp(systemId, BAD_CAST "ftp://", 6)) {
Daniel Veillard5233ffc1999-07-06 22:25:25 +0000244 } else {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000245 return(xmlNewInputFromFile(ctxt, (char *) systemId));
Daniel Veillard5233ffc1999-07-06 22:25:25 +0000246 }
Daniel Veillard011b63c1999-06-02 17:44:04 +0000247 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000248 return(NULL);
249}
250
Daniel Veillard97b58771998-10-20 06:14:16 +0000251/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000252 * getEntity:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000253 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000254 * @name: The entity name
255 *
256 * Get an entity by name
257 *
Daniel Veillard011b63c1999-06-02 17:44:04 +0000258 * Returns the xmlEntityPtr if found.
Daniel Veillard517752b1999-04-05 12:20:10 +0000259 */
260xmlEntityPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000261getEntity(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000262{
Daniel Veillard27d88741999-05-29 11:51:49 +0000263 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000264 xmlEntityPtr ret;
265
266#ifdef DEBUG_SAX
267 fprintf(stderr, "SAX.getEntity(%s)\n", name);
268#endif
269
270 ret = xmlGetDocEntity(ctxt->myDoc, name);
271 return(ret);
272}
273
Daniel Veillardb05deb71999-08-10 19:04:08 +0000274/**
275 * getParameterEntity:
276 * @ctx: the user data (XML parser context)
277 * @name: The entity name
278 *
279 * Get a parameter entity by name
280 *
281 * Returns the xmlEntityPtr if found.
282 */
283xmlEntityPtr
284getParameterEntity(void *ctx, const CHAR *name)
285{
286 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
287 xmlEntityPtr ret;
288
289#ifdef DEBUG_SAX
290 fprintf(stderr, "SAX.getParameterEntity(%s)\n", name);
291#endif
292
293 ret = xmlGetParameterEntity(ctxt->myDoc, name);
294 return(ret);
295}
296
Daniel Veillard517752b1999-04-05 12:20:10 +0000297
298/**
299 * entityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000300 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000301 * @name: the entity name
302 * @type: the entity type
303 * @publicId: The public ID of the entity
304 * @systemId: The system ID of the entity
305 * @content: the entity value (without processing).
306 *
307 * An entity definition has been parsed
308 */
309void
Daniel Veillard27d88741999-05-29 11:51:49 +0000310entityDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000311 const CHAR *publicId, const CHAR *systemId, CHAR *content)
312{
Daniel Veillard27d88741999-05-29 11:51:49 +0000313 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000314
315#ifdef DEBUG_SAX
316 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
317 name, type, publicId, systemId, content);
318#endif
319 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
320}
321
322/**
323 * attributeDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000324 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000325 * @name: the attribute name
326 * @type: the attribute type
327 * @publicId: The public ID of the attribute
328 * @systemId: The system ID of the attribute
329 * @content: the attribute value (without processing).
330 *
331 * An attribute definition has been parsed
332 */
333void
Daniel Veillard27d88741999-05-29 11:51:49 +0000334attributeDecl(void *ctx, const CHAR *elem, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000335 int type, int def, const CHAR *defaultValue,
336 xmlEnumerationPtr tree)
337{
Daniel Veillard27d88741999-05-29 11:51:49 +0000338 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000339 xmlAttributePtr attr;
Daniel Veillard517752b1999-04-05 12:20:10 +0000340
341#ifdef DEBUG_SAX
342 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
343 elem, name, type, def, defaultValue);
344#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000345 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
346 name, type, def, defaultValue, tree);
347 if (attr == 0) ctxt->valid = 0;
348 if (ctxt->validate && ctxt->wellFormed &&
349 ctxt->myDoc && ctxt->myDoc->intSubset)
350 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
351 attr);
Daniel Veillard517752b1999-04-05 12:20:10 +0000352}
353
354/**
355 * elementDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000356 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000357 * @name: the element name
358 * @type: the element type
359 * @publicId: The public ID of the element
360 * @systemId: The system ID of the element
361 * @content: the element value (without processing).
362 *
363 * An element definition has been parsed
364 */
365void
Daniel Veillard27d88741999-05-29 11:51:49 +0000366elementDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000367 xmlElementContentPtr content)
368{
Daniel Veillard27d88741999-05-29 11:51:49 +0000369 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000370 xmlElementPtr elem;
Daniel Veillard517752b1999-04-05 12:20:10 +0000371
372#ifdef DEBUG_SAX
373 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
374 name, type);
375#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000376
377 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
378 name, type, content);
379 if (elem == 0) ctxt->valid = 0;
380 if (ctxt->validate && ctxt->wellFormed &&
381 ctxt->myDoc && ctxt->myDoc->intSubset)
382 ctxt->valid &= xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Daniel Veillard517752b1999-04-05 12:20:10 +0000383}
384
385/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000386 * notationDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000387 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000388 * @name: The name of the notation
389 * @publicId: The public ID of the entity
390 * @systemId: The system ID of the entity
391 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000392 * What to do when a notation declaration has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000393 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000394void
Daniel Veillard27d88741999-05-29 11:51:49 +0000395notationDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000396 const CHAR *publicId, const CHAR *systemId)
397{
Daniel Veillard27d88741999-05-29 11:51:49 +0000398 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillardb05deb71999-08-10 19:04:08 +0000399 xmlNotationPtr nota;
400
Daniel Veillard260a68f1998-08-13 03:39:55 +0000401#ifdef DEBUG_SAX
402 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
403#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +0000404
405 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
406 publicId, systemId);
407 if (nota == 0) ctxt->valid = 0;
408 if (ctxt->validate && ctxt->wellFormed &&
409 ctxt->myDoc && ctxt->myDoc->intSubset)
410 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
411 nota);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000412}
413
Daniel Veillard97b58771998-10-20 06:14:16 +0000414/**
415 * unparsedEntityDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000416 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000417 * @name: The name of the entity
418 * @publicId: The public ID of the entity
419 * @systemId: The system ID of the entity
420 * @notationName: the name of the notation
421 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000422 * What to do when an unparsed entity declaration is parsed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000424void
Daniel Veillard27d88741999-05-29 11:51:49 +0000425unparsedEntityDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000426 const CHAR *publicId, const CHAR *systemId,
427 const CHAR *notationName)
428{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000429 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000430#ifdef DEBUG_SAX
431 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
432 name, publicId, systemId, notationName);
433#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000434 if (ctxt->validate && ctxt->wellFormed &&
435 ctxt->myDoc && ctxt->myDoc->intSubset)
436 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
437 notationName);
438 xmlAddDocEntity(ctxt->myDoc, name,
439 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
440 publicId, systemId, notationName);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000441}
442
Daniel Veillard97b58771998-10-20 06:14:16 +0000443/**
444 * setDocumentLocator:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000445 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000446 * @loc: A SAX Locator
447 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000448 * Receive the document locator at startup, actually xmlDefaultSAXLocator
449 * Everything is available on the context, so this is useless in our case.
450 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000451void
Daniel Veillard27d88741999-05-29 11:51:49 +0000452setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000453{
Daniel Veillard27d88741999-05-29 11:51:49 +0000454 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000455#ifdef DEBUG_SAX
456 fprintf(stderr, "SAX.setDocumentLocator()\n");
457#endif
458}
459
Daniel Veillard97b58771998-10-20 06:14:16 +0000460/**
461 * startDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000462 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000463 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000464 * called when the document start being processed.
465 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000466void
Daniel Veillard27d88741999-05-29 11:51:49 +0000467startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000468{
Daniel Veillard27d88741999-05-29 11:51:49 +0000469 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000470 xmlDocPtr doc;
471
Daniel Veillard260a68f1998-08-13 03:39:55 +0000472#ifdef DEBUG_SAX
473 fprintf(stderr, "SAX.startDocument()\n");
474#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000475 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
476 if (doc != NULL) {
477 if (ctxt->encoding != NULL)
478 doc->encoding = xmlStrdup(ctxt->encoding);
479 else
480 doc->encoding = NULL;
481 doc->standalone = ctxt->standalone;
482 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000483}
484
Daniel Veillard97b58771998-10-20 06:14:16 +0000485/**
486 * endDocument:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000487 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000488 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000489 * called when the document end has been detected.
490 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000491void
Daniel Veillard27d88741999-05-29 11:51:49 +0000492endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000493{
Daniel Veillard27d88741999-05-29 11:51:49 +0000494 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000495#ifdef DEBUG_SAX
496 fprintf(stderr, "SAX.endDocument()\n");
497#endif
498}
499
Daniel Veillard97b58771998-10-20 06:14:16 +0000500/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000501 * attribute:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000502 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000503 * @name: The attribute name
504 * @value: The attribute value
505 *
506 * Handle an attribute that has been read by the parser.
507 * The default handling is to convert the attribute into an
508 * DOM subtree and past it in a new xmlAttr element added to
509 * the element.
510 */
511void
Daniel Veillard27d88741999-05-29 11:51:49 +0000512attribute(void *ctx, const CHAR *fullname, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000513{
Daniel Veillard27d88741999-05-29 11:51:49 +0000514 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000515 xmlAttrPtr ret;
516 CHAR *name;
517 CHAR *ns;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000518 xmlNsPtr namespace;
Daniel Veillard517752b1999-04-05 12:20:10 +0000519
520/****************
521#ifdef DEBUG_SAX
522 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
523#endif
524 ****************/
525 /*
526 * Split the full name into a namespace prefix and the tag name
527 */
528 name = xmlSplitQName(fullname, &ns);
529
530 /*
531 * Check whether it's a namespace definition
532 */
533 if ((ns == NULL) &&
534 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
535 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
536 /* a default namespace definition */
537 xmlNewNs(ctxt->node, value, NULL);
538 if (name != NULL)
539 free(name);
540 return;
541 }
542 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
543 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
544 /* a standard namespace definition */
545 xmlNewNs(ctxt->node, value, name);
546 free(ns);
547 if (name != NULL)
548 free(name);
549 return;
550 }
551
Daniel Veillardb96e6431999-08-29 21:02:19 +0000552 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
553 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
554 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +0000555
Daniel Veillardb96e6431999-08-29 21:02:19 +0000556 if (ret != NULL) {
557 if (ctxt->replaceEntities == 0)
558 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
559 else
560 ret->val = xmlNewDocText(ctxt->myDoc, value);
561 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000562
563 if (ctxt->validate && ctxt->wellFormed &&
564 ctxt->myDoc && ctxt->myDoc->intSubset)
565 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
566 ctxt->node, ret, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000567 else {
568 /*
569 * when validating, the ID registration is done at the attribute
570 * validation level. Otherwise we have to do specific handling here.
571 */
572 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
573 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
574 }
Daniel Veillardb05deb71999-08-10 19:04:08 +0000575
Daniel Veillard517752b1999-04-05 12:20:10 +0000576 if (name != NULL)
577 free(name);
578 if (ns != NULL)
579 free(ns);
580}
581
582/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000583 * startElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000584 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000585 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000586 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000587 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000588 * called when an opening tag has been processed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000589 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000590void
Daniel Veillard27d88741999-05-29 11:51:49 +0000591startElement(void *ctx, const CHAR *fullname, const CHAR **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000592{
Daniel Veillard27d88741999-05-29 11:51:49 +0000593 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000594 xmlNodePtr ret;
595 xmlNodePtr parent = ctxt->node;
596 xmlNsPtr ns;
597 CHAR *name;
598 CHAR *prefix;
599 const CHAR *att;
600 const CHAR *value;
601
602 int i;
603
Daniel Veillard260a68f1998-08-13 03:39:55 +0000604#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000605 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000606#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000607 /*
608 * Split the full name into a namespace prefix and the tag name
609 */
610 name = xmlSplitQName(fullname, &prefix);
611
612
613 /*
614 * Note : the namespace resolution is deferred until the end of the
615 * attributes parsing, since local namespace can be defined as
616 * an attribute at this level.
617 */
618 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
619 if (ret == NULL) return;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000620 if (ctxt->myDoc->root == NULL) {
621#ifdef DEBUG_SAX_TREE
622 fprintf(stderr, "Setting %s as root\n", name);
623#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000624 ctxt->myDoc->root = ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000625 } else if (parent == NULL) {
626 parent = ctxt->myDoc->root;
627 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000628
629 /*
630 * We are parsing a new node.
631 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000632#ifdef DEBUG_SAX_TREE
633 fprintf(stderr, "pushing(%s)\n", name);
634#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000635 nodePush(ctxt, ret);
636
637 /*
638 * Link the child element
639 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000640 if (parent != NULL) {
641 if (parent->type == XML_ELEMENT_NODE) {
642#ifdef DEBUG_SAX_TREE
643 fprintf(stderr, "adding child %s to %s\n", name, parent->name);
644#endif
645 xmlAddChild(parent, ret);
646 } else {
647#ifdef DEBUG_SAX_TREE
648 fprintf(stderr, "adding sibling %s to ", name);
649 xmlDebugDumpOneNode(stderr, parent, 0);
650#endif
651 xmlAddSibling(parent, ret);
652 }
653 }
Daniel Veillard517752b1999-04-05 12:20:10 +0000654
655 /*
Daniel Veillardb96e6431999-08-29 21:02:19 +0000656 * process all the attributes whose name start with "xml"
Daniel Veillard517752b1999-04-05 12:20:10 +0000657 */
658 if (atts != NULL) {
659 i = 0;
660 att = atts[i++];
661 value = atts[i++];
662 while ((att != NULL) && (value != NULL)) {
Daniel Veillardb96e6431999-08-29 21:02:19 +0000663 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
664 attribute(ctxt, att, value);
665
666 att = atts[i++];
667 value = atts[i++];
668 }
669 }
670
671 /*
672 * process all the other attributes
673 */
674 if (atts != NULL) {
675 i = 0;
676 att = atts[i++];
677 value = atts[i++];
678 while ((att != NULL) && (value != NULL)) {
679 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
680 attribute(ctxt, att, value);
Daniel Veillard517752b1999-04-05 12:20:10 +0000681
682 /*
683 * Next ones
684 */
685 att = atts[i++];
686 value = atts[i++];
687 }
688 }
689
690 /*
691 * Search the namespace, note that since the attributes have been
692 * processed, the local namespaces are available.
693 */
694 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
695 if ((ns == NULL) && (parent != NULL))
696 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
697 xmlSetNs(ret, ns);
698
699 if (prefix != NULL)
700 free(prefix);
701 if (name != NULL)
702 free(name);
703
Daniel Veillard260a68f1998-08-13 03:39:55 +0000704}
705
Daniel Veillard97b58771998-10-20 06:14:16 +0000706/**
707 * endElement:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000708 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000709 * @name: The element name
710 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000711 * called when the end of an element has been detected.
712 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000713void
Daniel Veillard27d88741999-05-29 11:51:49 +0000714endElement(void *ctx, const CHAR *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000715{
Daniel Veillard27d88741999-05-29 11:51:49 +0000716 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000717 xmlParserNodeInfo node_info;
718 xmlNodePtr cur = ctxt->node;
719
Daniel Veillard260a68f1998-08-13 03:39:55 +0000720#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000721 if (name == NULL)
722 fprintf(stderr, "SAX.endElement(NULL)\n");
723 else
724 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000725#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000726
727 /* Capture end position and add node */
728 if (cur != NULL && ctxt->record_info) {
729 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
730 node_info.end_line = ctxt->input->line;
731 node_info.node = cur;
732 xmlParserAddNodeInfo(ctxt, &node_info);
733 }
734
Daniel Veillardb05deb71999-08-10 19:04:08 +0000735 if (ctxt->validate && ctxt->wellFormed &&
736 ctxt->myDoc && ctxt->myDoc->intSubset)
737 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
738 cur);
739
740
Daniel Veillard517752b1999-04-05 12:20:10 +0000741 /*
742 * end of parsing of this node.
743 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000744#ifdef DEBUG_SAX_TREE
745 fprintf(stderr, "popping(%s)\n", cur->name);
746#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000747 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000748}
749
Daniel Veillard97b58771998-10-20 06:14:16 +0000750/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000751 * reference:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000752 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000753 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000754 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000755 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000756 */
757void
Daniel Veillard27d88741999-05-29 11:51:49 +0000758reference(void *ctx, const CHAR *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000759{
Daniel Veillard27d88741999-05-29 11:51:49 +0000760 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000761 xmlNodePtr ret;
762
Daniel Veillard11e00581998-10-24 18:27:49 +0000763#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000764 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000765#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000766 ret = xmlNewReference(ctxt->myDoc, name);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000767#ifdef DEBUG_SAX_TREE
768 fprintf(stderr, "add reference %s to %s \n", name, ctxt->node->name);
769#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000770 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000771}
772
773/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000774 * characters:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000775 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000776 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000777 * @len: the number of CHAR
778 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000779 * receiving some chars from the parser.
780 * Question: how much at a time ???
781 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000782void
Daniel Veillard27d88741999-05-29 11:51:49 +0000783characters(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000784{
Daniel Veillard27d88741999-05-29 11:51:49 +0000785 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000786 xmlNodePtr lastChild;
787
788#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000789 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000790#endif
791 /*
792 * Handle the data if any. If there is no child
793 * add it as content, otherwise if the last child is text,
794 * concatenate it, else create a new node of type text.
795 */
796
797 lastChild = xmlGetLastChild(ctxt->node);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000798#ifdef DEBUG_SAX_TREE
799 fprintf(stderr, "add chars to %s \n", ctxt->node->name);
800#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000801 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000802 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000803 else {
804 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000805 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000806 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000807 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000808 xmlAddChild(ctxt->node, lastChild);
809 }
810 }
811}
812
Daniel Veillard97b58771998-10-20 06:14:16 +0000813/**
814 * ignorableWhitespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000815 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000816 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000817 * @len: the number of CHAR
818 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000819 * receiving some ignorable whitespaces from the parser.
820 * Question: how much at a time ???
821 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000822void
Daniel Veillard27d88741999-05-29 11:51:49 +0000823ignorableWhitespace(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000824{
Daniel Veillard27d88741999-05-29 11:51:49 +0000825 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000826#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000827 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000828#endif
829}
830
Daniel Veillard97b58771998-10-20 06:14:16 +0000831/**
832 * processingInstruction:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000833 * @ctx: the user data (XML parser context)
Daniel Veillard97b58771998-10-20 06:14:16 +0000834 * @target: the target name
835 * @data: the PI data's
836 * @len: the number of CHAR
837 *
838 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000839 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000840void
Daniel Veillard27d88741999-05-29 11:51:49 +0000841processingInstruction(void *ctx, const CHAR *target,
Daniel Veillard97b58771998-10-20 06:14:16 +0000842 const CHAR *data)
843{
Daniel Veillardb96e6431999-08-29 21:02:19 +0000844 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
845 xmlNodePtr ret;
846 xmlNodePtr parent = ctxt->node;
847
Daniel Veillard260a68f1998-08-13 03:39:55 +0000848#ifdef DEBUG_SAX
849 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
850#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +0000851
852 ret = xmlNewPI(target, data);
853 if (ret == NULL) return;
854 ret->doc = ctxt->myDoc;
855 if (ctxt->myDoc->root == NULL) {
856#ifdef DEBUG_SAX_TREE
857 fprintf(stderr, "Setting PI %s as root\n", target);
858#endif
859 ctxt->myDoc->root = ret;
860 } else if (parent == NULL) {
861 parent = ctxt->myDoc->root;
862 }
863 if (parent != NULL) {
864 if (parent->type == XML_ELEMENT_NODE) {
865#ifdef DEBUG_SAX_TREE
866 fprintf(stderr, "adding PI child %s to %s\n", target, parent->name);
867#endif
868 xmlAddChild(parent, ret);
869 } else {
870#ifdef DEBUG_SAX_TREE
871 fprintf(stderr, "adding PI sibling %s to ", target);
872 xmlDebugDumpOneNode(stderr, parent, 0);
873#endif
874 xmlAddSibling(parent, ret);
875 }
876 }
877
Daniel Veillard260a68f1998-08-13 03:39:55 +0000878}
879
Daniel Veillard517752b1999-04-05 12:20:10 +0000880/**
881 * globalNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000882 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000883 * @href: the namespace associated URN
884 * @prefix: the namespace prefix
885 *
886 * An old global namespace has been parsed.
887 */
888void
Daniel Veillard27d88741999-05-29 11:51:49 +0000889globalNamespace(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000890{
Daniel Veillard27d88741999-05-29 11:51:49 +0000891 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000892#ifdef DEBUG_SAX
893 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
894#endif
895 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
896}
897
898/**
899 * setNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000900 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000901 * @name: the namespace prefix
902 *
903 * Set the current element namespace.
904 */
905void
Daniel Veillard27d88741999-05-29 11:51:49 +0000906setNamespace(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000907{
Daniel Veillard27d88741999-05-29 11:51:49 +0000908 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000909 xmlNsPtr ns;
910 xmlNodePtr parent;
911
912#ifdef DEBUG_SAX
913 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
914#endif
915 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
916 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
917 if (ctxt->nodeNr >= 2) {
918 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
919 if (parent != NULL)
920 ns = xmlSearchNs(ctxt->myDoc, parent, name);
921 }
922 }
923 xmlSetNs(ctxt->node, ns);
924}
925
926/**
927 * getNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000928 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000929 *
930 * Get the current element namespace.
931 */
932xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000933getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000934{
Daniel Veillard27d88741999-05-29 11:51:49 +0000935 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000936 xmlNsPtr ret;
937
938#ifdef DEBUG_SAX
939 fprintf(stderr, "SAX.getNamespace()\n");
940#endif
941 ret = ctxt->node->ns;
942 return(ret);
943}
944
945/**
946 * checkNamespace:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000947 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000948 * @namespace: the namespace to check against
949 *
950 * Check that the current element namespace is the same as the
951 * one read upon parsing.
952 */
953int
Daniel Veillard27d88741999-05-29 11:51:49 +0000954checkNamespace(void *ctx, CHAR *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000955{
Daniel Veillard27d88741999-05-29 11:51:49 +0000956 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000957 xmlNodePtr cur = ctxt->node;
958
959#ifdef DEBUG_SAX
960 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
961#endif
962
963 /*
964 * Check that the Name in the ETag is the same as in the STag.
965 */
966 if (namespace == NULL) {
967 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
968 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
969 ctxt->sax->error(ctxt,
970 "End tags for %s don't hold the namespace %s\n",
971 cur->name, cur->ns->prefix);
972 ctxt->wellFormed = 0;
973 }
974 } else {
975 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
976 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
977 ctxt->sax->error(ctxt,
978 "End tags %s holds a prefix %s not used by the open tag\n",
979 cur->name, namespace);
980 ctxt->wellFormed = 0;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000981 } else if (xmlStrcmp(namespace, cur->ns->prefix)) {
Daniel Veillard517752b1999-04-05 12:20:10 +0000982 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
983 ctxt->sax->error(ctxt,
984 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
985 cur->name, cur->ns->prefix, namespace);
986 ctxt->wellFormed = 0;
987 } else
988 return(1);
989 }
990 return(0);
991}
992
993/**
994 * namespaceDecl:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000995 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +0000996 * @href: the namespace associated URN
997 * @prefix: the namespace prefix
998 *
999 * A namespace has been parsed.
1000 */
1001void
Daniel Veillard27d88741999-05-29 11:51:49 +00001002namespaceDecl(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +00001003{
Daniel Veillard27d88741999-05-29 11:51:49 +00001004 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +00001005#ifdef DEBUG_SAX
1006 if (prefix == NULL)
1007 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
1008 else
1009 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1010#endif
1011 xmlNewNs(ctxt->node, href, prefix);
1012}
1013
1014/**
1015 * comment:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001016 * @ctx: the user data (XML parser context)
Daniel Veillard517752b1999-04-05 12:20:10 +00001017 * @value: the comment content
1018 *
1019 * A comment has been parsed.
1020 */
1021void
Daniel Veillard27d88741999-05-29 11:51:49 +00001022comment(void *ctx, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +00001023{
Daniel Veillard27d88741999-05-29 11:51:49 +00001024 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard14fff061999-06-22 21:49:07 +00001025 xmlNodePtr ret;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001026 xmlNodePtr parent = ctxt->node;
Daniel Veillard14fff061999-06-22 21:49:07 +00001027
Daniel Veillard517752b1999-04-05 12:20:10 +00001028#ifdef DEBUG_SAX
1029 fprintf(stderr, "SAX.comment(%s)\n", value);
1030#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00001031 ret = xmlNewDocComment(ctxt->myDoc, value);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001032 if (ret == NULL) return;
1033
1034 if (ctxt->myDoc->root == NULL) {
1035#ifdef DEBUG_SAX_TREE
1036 fprintf(stderr, "Setting comment as root\n");
1037#endif
1038 ctxt->myDoc->root = ret;
1039 } else if (parent == NULL) {
1040 parent = ctxt->myDoc->root;
1041 }
1042 if (parent != NULL) {
1043 if (parent->type == XML_ELEMENT_NODE) {
1044#ifdef DEBUG_SAX_TREE
1045 fprintf(stderr, "adding comment child to %s\n", parent->name);
1046#endif
1047 xmlAddChild(parent, ret);
1048 } else {
1049#ifdef DEBUG_SAX_TREE
1050 fprintf(stderr, "adding comment sibling to ");
1051 xmlDebugDumpOneNode(stderr, parent, 0);
1052#endif
1053 xmlAddSibling(parent, ret);
1054 }
1055 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001056}
1057
1058/**
1059 * cdataBlock:
1060 * @ctx: the user data (XML parser context)
1061 * @value: The pcdata content
1062 * @len: the block length
1063 *
1064 * called when a pcdata block has been parsed
1065 */
1066void
1067cdataBlock(void *ctx, const CHAR *value, int len)
1068{
1069 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1070 xmlNodePtr ret;
1071
1072#ifdef DEBUG_SAX
Daniel Veillardb96e6431999-08-29 21:02:19 +00001073 fprintf(stderr, "SAX.pcdata(%.10s, %d)\n", value, len);
Daniel Veillardb05deb71999-08-10 19:04:08 +00001074#endif
1075 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1076 xmlAddChild(ctxt->node, ret);
1077 /* !!!!! merges */
Daniel Veillard517752b1999-04-05 12:20:10 +00001078}
1079
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001080/*
1081 * Default handler for XML, builds the DOM tree
1082 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001083xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +00001084 internalSubset,
1085 isStandalone,
1086 hasInternalSubset,
1087 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001088 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +00001089 getEntity,
1090 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001091 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +00001092 attributeDecl,
1093 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001094 unparsedEntityDecl,
1095 setDocumentLocator,
1096 startDocument,
1097 endDocument,
1098 startElement,
1099 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +00001100 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001101 characters,
1102 ignorableWhitespace,
1103 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +00001104 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 xmlParserWarning,
1106 xmlParserError,
1107 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001108 getParameterEntity,
1109 cdataBlock,
Daniel Veillard260a68f1998-08-13 03:39:55 +00001110};
1111
Daniel Veillard97b58771998-10-20 06:14:16 +00001112/**
1113 * xmlDefaultSAXHandlerInit:
1114 *
1115 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +00001116 */
1117void
1118xmlDefaultSAXHandlerInit(void)
1119{
Daniel Veillard517752b1999-04-05 12:20:10 +00001120 xmlDefaultSAXHandler.internalSubset = internalSubset;
1121 xmlDefaultSAXHandler.isStandalone = isStandalone;
1122 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1123 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001124 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001125 xmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001126 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +00001127 xmlDefaultSAXHandler.entityDecl = entityDecl;
1128 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1129 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001130 xmlDefaultSAXHandler.notationDecl = notationDecl;
1131 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1132 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1133 xmlDefaultSAXHandler.startDocument = startDocument;
1134 xmlDefaultSAXHandler.endDocument = endDocument;
1135 xmlDefaultSAXHandler.startElement = startElement;
1136 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +00001137 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001138 xmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001139 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001140 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1141 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +00001142 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001143 xmlDefaultSAXHandler.warning = xmlParserWarning;
1144 xmlDefaultSAXHandler.error = xmlParserError;
1145 xmlDefaultSAXHandler.fatalError = xmlParserError;
1146}
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001147
1148/*
1149 * Default handler for HTML, builds the DOM tree
1150 */
1151xmlSAXHandler htmlDefaultSAXHandler = {
1152 NULL,
1153 NULL,
1154 NULL,
1155 NULL,
1156 NULL,
1157 getEntity,
1158 NULL,
1159 NULL,
1160 NULL,
1161 NULL,
1162 NULL,
1163 setDocumentLocator,
1164 startDocument,
1165 endDocument,
1166 startElement,
1167 endElement,
1168 NULL,
1169 characters,
1170 ignorableWhitespace,
1171 NULL,
1172 comment,
1173 xmlParserWarning,
1174 xmlParserError,
1175 xmlParserError,
Daniel Veillardb05deb71999-08-10 19:04:08 +00001176 getParameterEntity,
1177 NULL,
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001178};
1179
1180/**
1181 * htmlDefaultSAXHandlerInit:
1182 *
1183 * Initialize the default SAX handler
1184 */
1185void
1186htmlDefaultSAXHandlerInit(void)
1187{
1188 htmlDefaultSAXHandler.internalSubset = NULL;
1189 htmlDefaultSAXHandler.isStandalone = NULL;
1190 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1191 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1192 htmlDefaultSAXHandler.resolveEntity = NULL;
1193 htmlDefaultSAXHandler.getEntity = getEntity;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001194 htmlDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001195 htmlDefaultSAXHandler.entityDecl = NULL;
1196 htmlDefaultSAXHandler.attributeDecl = NULL;
1197 htmlDefaultSAXHandler.elementDecl = NULL;
1198 htmlDefaultSAXHandler.notationDecl = NULL;
1199 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1200 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1201 htmlDefaultSAXHandler.startDocument = startDocument;
1202 htmlDefaultSAXHandler.endDocument = endDocument;
1203 htmlDefaultSAXHandler.startElement = startElement;
1204 htmlDefaultSAXHandler.endElement = endElement;
1205 htmlDefaultSAXHandler.reference = NULL;
1206 htmlDefaultSAXHandler.characters = characters;
Daniel Veillardb05deb71999-08-10 19:04:08 +00001207 htmlDefaultSAXHandler.cdataBlock = NULL;
Daniel Veillardbe70ff71999-07-05 16:50:46 +00001208 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1209 htmlDefaultSAXHandler.processingInstruction = NULL;
1210 htmlDefaultSAXHandler.comment = comment;
1211 htmlDefaultSAXHandler.warning = xmlParserWarning;
1212 htmlDefaultSAXHandler.error = xmlParserError;
1213 htmlDefaultSAXHandler.fatalError = xmlParserError;
1214}