blob: 596f6682df29cbc1c1de244528225b7d37177d7b [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 Veillard260a68f1998-08-13 03:39:55 +000017
18/* #define DEBUG_SAX */
19
Daniel Veillard97b58771998-10-20 06:14:16 +000020/**
21 * getPublicId:
22 * @ctxt: An XML parser context
23 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000024 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000025 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000026 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000027 */
Daniel Veillard97b58771998-10-20 06:14:16 +000028const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000029getPublicId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000030{
Daniel Veillard27d88741999-05-29 11:51:49 +000031 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +000032 return(NULL);
33}
34
Daniel Veillard97b58771998-10-20 06:14:16 +000035/**
36 * getSystemId:
37 * @ctxt: An XML parser context
38 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000039 * Return the system ID, basically URI or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000040 * http://www.sgmlsource.com/dtds/memo.dtd
41 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000042 * Returns a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000043 */
Daniel Veillard97b58771998-10-20 06:14:16 +000044const CHAR *
Daniel Veillard27d88741999-05-29 11:51:49 +000045getSystemId(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000046{
Daniel Veillard27d88741999-05-29 11:51:49 +000047 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000048 return(ctxt->input->filename);
49}
50
Daniel Veillard97b58771998-10-20 06:14:16 +000051/**
52 * getLineNumber:
53 * @ctxt: An XML parser context
54 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000055 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000056 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000057 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000058 */
Daniel Veillard97b58771998-10-20 06:14:16 +000059int
Daniel Veillard27d88741999-05-29 11:51:49 +000060getLineNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000061{
Daniel Veillard27d88741999-05-29 11:51:49 +000062 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000063 return(ctxt->input->line);
64}
Daniel Veillard97b58771998-10-20 06:14:16 +000065
66/**
67 * getColumnNumber:
68 * @ctxt: An XML parser context
69 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000070 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000071 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000072 * Returns an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000073 */
Daniel Veillard97b58771998-10-20 06:14:16 +000074int
Daniel Veillard27d88741999-05-29 11:51:49 +000075getColumnNumber(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +000076{
Daniel Veillard27d88741999-05-29 11:51:49 +000077 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +000078 return(ctxt->input->col);
79}
80
81/*
82 * The default SAX Locator.
83 */
84
85xmlSAXLocator xmlDefaultSAXLocator = {
86 getPublicId, getSystemId, getLineNumber, getColumnNumber
87};
88
Daniel Veillard97b58771998-10-20 06:14:16 +000089/**
Daniel Veillard517752b1999-04-05 12:20:10 +000090 * isStandalone:
91 * @ctxt: An XML parser context
92 *
93 * Is this document tagged standalone ?
94 *
95 * Returns 1 if true
96 */
97int
Daniel Veillard27d88741999-05-29 11:51:49 +000098isStandalone(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +000099{
Daniel Veillard27d88741999-05-29 11:51:49 +0000100 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000101 return(ctxt->myDoc->standalone == 1);
102}
103
104/**
105 * hasInternalSubset:
106 * @ctxt: An XML parser context
107 *
108 * Does this document has an internal subset
109 *
110 * Returns 1 if true
111 */
112int
Daniel Veillard27d88741999-05-29 11:51:49 +0000113hasInternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000114{
Daniel Veillard27d88741999-05-29 11:51:49 +0000115 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000116 return(ctxt->myDoc->intSubset != NULL);
117}
118
119/**
120 * hasExternalSubset:
121 * @ctxt: An XML parser context
122 *
123 * Does this document has an external subset
124 *
125 * Returns 1 if true
126 */
127int
Daniel Veillard27d88741999-05-29 11:51:49 +0000128hasExternalSubset(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000129{
Daniel Veillard27d88741999-05-29 11:51:49 +0000130 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000131 return(ctxt->myDoc->extSubset != NULL);
132}
133
134/**
135 * hasInternalSubset:
136 * @ctxt: An XML parser context
137 *
138 * Does this document has an internal subset
139 */
140void
Daniel Veillard27d88741999-05-29 11:51:49 +0000141internalSubset(void *ctx, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000142 const CHAR *ExternalID, const CHAR *SystemID)
143{
Daniel Veillard27d88741999-05-29 11:51:49 +0000144 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000145#ifdef DEBUG_SAX
146 fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
147 name, ExternalID, SystemID);
148#endif
149 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
150}
151
152/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000153 * resolveEntity:
154 * @ctxt: An XML parser context
155 * @publicId: The public ID of the entity
156 * @systemId: The system ID of the entity
157 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000158 * Special entity resolver, better left to the parser, it has
159 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +0000160 * The default behaviour is to NOT resolve the entities, in that case
161 * the ENTITY_REF nodes are built in the structure (and the parameter
162 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +0000163 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000164 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000165 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000166xmlParserInputPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000167resolveEntity(void *ctx, const CHAR *publicId, const CHAR *systemId)
Daniel Veillard97b58771998-10-20 06:14:16 +0000168{
Daniel Veillard27d88741999-05-29 11:51:49 +0000169 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000170
171#ifdef DEBUG_SAX
172 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
173#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000174
Daniel Veillard517752b1999-04-05 12:20:10 +0000175 /*
176 * TODO : not 100% sure that the appropriate handling in that case.
177 */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000178 return(NULL);
179}
180
Daniel Veillard97b58771998-10-20 06:14:16 +0000181/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000182 * getEntity:
183 * @ctxt: An XML parser context
184 * @name: The entity name
185 *
186 * Get an entity by name
187 *
188 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
189 */
190xmlEntityPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000191getEntity(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000192{
Daniel Veillard27d88741999-05-29 11:51:49 +0000193 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000194 xmlEntityPtr ret;
195
196#ifdef DEBUG_SAX
197 fprintf(stderr, "SAX.getEntity(%s)\n", name);
198#endif
199
200 ret = xmlGetDocEntity(ctxt->myDoc, name);
201 return(ret);
202}
203
204
205/**
206 * entityDecl:
207 * @ctxt: An XML parser context
208 * @name: the entity name
209 * @type: the entity type
210 * @publicId: The public ID of the entity
211 * @systemId: The system ID of the entity
212 * @content: the entity value (without processing).
213 *
214 * An entity definition has been parsed
215 */
216void
Daniel Veillard27d88741999-05-29 11:51:49 +0000217entityDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000218 const CHAR *publicId, const CHAR *systemId, CHAR *content)
219{
Daniel Veillard27d88741999-05-29 11:51:49 +0000220 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000221
222#ifdef DEBUG_SAX
223 fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
224 name, type, publicId, systemId, content);
225#endif
226 xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
227}
228
229/**
230 * attributeDecl:
231 * @ctxt: An XML parser context
232 * @name: the attribute name
233 * @type: the attribute type
234 * @publicId: The public ID of the attribute
235 * @systemId: The system ID of the attribute
236 * @content: the attribute value (without processing).
237 *
238 * An attribute definition has been parsed
239 */
240void
Daniel Veillard27d88741999-05-29 11:51:49 +0000241attributeDecl(void *ctx, const CHAR *elem, const CHAR *name,
Daniel Veillard517752b1999-04-05 12:20:10 +0000242 int type, int def, const CHAR *defaultValue,
243 xmlEnumerationPtr tree)
244{
Daniel Veillard27d88741999-05-29 11:51:49 +0000245 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000246
247#ifdef DEBUG_SAX
248 fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
249 elem, name, type, def, defaultValue);
250#endif
251 xmlAddAttributeDecl(ctxt->myDoc->intSubset, elem, name, type, def,
252 defaultValue, tree);
253}
254
255/**
256 * elementDecl:
257 * @ctxt: An XML parser context
258 * @name: the element name
259 * @type: the element type
260 * @publicId: The public ID of the element
261 * @systemId: The system ID of the element
262 * @content: the element value (without processing).
263 *
264 * An element definition has been parsed
265 */
266void
Daniel Veillard27d88741999-05-29 11:51:49 +0000267elementDecl(void *ctx, const CHAR *name, int type,
Daniel Veillard517752b1999-04-05 12:20:10 +0000268 xmlElementContentPtr content)
269{
Daniel Veillard27d88741999-05-29 11:51:49 +0000270 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000271
272#ifdef DEBUG_SAX
273 fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
274 name, type);
275#endif
276 xmlAddElementDecl(ctxt->myDoc->intSubset, name, type, content);
277}
278
279/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000280 * notationDecl:
281 * @ctxt: An XML parser context
282 * @name: The name of the notation
283 * @publicId: The public ID of the entity
284 * @systemId: The system ID of the entity
285 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000286 * What to do when a notation declaration has been parsed.
287 * TODO Not handled currently.
288 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000289void
Daniel Veillard27d88741999-05-29 11:51:49 +0000290notationDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000291 const CHAR *publicId, const CHAR *systemId)
292{
Daniel Veillard27d88741999-05-29 11:51:49 +0000293 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000294#ifdef DEBUG_SAX
295 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
296#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000297 xmlAddNotationDecl(ctxt->myDoc->intSubset, name, publicId, systemId);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000298}
299
Daniel Veillard97b58771998-10-20 06:14:16 +0000300/**
301 * unparsedEntityDecl:
302 * @ctxt: An XML parser context
303 * @name: The name of the entity
304 * @publicId: The public ID of the entity
305 * @systemId: The system ID of the entity
306 * @notationName: the name of the notation
307 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000308 * What to do when an unparsed entity declaration is parsed
309 * TODO Create an Entity node.
310 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000311void
Daniel Veillard27d88741999-05-29 11:51:49 +0000312unparsedEntityDecl(void *ctx, const CHAR *name,
Daniel Veillard97b58771998-10-20 06:14:16 +0000313 const CHAR *publicId, const CHAR *systemId,
314 const CHAR *notationName)
315{
Daniel Veillard27d88741999-05-29 11:51:49 +0000316 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000317#ifdef DEBUG_SAX
318 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
319 name, publicId, systemId, notationName);
320#endif
321}
322
Daniel Veillard97b58771998-10-20 06:14:16 +0000323/**
324 * setDocumentLocator:
325 * @ctxt: An XML parser context
326 * @loc: A SAX Locator
327 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000328 * Receive the document locator at startup, actually xmlDefaultSAXLocator
329 * Everything is available on the context, so this is useless in our case.
330 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000331void
Daniel Veillard27d88741999-05-29 11:51:49 +0000332setDocumentLocator(void *ctx, xmlSAXLocatorPtr loc)
Daniel Veillard97b58771998-10-20 06:14:16 +0000333{
Daniel Veillard27d88741999-05-29 11:51:49 +0000334 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000335#ifdef DEBUG_SAX
336 fprintf(stderr, "SAX.setDocumentLocator()\n");
337#endif
338}
339
Daniel Veillard97b58771998-10-20 06:14:16 +0000340/**
341 * startDocument:
342 * @ctxt: An XML parser context
343 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000344 * called when the document start being processed.
345 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000346void
Daniel Veillard27d88741999-05-29 11:51:49 +0000347startDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000348{
Daniel Veillard27d88741999-05-29 11:51:49 +0000349 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000350 xmlDocPtr doc;
351
Daniel Veillard260a68f1998-08-13 03:39:55 +0000352#ifdef DEBUG_SAX
353 fprintf(stderr, "SAX.startDocument()\n");
354#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000355 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
356 if (doc != NULL) {
357 if (ctxt->encoding != NULL)
358 doc->encoding = xmlStrdup(ctxt->encoding);
359 else
360 doc->encoding = NULL;
361 doc->standalone = ctxt->standalone;
362 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000363}
364
Daniel Veillard97b58771998-10-20 06:14:16 +0000365/**
366 * endDocument:
367 * @ctxt: An XML parser context
368 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000369 * called when the document end has been detected.
370 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000371void
Daniel Veillard27d88741999-05-29 11:51:49 +0000372endDocument(void *ctx)
Daniel Veillard97b58771998-10-20 06:14:16 +0000373{
Daniel Veillard27d88741999-05-29 11:51:49 +0000374 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000375#ifdef DEBUG_SAX
376 fprintf(stderr, "SAX.endDocument()\n");
377#endif
378}
379
Daniel Veillard97b58771998-10-20 06:14:16 +0000380/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000381 * attribute:
382 * @ctxt: An XML parser context
383 * @name: The attribute name
384 * @value: The attribute value
385 *
386 * Handle an attribute that has been read by the parser.
387 * The default handling is to convert the attribute into an
388 * DOM subtree and past it in a new xmlAttr element added to
389 * the element.
390 */
391void
Daniel Veillard27d88741999-05-29 11:51:49 +0000392attribute(void *ctx, const CHAR *fullname, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000393{
Daniel Veillard27d88741999-05-29 11:51:49 +0000394 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000395 xmlAttrPtr ret;
396 CHAR *name;
397 CHAR *ns;
398
399/****************
400#ifdef DEBUG_SAX
401 fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
402#endif
403 ****************/
404 /*
405 * Split the full name into a namespace prefix and the tag name
406 */
407 name = xmlSplitQName(fullname, &ns);
408
409 /*
410 * Check whether it's a namespace definition
411 */
412 if ((ns == NULL) &&
413 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
414 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
415 /* a default namespace definition */
416 xmlNewNs(ctxt->node, value, NULL);
417 if (name != NULL)
418 free(name);
419 return;
420 }
421 if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
422 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
423 /* a standard namespace definition */
424 xmlNewNs(ctxt->node, value, name);
425 free(ns);
426 if (name != NULL)
427 free(name);
428 return;
429 }
430
431 ret = xmlNewProp(ctxt->node, name, NULL);
432 if (ret != NULL)
433 ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
434 if (name != NULL)
435 free(name);
436 if (ns != NULL)
437 free(ns);
438}
439
440/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000441 * startElement:
442 * @ctxt: An XML parser context
443 * @name: The element name
Daniel Veillard517752b1999-04-05 12:20:10 +0000444 * @atts: An array of name/value attributes pairs, NULL terminated
Daniel Veillard97b58771998-10-20 06:14:16 +0000445 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000446 * called when an opening tag has been processed.
447 * TODO We currently have a small pblm with the arguments ...
448 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000449void
Daniel Veillard27d88741999-05-29 11:51:49 +0000450startElement(void *ctx, const CHAR *fullname, const CHAR **atts)
Daniel Veillard97b58771998-10-20 06:14:16 +0000451{
Daniel Veillard27d88741999-05-29 11:51:49 +0000452 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000453 xmlNodePtr ret;
454 xmlNodePtr parent = ctxt->node;
455 xmlNsPtr ns;
456 CHAR *name;
457 CHAR *prefix;
458 const CHAR *att;
459 const CHAR *value;
460
461 int i;
462
Daniel Veillard260a68f1998-08-13 03:39:55 +0000463#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000464 fprintf(stderr, "SAX.startElement(%s)\n", fullname);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000465#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000466 /*
467 * Split the full name into a namespace prefix and the tag name
468 */
469 name = xmlSplitQName(fullname, &prefix);
470
471
472 /*
473 * Note : the namespace resolution is deferred until the end of the
474 * attributes parsing, since local namespace can be defined as
475 * an attribute at this level.
476 */
477 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
478 if (ret == NULL) return;
479 if (ctxt->myDoc->root == NULL)
480 ctxt->myDoc->root = ret;
481
482 /*
483 * We are parsing a new node.
484 */
485 nodePush(ctxt, ret);
486
487 /*
488 * Link the child element
489 */
490 if (parent != NULL)
491 xmlAddChild(parent, ctxt->node);
492
493 /*
494 * process all the attributes.
495 */
496 if (atts != NULL) {
497 i = 0;
498 att = atts[i++];
499 value = atts[i++];
500 while ((att != NULL) && (value != NULL)) {
501 /*
502 * Handle one pair of attribute/value
503 */
504 attribute(ctxt, att, value);
505
506 /*
507 * Next ones
508 */
509 att = atts[i++];
510 value = atts[i++];
511 }
512 }
513
514 /*
515 * Search the namespace, note that since the attributes have been
516 * processed, the local namespaces are available.
517 */
518 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
519 if ((ns == NULL) && (parent != NULL))
520 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
521 xmlSetNs(ret, ns);
522
523 if (prefix != NULL)
524 free(prefix);
525 if (name != NULL)
526 free(name);
527
Daniel Veillard260a68f1998-08-13 03:39:55 +0000528}
529
Daniel Veillard97b58771998-10-20 06:14:16 +0000530/**
531 * endElement:
532 * @ctxt: An XML parser context
533 * @name: The element name
534 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000535 * called when the end of an element has been detected.
536 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000537void
Daniel Veillard27d88741999-05-29 11:51:49 +0000538endElement(void *ctx, const CHAR *name)
Daniel Veillard97b58771998-10-20 06:14:16 +0000539{
Daniel Veillard27d88741999-05-29 11:51:49 +0000540 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000541 xmlParserNodeInfo node_info;
542 xmlNodePtr cur = ctxt->node;
543
Daniel Veillard260a68f1998-08-13 03:39:55 +0000544#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000545 if (name == NULL)
546 fprintf(stderr, "SAX.endElement(NULL)\n");
547 else
548 fprintf(stderr, "SAX.endElement(%s)\n", name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000549#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000550
551 /* Capture end position and add node */
552 if (cur != NULL && ctxt->record_info) {
553 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
554 node_info.end_line = ctxt->input->line;
555 node_info.node = cur;
556 xmlParserAddNodeInfo(ctxt, &node_info);
557 }
558
559 /*
560 * end of parsing of this node.
561 */
562 nodePop(ctxt);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000563}
564
Daniel Veillard97b58771998-10-20 06:14:16 +0000565/**
Daniel Veillard517752b1999-04-05 12:20:10 +0000566 * reference:
Daniel Veillard11e00581998-10-24 18:27:49 +0000567 * @ctxt: An XML parser context
Daniel Veillard517752b1999-04-05 12:20:10 +0000568 * @name: The entity name
Daniel Veillard11e00581998-10-24 18:27:49 +0000569 *
Daniel Veillard517752b1999-04-05 12:20:10 +0000570 * called when an entity reference is detected.
Daniel Veillard11e00581998-10-24 18:27:49 +0000571 */
572void
Daniel Veillard27d88741999-05-29 11:51:49 +0000573reference(void *ctx, const CHAR *name)
Daniel Veillard11e00581998-10-24 18:27:49 +0000574{
Daniel Veillard27d88741999-05-29 11:51:49 +0000575 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000576 xmlNodePtr ret;
577
Daniel Veillard11e00581998-10-24 18:27:49 +0000578#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000579 fprintf(stderr, "SAX.reference(%s)\n", name);
Daniel Veillard11e00581998-10-24 18:27:49 +0000580#endif
Daniel Veillard517752b1999-04-05 12:20:10 +0000581 ret = xmlNewReference(ctxt->myDoc, name);
582 xmlAddChild(ctxt->node, ret);
Daniel Veillard11e00581998-10-24 18:27:49 +0000583}
584
585/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000586 * characters:
587 * @ctxt: An XML parser context
588 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000589 * @len: the number of CHAR
590 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000591 * receiving some chars from the parser.
592 * Question: how much at a time ???
593 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000594void
Daniel Veillard27d88741999-05-29 11:51:49 +0000595characters(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000596{
Daniel Veillard27d88741999-05-29 11:51:49 +0000597 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000598 xmlNodePtr lastChild;
599
600#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000601 fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000602#endif
603 /*
604 * Handle the data if any. If there is no child
605 * add it as content, otherwise if the last child is text,
606 * concatenate it, else create a new node of type text.
607 */
608
609 lastChild = xmlGetLastChild(ctxt->node);
610 if (lastChild == NULL)
Daniel Veillard517752b1999-04-05 12:20:10 +0000611 xmlNodeAddContentLen(ctxt->node, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000612 else {
613 if (xmlNodeIsText(lastChild))
Daniel Veillard517752b1999-04-05 12:20:10 +0000614 xmlTextConcat(lastChild, ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000615 else {
Daniel Veillard517752b1999-04-05 12:20:10 +0000616 lastChild = xmlNewTextLen(ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000617 xmlAddChild(ctxt->node, lastChild);
618 }
619 }
620}
621
Daniel Veillard97b58771998-10-20 06:14:16 +0000622/**
623 * ignorableWhitespace:
624 * @ctxt: An XML parser context
625 * @ch: a CHAR string
Daniel Veillard97b58771998-10-20 06:14:16 +0000626 * @len: the number of CHAR
627 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000628 * receiving some ignorable whitespaces from the parser.
629 * Question: how much at a time ???
630 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000631void
Daniel Veillard27d88741999-05-29 11:51:49 +0000632ignorableWhitespace(void *ctx, const CHAR *ch, int len)
Daniel Veillard97b58771998-10-20 06:14:16 +0000633{
Daniel Veillard27d88741999-05-29 11:51:49 +0000634 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000635#ifdef DEBUG_SAX
Daniel Veillard517752b1999-04-05 12:20:10 +0000636 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000637#endif
638}
639
Daniel Veillard97b58771998-10-20 06:14:16 +0000640/**
641 * processingInstruction:
642 * @ctxt: An XML parser context
643 * @target: the target name
644 * @data: the PI data's
645 * @len: the number of CHAR
646 *
647 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000648 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000649void
Daniel Veillard27d88741999-05-29 11:51:49 +0000650processingInstruction(void *ctx, const CHAR *target,
Daniel Veillard97b58771998-10-20 06:14:16 +0000651 const CHAR *data)
652{
Daniel Veillard27d88741999-05-29 11:51:49 +0000653 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000654#ifdef DEBUG_SAX
655 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
656#endif
657}
658
Daniel Veillard517752b1999-04-05 12:20:10 +0000659/**
660 * globalNamespace:
661 * @ctxt: An XML parser context
662 * @href: the namespace associated URN
663 * @prefix: the namespace prefix
664 *
665 * An old global namespace has been parsed.
666 */
667void
Daniel Veillard27d88741999-05-29 11:51:49 +0000668globalNamespace(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000669{
Daniel Veillard27d88741999-05-29 11:51:49 +0000670 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000671#ifdef DEBUG_SAX
672 fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
673#endif
674 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
675}
676
677/**
678 * setNamespace:
679 * @ctxt: An XML parser context
680 * @name: the namespace prefix
681 *
682 * Set the current element namespace.
683 */
684void
Daniel Veillard27d88741999-05-29 11:51:49 +0000685setNamespace(void *ctx, const CHAR *name)
Daniel Veillard517752b1999-04-05 12:20:10 +0000686{
Daniel Veillard27d88741999-05-29 11:51:49 +0000687 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000688 xmlNsPtr ns;
689 xmlNodePtr parent;
690
691#ifdef DEBUG_SAX
692 fprintf(stderr, "SAX.setNamespace(%s)\n", name);
693#endif
694 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
695 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
696 if (ctxt->nodeNr >= 2) {
697 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
698 if (parent != NULL)
699 ns = xmlSearchNs(ctxt->myDoc, parent, name);
700 }
701 }
702 xmlSetNs(ctxt->node, ns);
703}
704
705/**
706 * getNamespace:
707 * @ctxt: An XML parser context
708 *
709 * Get the current element namespace.
710 */
711xmlNsPtr
Daniel Veillard27d88741999-05-29 11:51:49 +0000712getNamespace(void *ctx)
Daniel Veillard517752b1999-04-05 12:20:10 +0000713{
Daniel Veillard27d88741999-05-29 11:51:49 +0000714 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000715 xmlNsPtr ret;
716
717#ifdef DEBUG_SAX
718 fprintf(stderr, "SAX.getNamespace()\n");
719#endif
720 ret = ctxt->node->ns;
721 return(ret);
722}
723
724/**
725 * checkNamespace:
726 * @ctxt: An XML parser context
727 * @namespace: the namespace to check against
728 *
729 * Check that the current element namespace is the same as the
730 * one read upon parsing.
731 */
732int
Daniel Veillard27d88741999-05-29 11:51:49 +0000733checkNamespace(void *ctx, CHAR *namespace)
Daniel Veillard517752b1999-04-05 12:20:10 +0000734{
Daniel Veillard27d88741999-05-29 11:51:49 +0000735 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000736 xmlNodePtr cur = ctxt->node;
737
738#ifdef DEBUG_SAX
739 fprintf(stderr, "SAX.checkNamespace(%s)\n", namespace);
740#endif
741
742 /*
743 * Check that the Name in the ETag is the same as in the STag.
744 */
745 if (namespace == NULL) {
746 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
747 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
748 ctxt->sax->error(ctxt,
749 "End tags for %s don't hold the namespace %s\n",
750 cur->name, cur->ns->prefix);
751 ctxt->wellFormed = 0;
752 }
753 } else {
754 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
755 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
756 ctxt->sax->error(ctxt,
757 "End tags %s holds a prefix %s not used by the open tag\n",
758 cur->name, namespace);
759 ctxt->wellFormed = 0;
760 } else if (strcmp(namespace, cur->ns->prefix)) {
761 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
762 ctxt->sax->error(ctxt,
763 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
764 cur->name, cur->ns->prefix, namespace);
765 ctxt->wellFormed = 0;
766 } else
767 return(1);
768 }
769 return(0);
770}
771
772/**
773 * namespaceDecl:
774 * @ctxt: An XML parser context
775 * @href: the namespace associated URN
776 * @prefix: the namespace prefix
777 *
778 * A namespace has been parsed.
779 */
780void
Daniel Veillard27d88741999-05-29 11:51:49 +0000781namespaceDecl(void *ctx, const CHAR *href, const CHAR *prefix)
Daniel Veillard517752b1999-04-05 12:20:10 +0000782{
Daniel Veillard27d88741999-05-29 11:51:49 +0000783 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000784#ifdef DEBUG_SAX
785 if (prefix == NULL)
786 fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
787 else
788 fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
789#endif
790 xmlNewNs(ctxt->node, href, prefix);
791}
792
793/**
794 * comment:
795 * @ctxt: An XML parser context
796 * @value: the comment content
797 *
798 * A comment has been parsed.
799 */
800void
Daniel Veillard27d88741999-05-29 11:51:49 +0000801comment(void *ctx, const CHAR *value)
Daniel Veillard517752b1999-04-05 12:20:10 +0000802{
Daniel Veillard27d88741999-05-29 11:51:49 +0000803 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard517752b1999-04-05 12:20:10 +0000804#ifdef DEBUG_SAX
805 fprintf(stderr, "SAX.comment(%s)\n", value);
806#endif
807 xmlNewDocComment(ctxt->myDoc, value);
808}
809
Daniel Veillard260a68f1998-08-13 03:39:55 +0000810xmlSAXHandler xmlDefaultSAXHandler = {
Daniel Veillard517752b1999-04-05 12:20:10 +0000811 internalSubset,
812 isStandalone,
813 hasInternalSubset,
814 hasExternalSubset,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000815 resolveEntity,
Daniel Veillard517752b1999-04-05 12:20:10 +0000816 getEntity,
817 entityDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000818 notationDecl,
Daniel Veillard517752b1999-04-05 12:20:10 +0000819 attributeDecl,
820 elementDecl,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000821 unparsedEntityDecl,
822 setDocumentLocator,
823 startDocument,
824 endDocument,
825 startElement,
826 endElement,
Daniel Veillard517752b1999-04-05 12:20:10 +0000827 reference,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000828 characters,
829 ignorableWhitespace,
830 processingInstruction,
Daniel Veillard517752b1999-04-05 12:20:10 +0000831 comment,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000832 xmlParserWarning,
833 xmlParserError,
834 xmlParserError,
835};
836
Daniel Veillard97b58771998-10-20 06:14:16 +0000837/**
838 * xmlDefaultSAXHandlerInit:
839 *
840 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +0000841 */
842void
843xmlDefaultSAXHandlerInit(void)
844{
Daniel Veillard517752b1999-04-05 12:20:10 +0000845 xmlDefaultSAXHandler.internalSubset = internalSubset;
846 xmlDefaultSAXHandler.isStandalone = isStandalone;
847 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
848 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000849 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillard517752b1999-04-05 12:20:10 +0000850 xmlDefaultSAXHandler.getEntity = getEntity;
851 xmlDefaultSAXHandler.entityDecl = entityDecl;
852 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
853 xmlDefaultSAXHandler.elementDecl = elementDecl;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000854 xmlDefaultSAXHandler.notationDecl = notationDecl;
855 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
856 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
857 xmlDefaultSAXHandler.startDocument = startDocument;
858 xmlDefaultSAXHandler.endDocument = endDocument;
859 xmlDefaultSAXHandler.startElement = startElement;
860 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard517752b1999-04-05 12:20:10 +0000861 xmlDefaultSAXHandler.reference = reference;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000862 xmlDefaultSAXHandler.characters = characters;
863 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
864 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
Daniel Veillard517752b1999-04-05 12:20:10 +0000865 xmlDefaultSAXHandler.comment = comment;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000866 xmlDefaultSAXHandler.warning = xmlParserWarning;
867 xmlDefaultSAXHandler.error = xmlParserError;
868 xmlDefaultSAXHandler.fatalError = xmlParserError;
869}