blob: 05d70ab0397f3795ea69c100bd2301525ec2a031 [file] [log] [blame]
Owen Taylor3473f882001-02-23 17:55:21 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
3 *
4 * See Copyright for the status of this software.
5 *
Daniel Veillardc5d64342001-06-24 12:13:24 +00006 * Daniel Veillard <daniel@veillard.com>
Owen Taylor3473f882001-02-23 17:55:21 +00007 */
8
9
Bjorn Reese70a9da52001-04-21 16:57:29 +000010#include "libxml.h"
Owen Taylor3473f882001-02-23 17:55:21 +000011#include <stdlib.h>
12#include <string.h>
13#include <libxml/xmlmemory.h>
14#include <libxml/tree.h>
15#include <libxml/parser.h>
16#include <libxml/parserInternals.h>
17#include <libxml/valid.h>
18#include <libxml/entities.h>
19#include <libxml/xmlerror.h>
20#include <libxml/debugXML.h>
21#include <libxml/xmlIO.h>
22#include <libxml/SAX.h>
23#include <libxml/uri.h>
Daniel Veillard48da9102001-08-07 01:10:10 +000024#include <libxml/valid.h>
Owen Taylor3473f882001-02-23 17:55:21 +000025#include <libxml/HTMLtree.h>
26
27/* #define DEBUG_SAX */
28/* #define DEBUG_SAX_TREE */
29
30/**
31 * getPublicId:
32 * @ctx: the user data (XML parser context)
33 *
34 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
35 *
36 * Returns a xmlChar *
37 */
38const xmlChar *
Daniel Veillardc86a4fa2001-03-26 16:28:29 +000039getPublicId(void *ctx ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +000040{
41 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
42 return(NULL);
43}
44
45/**
46 * getSystemId:
47 * @ctx: the user data (XML parser context)
48 *
49 * Return the system ID, basically URL or filename e.g.
50 * http://www.sgmlsource.com/dtds/memo.dtd
51 *
52 * Returns a xmlChar *
53 */
54const xmlChar *
55getSystemId(void *ctx)
56{
57 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
Daniel Veillard56a4cb82001-03-24 17:00:36 +000058 return((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +000059}
60
61/**
62 * getLineNumber:
63 * @ctx: the user data (XML parser context)
64 *
65 * Return the line number of the current parsing point.
66 *
67 * Returns an int
68 */
69int
70getLineNumber(void *ctx)
71{
72 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
73 return(ctxt->input->line);
74}
75
76/**
77 * getColumnNumber:
78 * @ctx: the user data (XML parser context)
79 *
80 * Return the column number of the current parsing point.
81 *
82 * Returns an int
83 */
84int
85getColumnNumber(void *ctx)
86{
87 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
88 return(ctxt->input->col);
89}
90
91/*
92 * The default SAX Locator.
93 */
94
95xmlSAXLocator xmlDefaultSAXLocator = {
96 getPublicId, getSystemId, getLineNumber, getColumnNumber
97};
98
99/**
100 * isStandalone:
101 * @ctx: the user data (XML parser context)
102 *
103 * Is this document tagged standalone ?
104 *
105 * Returns 1 if true
106 */
107int
108isStandalone(void *ctx)
109{
110 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
111 return(ctxt->myDoc->standalone == 1);
112}
113
114/**
115 * hasInternalSubset:
116 * @ctx: the user data (XML parser context)
117 *
118 * Does this document has an internal subset
119 *
120 * Returns 1 if true
121 */
122int
123hasInternalSubset(void *ctx)
124{
125 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
126 return(ctxt->myDoc->intSubset != NULL);
127}
128
129/**
130 * hasExternalSubset:
131 * @ctx: the user data (XML parser context)
132 *
133 * Does this document has an external subset
134 *
135 * Returns 1 if true
136 */
137int
138hasExternalSubset(void *ctx)
139{
140 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
141 return(ctxt->myDoc->extSubset != NULL);
142}
143
144/**
145 * internalSubset:
146 * @ctx: the user data (XML parser context)
147 * @name: the root element name
148 * @ExternalID: the external ID
149 * @SystemID: the SYSTEM ID (e.g. filename or URL)
150 *
151 * Callback on internal subset declaration.
152 */
153void
154internalSubset(void *ctx, const xmlChar *name,
155 const xmlChar *ExternalID, const xmlChar *SystemID)
156{
157 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
158 xmlDtdPtr dtd;
159#ifdef DEBUG_SAX
160 xmlGenericError(xmlGenericErrorContext,
161 "SAX.internalSubset(%s, %s, %s)\n",
162 name, ExternalID, SystemID);
163#endif
164
165 if (ctxt->myDoc == NULL)
166 return;
167 dtd = xmlGetIntSubset(ctxt->myDoc);
168 if (dtd != NULL) {
169 if (ctxt->html)
170 return;
171 xmlUnlinkNode((xmlNodePtr) dtd);
172 xmlFreeDtd(dtd);
173 ctxt->myDoc->intSubset = NULL;
174 }
175 ctxt->myDoc->intSubset =
176 xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
177}
178
179/**
180 * externalSubset:
181 * @ctx: the user data (XML parser context)
182 * @name: the root element name
183 * @ExternalID: the external ID
184 * @SystemID: the SYSTEM ID (e.g. filename or URL)
185 *
186 * Callback on external subset declaration.
187 */
188void
189externalSubset(void *ctx, const xmlChar *name,
190 const xmlChar *ExternalID, const xmlChar *SystemID)
191{
192 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
193#ifdef DEBUG_SAX
194 xmlGenericError(xmlGenericErrorContext,
195 "SAX.externalSubset(%s, %s, %s)\n",
196 name, ExternalID, SystemID);
197#endif
198 if (((ExternalID != NULL) || (SystemID != NULL)) &&
Daniel Veillard9403a042001-05-28 11:00:53 +0000199 (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
Owen Taylor3473f882001-02-23 17:55:21 +0000200 (ctxt->wellFormed && ctxt->myDoc))) {
201 /*
202 * Try to fetch and parse the external subset.
203 */
204 xmlParserInputPtr oldinput;
205 int oldinputNr;
206 int oldinputMax;
207 xmlParserInputPtr *oldinputTab;
Owen Taylor3473f882001-02-23 17:55:21 +0000208 xmlParserInputPtr input = NULL;
209 xmlCharEncoding enc;
210 int oldcharset;
211
212 /*
213 * Ask the Entity resolver to load the damn thing
214 */
215 if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
216 input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
217 SystemID);
218 if (input == NULL) {
219 return;
220 }
221
222 xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
223
224 /*
225 * make sure we won't destroy the main document context
226 */
227 oldinput = ctxt->input;
228 oldinputNr = ctxt->inputNr;
229 oldinputMax = ctxt->inputMax;
230 oldinputTab = ctxt->inputTab;
Owen Taylor3473f882001-02-23 17:55:21 +0000231 oldcharset = ctxt->charset;
232
233 ctxt->inputTab = (xmlParserInputPtr *)
234 xmlMalloc(5 * sizeof(xmlParserInputPtr));
235 if (ctxt->inputTab == NULL) {
236 ctxt->errNo = XML_ERR_NO_MEMORY;
237 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
238 ctxt->sax->error(ctxt->userData,
239 "externalSubset: out of memory\n");
240 ctxt->errNo = XML_ERR_NO_MEMORY;
241 ctxt->input = oldinput;
242 ctxt->inputNr = oldinputNr;
243 ctxt->inputMax = oldinputMax;
244 ctxt->inputTab = oldinputTab;
245 ctxt->charset = oldcharset;
246 return;
247 }
248 ctxt->inputNr = 0;
249 ctxt->inputMax = 5;
250 ctxt->input = NULL;
251 xmlPushInput(ctxt, input);
252
253 /*
254 * On the fly encoding conversion if needed
255 */
256 enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
257 xmlSwitchEncoding(ctxt, enc);
258
259 if (input->filename == NULL)
260 input->filename = (char *) xmlStrdup(SystemID);
261 input->line = 1;
262 input->col = 1;
263 input->base = ctxt->input->cur;
264 input->cur = ctxt->input->cur;
265 input->free = NULL;
266
267 /*
268 * let's parse that entity knowing it's an external subset.
269 */
270 xmlParseExternalSubset(ctxt, ExternalID, SystemID);
271
272 /*
273 * Free up the external entities
274 */
275
276 while (ctxt->inputNr > 1)
277 xmlPopInput(ctxt);
278 xmlFreeInputStream(ctxt->input);
279 xmlFree(ctxt->inputTab);
280
281 /*
282 * Restore the parsing context of the main entity
283 */
284 ctxt->input = oldinput;
285 ctxt->inputNr = oldinputNr;
286 ctxt->inputMax = oldinputMax;
287 ctxt->inputTab = oldinputTab;
288 ctxt->charset = oldcharset;
289 /* ctxt->wellFormed = oldwellFormed; */
290 }
291}
292
293/**
294 * resolveEntity:
295 * @ctx: the user data (XML parser context)
296 * @publicId: The public ID of the entity
297 * @systemId: The system ID of the entity
298 *
299 * The entity loader, to control the loading of external entities,
300 * the application can either:
301 * - override this resolveEntity() callback in the SAX block
302 * - or better use the xmlSetExternalEntityLoader() function to
303 * set up it's own entity resolution routine
304 *
305 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
306 */
307xmlParserInputPtr
308resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
309{
310 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
311 xmlParserInputPtr ret;
312 xmlChar *URI;
313 const char *base = NULL;
314
315 if (ctxt->input != NULL)
316 base = ctxt->input->filename;
317 if (base == NULL)
318 base = ctxt->directory;
319
320 URI = xmlBuildURI(systemId, (const xmlChar *) base);
321
322#ifdef DEBUG_SAX
323 xmlGenericError(xmlGenericErrorContext,
324 "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
325#endif
326
327 ret = xmlLoadExternalEntity((const char *) URI,
328 (const char *) publicId, ctxt);
329 if (URI != NULL)
330 xmlFree(URI);
331 return(ret);
332}
333
334/**
335 * getEntity:
336 * @ctx: the user data (XML parser context)
337 * @name: The entity name
338 *
339 * Get an entity by name
340 *
341 * Returns the xmlEntityPtr if found.
342 */
343xmlEntityPtr
344getEntity(void *ctx, const xmlChar *name)
345{
346 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
347 xmlEntityPtr ret;
348
349#ifdef DEBUG_SAX
350 xmlGenericError(xmlGenericErrorContext,
351 "SAX.getEntity(%s)\n", name);
352#endif
353
354 ret = xmlGetDocEntity(ctxt->myDoc, name);
355 if ((ret != NULL) && (ctxt->validate) && (ret->children == NULL) &&
356 (ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
357 /*
358 * for validation purposes we really need to fetch and
359 * parse the external entity
360 */
Owen Taylor3473f882001-02-23 17:55:21 +0000361 xmlNodePtr children;
362
Daniel Veillard5015b712001-08-17 09:37:52 +0000363 xmlParseCtxtExternalEntity(ctxt, ret->URI, ret->ExternalID, &children);
Owen Taylor3473f882001-02-23 17:55:21 +0000364 xmlAddChildList((xmlNodePtr) ret, children);
365 }
366 return(ret);
367}
368
369/**
370 * getParameterEntity:
371 * @ctx: the user data (XML parser context)
372 * @name: The entity name
373 *
374 * Get a parameter entity by name
375 *
376 * Returns the xmlEntityPtr if found.
377 */
378xmlEntityPtr
379getParameterEntity(void *ctx, const xmlChar *name)
380{
381 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
382 xmlEntityPtr ret;
383
384#ifdef DEBUG_SAX
385 xmlGenericError(xmlGenericErrorContext,
386 "SAX.getParameterEntity(%s)\n", name);
387#endif
388
389 ret = xmlGetParameterEntity(ctxt->myDoc, name);
390 return(ret);
391}
392
393
394/**
395 * entityDecl:
396 * @ctx: the user data (XML parser context)
397 * @name: the entity name
398 * @type: the entity type
399 * @publicId: The public ID of the entity
400 * @systemId: The system ID of the entity
401 * @content: the entity value (without processing).
402 *
403 * An entity definition has been parsed
404 */
405void
406entityDecl(void *ctx, const xmlChar *name, int type,
407 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
408{
409 xmlEntityPtr ent;
410 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
411
412#ifdef DEBUG_SAX
413 xmlGenericError(xmlGenericErrorContext,
414 "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
415 name, type, publicId, systemId, content);
416#endif
417 if (ctxt->inSubset == 1) {
418 ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
419 systemId, content);
420 if ((ent == NULL) && (ctxt->pedantic) &&
421 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
422 ctxt->sax->warning(ctxt,
423 "Entity(%s) already defined in the internal subset\n", name);
424 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
425 xmlChar *URI;
426 const char *base = NULL;
427
428 if (ctxt->input != NULL)
429 base = ctxt->input->filename;
430 if (base == NULL)
431 base = ctxt->directory;
432
433 URI = xmlBuildURI(systemId, (const xmlChar *) base);
434 ent->URI = URI;
435 }
436 } else if (ctxt->inSubset == 2) {
437 ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
438 systemId, content);
439 if ((ent == NULL) && (ctxt->pedantic) &&
440 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
441 ctxt->sax->warning(ctxt,
442 "Entity(%s) already defined in the external subset\n", name);
443 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
444 xmlChar *URI;
445 const char *base = NULL;
446
447 if (ctxt->input != NULL)
448 base = ctxt->input->filename;
449 if (base == NULL)
450 base = ctxt->directory;
451
452 URI = xmlBuildURI(systemId, (const xmlChar *) base);
453 ent->URI = URI;
454 }
455 } else {
456 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
457 ctxt->sax->error(ctxt,
458 "SAX.entityDecl(%s) called while not in subset\n", name);
459 }
460}
461
462/**
463 * attributeDecl:
464 * @ctx: the user data (XML parser context)
465 * @elem: the name of the element
466 * @fullname: the attribute name
467 * @type: the attribute type
468 * @def: the type of default value
469 * @defaultValue: the attribute default value
470 * @tree: the tree of enumerated value set
471 *
472 * An attribute definition has been parsed
473 */
474void
475attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
476 int type, int def, const xmlChar *defaultValue,
477 xmlEnumerationPtr tree)
478{
479 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
480 xmlAttributePtr attr;
481 xmlChar *name = NULL, *prefix = NULL;
482
483#ifdef DEBUG_SAX
484 xmlGenericError(xmlGenericErrorContext,
485 "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
486 elem, fullname, type, def, defaultValue);
487#endif
488 name = xmlSplitQName(ctxt, fullname, &prefix);
489 if (ctxt->inSubset == 1)
490 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
491 name, prefix, (xmlAttributeType) type,
492 (xmlAttributeDefault) def, defaultValue, tree);
493 else if (ctxt->inSubset == 2)
494 attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
495 name, prefix, (xmlAttributeType) type,
496 (xmlAttributeDefault) def, defaultValue, tree);
497 else {
498 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
499 ctxt->sax->error(ctxt,
500 "SAX.attributeDecl(%s) called while not in subset\n", name);
501 return;
502 }
503 if (attr == 0) ctxt->valid = 0;
504 if (ctxt->validate && ctxt->wellFormed &&
505 ctxt->myDoc && ctxt->myDoc->intSubset)
506 ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
507 attr);
508 if (prefix != NULL)
509 xmlFree(prefix);
510 if (name != NULL)
511 xmlFree(name);
512}
513
514/**
515 * elementDecl:
516 * @ctx: the user data (XML parser context)
517 * @name: the element name
518 * @type: the element type
519 * @content: the element value tree
520 *
521 * An element definition has been parsed
522 */
523void
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000524elementDecl(void *ctx, const xmlChar * name, int type,
525 xmlElementContentPtr content)
Owen Taylor3473f882001-02-23 17:55:21 +0000526{
527 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
528 xmlElementPtr elem = NULL;
529
530#ifdef DEBUG_SAX
531 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000532 "SAX.elementDecl(%s, %d, ...)\n", name, type);
Owen Taylor3473f882001-02-23 17:55:21 +0000533#endif
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000534
Owen Taylor3473f882001-02-23 17:55:21 +0000535 if (ctxt->inSubset == 1)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000536 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
537 name, (xmlElementTypeVal) type, content);
Owen Taylor3473f882001-02-23 17:55:21 +0000538 else if (ctxt->inSubset == 2)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000539 elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
540 name, (xmlElementTypeVal) type, content);
Owen Taylor3473f882001-02-23 17:55:21 +0000541 else {
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000542 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
543 ctxt->sax->error(ctxt,
544 "SAX.elementDecl(%s) called while not in subset\n",
545 name);
546 return;
Owen Taylor3473f882001-02-23 17:55:21 +0000547 }
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000548 if (elem == NULL)
549 ctxt->valid = 0;
Owen Taylor3473f882001-02-23 17:55:21 +0000550 if (ctxt->validate && ctxt->wellFormed &&
551 ctxt->myDoc && ctxt->myDoc->intSubset)
Daniel Veillard1fd36d22001-07-04 22:54:28 +0000552 ctxt->valid &=
553 xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
Owen Taylor3473f882001-02-23 17:55:21 +0000554}
555
556/**
557 * notationDecl:
558 * @ctx: the user data (XML parser context)
559 * @name: The name of the notation
560 * @publicId: The public ID of the entity
561 * @systemId: The system ID of the entity
562 *
563 * What to do when a notation declaration has been parsed.
564 */
565void
566notationDecl(void *ctx, const xmlChar *name,
567 const xmlChar *publicId, const xmlChar *systemId)
568{
569 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
570 xmlNotationPtr nota = NULL;
571
572#ifdef DEBUG_SAX
573 xmlGenericError(xmlGenericErrorContext,
574 "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
575#endif
576
577 if (ctxt->inSubset == 1)
578 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
579 publicId, systemId);
580 else if (ctxt->inSubset == 2)
Daniel Veillard25239c12001-03-14 13:56:48 +0000581 nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
Owen Taylor3473f882001-02-23 17:55:21 +0000582 publicId, systemId);
583 else {
584 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
585 ctxt->sax->error(ctxt,
586 "SAX.notationDecl(%s) called while not in subset\n", name);
587 return;
588 }
589 if (nota == NULL) ctxt->valid = 0;
590 if (ctxt->validate && ctxt->wellFormed &&
591 ctxt->myDoc && ctxt->myDoc->intSubset)
592 ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
593 nota);
594}
595
596/**
597 * unparsedEntityDecl:
598 * @ctx: the user data (XML parser context)
599 * @name: The name of the entity
600 * @publicId: The public ID of the entity
601 * @systemId: The system ID of the entity
602 * @notationName: the name of the notation
603 *
604 * What to do when an unparsed entity declaration is parsed
605 */
606void
607unparsedEntityDecl(void *ctx, const xmlChar *name,
608 const xmlChar *publicId, const xmlChar *systemId,
609 const xmlChar *notationName)
610{
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000611 xmlEntityPtr ent;
Owen Taylor3473f882001-02-23 17:55:21 +0000612 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
613#ifdef DEBUG_SAX
614 xmlGenericError(xmlGenericErrorContext,
615 "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
616 name, publicId, systemId, notationName);
617#endif
618 if (ctxt->validate && ctxt->wellFormed &&
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000619 ctxt->myDoc && ctxt->myDoc->extSubset)
Owen Taylor3473f882001-02-23 17:55:21 +0000620 ctxt->valid &= xmlValidateNotationUse(&ctxt->vctxt, ctxt->myDoc,
621 notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000622 if (ctxt->inSubset == 1) {
623 ent = xmlAddDocEntity(ctxt->myDoc, name,
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000624 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
625 publicId, systemId, notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000626 if ((ent == NULL) && (ctxt->pedantic) &&
627 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
628 ctxt->sax->warning(ctxt,
629 "Entity(%s) already defined in the internal subset\n", name);
630 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
631 xmlChar *URI;
632 const char *base = NULL;
633
634 if (ctxt->input != NULL)
635 base = ctxt->input->filename;
636 if (base == NULL)
637 base = ctxt->directory;
638
639 URI = xmlBuildURI(systemId, (const xmlChar *) base);
640 ent->URI = URI;
641 }
642 } else if (ctxt->inSubset == 2) {
643 ent = xmlAddDtdEntity(ctxt->myDoc, name,
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000644 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
645 publicId, systemId, notationName);
Daniel Veillard9f4eb912001-08-01 21:22:27 +0000646 if ((ent == NULL) && (ctxt->pedantic) &&
647 (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
648 ctxt->sax->warning(ctxt,
649 "Entity(%s) already defined in the external subset\n", name);
650 if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
651 xmlChar *URI;
652 const char *base = NULL;
653
654 if (ctxt->input != NULL)
655 base = ctxt->input->filename;
656 if (base == NULL)
657 base = ctxt->directory;
658
659 URI = xmlBuildURI(systemId, (const xmlChar *) base);
660 ent->URI = URI;
661 }
662 } else {
Daniel Veillarde020c3a2001-03-21 18:06:15 +0000663 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
664 ctxt->sax->error(ctxt,
665 "SAX.unparsedEntityDecl(%s) called while not in subset\n", name);
666 }
Owen Taylor3473f882001-02-23 17:55:21 +0000667}
668
669/**
670 * setDocumentLocator:
671 * @ctx: the user data (XML parser context)
672 * @loc: A SAX Locator
673 *
674 * Receive the document locator at startup, actually xmlDefaultSAXLocator
675 * Everything is available on the context, so this is useless in our case.
676 */
677void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +0000678setDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +0000679{
680 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
681#ifdef DEBUG_SAX
682 xmlGenericError(xmlGenericErrorContext,
683 "SAX.setDocumentLocator()\n");
684#endif
685}
686
687/**
688 * startDocument:
689 * @ctx: the user data (XML parser context)
690 *
691 * called when the document start being processed.
692 */
693void
694startDocument(void *ctx)
695{
696 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
697 xmlDocPtr doc;
698
699#ifdef DEBUG_SAX
700 xmlGenericError(xmlGenericErrorContext,
701 "SAX.startDocument()\n");
702#endif
703 if (ctxt->html) {
704 if (ctxt->myDoc == NULL)
705#ifdef LIBXML_HTML_ENABLED
706 ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
707#else
708 xmlGenericError(xmlGenericErrorContext,
709 "libxml2 built without HTML support\n");
710#endif
711 } else {
712 doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
713 if (doc != NULL) {
714 if (ctxt->encoding != NULL)
715 doc->encoding = xmlStrdup(ctxt->encoding);
716 else
717 doc->encoding = NULL;
718 doc->standalone = ctxt->standalone;
719 }
720 }
721 if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
722 (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
Daniel Veillard56a4cb82001-03-24 17:00:36 +0000723 ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
Owen Taylor3473f882001-02-23 17:55:21 +0000724 }
725}
726
727/**
728 * endDocument:
729 * @ctx: the user data (XML parser context)
730 *
731 * called when the document end has been detected.
732 */
733void
734endDocument(void *ctx)
735{
736 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
737#ifdef DEBUG_SAX
738 xmlGenericError(xmlGenericErrorContext,
739 "SAX.endDocument()\n");
740#endif
741 if (ctxt->validate && ctxt->wellFormed &&
742 ctxt->myDoc && ctxt->myDoc->intSubset)
743 ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
744
745 /*
746 * Grab the encoding if it was added on-the-fly
747 */
748 if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
749 (ctxt->myDoc->encoding == NULL)) {
750 ctxt->myDoc->encoding = ctxt->encoding;
751 ctxt->encoding = NULL;
752 }
753 if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
754 (ctxt->myDoc->encoding == NULL)) {
755 ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
756 }
757 if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
758 (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
759 ctxt->myDoc->charset = ctxt->charset;
760 }
761}
762
763/**
764 * attribute:
765 * @ctx: the user data (XML parser context)
766 * @fullname: The attribute name, including namespace prefix
767 * @value: The attribute value
768 *
769 * Handle an attribute that has been read by the parser.
770 * The default handling is to convert the attribute into an
771 * DOM subtree and past it in a new xmlAttr element added to
772 * the element.
773 */
774void
775attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
776{
777 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
778 xmlAttrPtr ret;
779 xmlChar *name;
780 xmlChar *ns;
781 xmlChar *nval;
782 xmlNsPtr namespace;
783
784/****************
785#ifdef DEBUG_SAX
786 xmlGenericError(xmlGenericErrorContext,
787 "SAX.attribute(%s, %s)\n", fullname, value);
788#endif
789 ****************/
790 /*
791 * Split the full name into a namespace prefix and the tag name
792 */
793 name = xmlSplitQName(ctxt, fullname, &ns);
794
795 /*
796 * Do the last stage of the attribute normalization
797 * Needed for HTML too:
798 * http://www.w3.org/TR/html4/types.html#h-6.2
799 */
800 nval = xmlValidNormalizeAttributeValue(ctxt->myDoc, ctxt->node,
801 fullname, value);
802 if (nval != NULL)
803 value = nval;
804
805 /*
806 * Check whether it's a namespace definition
807 */
808 if ((!ctxt->html) && (ns == NULL) &&
809 (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
810 (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
811 if (value[0] != 0) {
812 xmlURIPtr uri;
813
814 uri = xmlParseURI((const char *)value);
815 if (uri == NULL) {
816 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
817 ctxt->sax->warning(ctxt->userData,
818 "nmlns: %s not a valid URI\n", value);
819 } else {
820 if (uri->scheme == NULL) {
821 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
822 ctxt->sax->warning(ctxt->userData,
823 "nmlns: URI %s is not absolute\n", value);
824 }
825 xmlFreeURI(uri);
826 }
827 }
828
829 /* a default namespace definition */
830 xmlNewNs(ctxt->node, value, NULL);
831 if (name != NULL)
832 xmlFree(name);
833 if (nval != NULL)
834 xmlFree(nval);
835 return;
836 }
837 if ((!ctxt->html) &&
838 (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
839 (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
840 /*
841 * Validate also for namespace decls, they are attributes from
842 * an XML-1.0 perspective
843 TODO ... doesn't map well with current API
844 if (ctxt->validate && ctxt->wellFormed &&
845 ctxt->myDoc && ctxt->myDoc->intSubset)
846 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
847 ctxt->node, ret, value);
848 */
849 /* a standard namespace definition */
850 xmlNewNs(ctxt->node, value, name);
851 xmlFree(ns);
852 if (name != NULL)
853 xmlFree(name);
854 if (nval != NULL)
855 xmlFree(nval);
856 return;
857 }
858
859 if (ns != NULL)
860 namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
861 else {
862 namespace = NULL;
863 }
864
865 /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
866 ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
867
868 if (ret != NULL) {
869 if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
870 xmlNodePtr tmp;
871
872 ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
873 tmp = ret->children;
874 while (tmp != NULL) {
875 tmp->parent = (xmlNodePtr) ret;
876 if (tmp->next == NULL)
877 ret->last = tmp;
878 tmp = tmp->next;
879 }
880 } else if (value != NULL) {
881 ret->children = xmlNewDocText(ctxt->myDoc, value);
882 ret->last = ret->children;
883 if (ret->children != NULL)
884 ret->children->parent = (xmlNodePtr) ret;
885 }
886 }
887
888 if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
889 ctxt->myDoc && ctxt->myDoc->intSubset) {
890
891 /*
892 * If we don't substitute entities, the validation should be
893 * done on a value with replaced entities anyway.
894 */
895 if (!ctxt->replaceEntities) {
896 xmlChar *val;
897
898 ctxt->depth++;
899 val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
900 0,0,0);
901 ctxt->depth--;
902 if (val == NULL)
903 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
904 ctxt->myDoc, ctxt->node, ret, value);
905 else {
906 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
907 ctxt->myDoc, ctxt->node, ret, val);
908 xmlFree(val);
909 }
910 } else {
911 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
912 ctxt->node, ret, value);
913 }
Daniel Veillard62f313b2001-07-04 19:49:14 +0000914 } else if (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
915 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) {
Owen Taylor3473f882001-02-23 17:55:21 +0000916 /*
917 * when validating, the ID registration is done at the attribute
918 * validation level. Otherwise we have to do specific handling here.
919 */
920 if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
921 xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
922 else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
923 xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
924 }
925
926 if (nval != NULL)
927 xmlFree(nval);
928 if (name != NULL)
929 xmlFree(name);
930 if (ns != NULL)
931 xmlFree(ns);
932}
933
934/**
935 * startElement:
936 * @ctx: the user data (XML parser context)
937 * @fullname: The element name, including namespace prefix
938 * @atts: An array of name/value attributes pairs, NULL terminated
939 *
940 * called when an opening tag has been processed.
941 */
942void
943startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
944{
945 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
946 xmlNodePtr ret;
947 xmlNodePtr parent = ctxt->node;
948 xmlNsPtr ns;
949 xmlChar *name;
950 xmlChar *prefix;
951 const xmlChar *att;
952 const xmlChar *value;
953 int i;
954
955#ifdef DEBUG_SAX
956 xmlGenericError(xmlGenericErrorContext,
957 "SAX.startElement(%s)\n", fullname);
958#endif
959
960 /*
961 * First check on validity:
962 */
963 if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
964 ((ctxt->myDoc->intSubset == NULL) ||
965 ((ctxt->myDoc->intSubset->notations == NULL) &&
966 (ctxt->myDoc->intSubset->elements == NULL) &&
967 (ctxt->myDoc->intSubset->attributes == NULL) &&
968 (ctxt->myDoc->intSubset->entities == NULL)))) {
969 if (ctxt->vctxt.error != NULL) {
970 ctxt->vctxt.error(ctxt->vctxt.userData,
971 "Validation failed: no DTD found !\n");
972 }
973 ctxt->validate = 0;
974 }
975
976
977 /*
978 * Split the full name into a namespace prefix and the tag name
979 */
980 name = xmlSplitQName(ctxt, fullname, &prefix);
981
982
983 /*
984 * Note : the namespace resolution is deferred until the end of the
985 * attributes parsing, since local namespace can be defined as
986 * an attribute at this level.
987 */
988 ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
989 if (ret == NULL) return;
990 if (ctxt->myDoc->children == NULL) {
991#ifdef DEBUG_SAX_TREE
992 xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
993#endif
994 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
995 } else if (parent == NULL) {
996 parent = ctxt->myDoc->children;
997 }
998 ctxt->nodemem = -1;
Daniel Veillardd9bad132001-07-23 19:39:43 +0000999 if (ctxt->linenumbers) {
1000 if (ctxt->input != NULL)
1001 ret->content = (void *) (long) ctxt->input->line;
1002 }
Owen Taylor3473f882001-02-23 17:55:21 +00001003
1004 /*
1005 * We are parsing a new node.
1006 */
1007#ifdef DEBUG_SAX_TREE
1008 xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1009#endif
1010 nodePush(ctxt, ret);
1011
1012 /*
1013 * Link the child element
1014 */
1015 if (parent != NULL) {
1016 if (parent->type == XML_ELEMENT_NODE) {
1017#ifdef DEBUG_SAX_TREE
1018 xmlGenericError(xmlGenericErrorContext,
1019 "adding child %s to %s\n", name, parent->name);
1020#endif
1021 xmlAddChild(parent, ret);
1022 } else {
1023#ifdef DEBUG_SAX_TREE
1024 xmlGenericError(xmlGenericErrorContext,
1025 "adding sibling %s to ", name);
1026 xmlDebugDumpOneNode(stderr, parent, 0);
1027#endif
1028 xmlAddSibling(parent, ret);
1029 }
1030 }
1031
1032 /*
Daniel Veillard48da9102001-08-07 01:10:10 +00001033 * Insert all the defaulted attributes from the DTD especially namespaces
1034 */
1035 if ((!ctxt->html) &&
1036 ((ctxt->myDoc->intSubset != NULL) ||
1037 (ctxt->myDoc->extSubset != NULL))) {
1038 xmlElementPtr elemDecl = NULL;
1039
1040 if (prefix != NULL) {
1041 if (ctxt->myDoc->intSubset != NULL)
1042 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
1043 name, prefix);
1044 if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
1045 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1046 name, prefix);
1047 } else {
1048 if (ctxt->myDoc->intSubset != NULL)
1049 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset,
1050 name, prefix);
1051 if ((elemDecl == NULL) && (ctxt->myDoc->extSubset != NULL))
1052 elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1053 name, prefix);
1054 }
1055 if (elemDecl != NULL) {
1056 xmlAttributePtr attr = elemDecl->attributes;
1057 while (attr != NULL) {
1058 if (attr->defaultValue != NULL) {
1059 /*
1060 * the element should be instanciated in the tree if:
1061 * - this is a namespace prefix
1062 * - the user required for completion in the tree
1063 * like XSLT
1064 */
1065 if (((attr->prefix != NULL) &&
1066 (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1067 ((attr->prefix == NULL) &&
1068 (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1069 (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1070 xmlChar buffer[100];
1071 const xmlChar *fulln = attr->name;
1072
1073 if (attr->prefix != NULL) {
1074 snprintf((char *) buffer, 99, "%s:%s",
1075 attr->prefix, attr->name);
1076 buffer[99] = 0;
1077 fulln = buffer;
1078 }
1079
1080 /*
1081 * Check that the attribute is not declared in the
1082 * serialization
1083 */
1084 att = NULL;
1085 if (atts != NULL) {
1086 i = 0;
1087 att = atts[i];
1088 while (att != NULL) {
1089 if (xmlStrEqual(att, fulln))
1090 break;
1091 i += 2;
1092 att = atts[i];
1093 }
1094 }
1095 if (att == NULL)
1096 attribute(ctxt, fulln, attr->defaultValue);
1097 }
1098 }
1099 attr = attr->nexth;
1100 }
1101 }
1102 }
1103
1104 /*
Owen Taylor3473f882001-02-23 17:55:21 +00001105 * process all the attributes whose name start with "xml"
1106 */
1107 if (atts != NULL) {
1108 i = 0;
1109 att = atts[i++];
1110 value = atts[i++];
1111 if (!ctxt->html) {
1112 while ((att != NULL) && (value != NULL)) {
1113 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
1114 attribute(ctxt, att, value);
1115
1116 att = atts[i++];
1117 value = atts[i++];
1118 }
1119 }
1120 }
1121
1122 /*
1123 * Search the namespace, note that since the attributes have been
1124 * processed, the local namespaces are available.
1125 */
1126 ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1127 if ((ns == NULL) && (parent != NULL))
1128 ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1129 if ((prefix != NULL) && (ns == NULL)) {
1130 ns = xmlNewNs(ret, NULL, prefix);
1131 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1132 ctxt->sax->warning(ctxt->userData,
1133 "Namespace prefix %s is not defined\n", prefix);
1134 }
1135 xmlSetNs(ret, ns);
1136
1137 /*
1138 * process all the other attributes
1139 */
1140 if (atts != NULL) {
1141 i = 0;
1142 att = atts[i++];
1143 value = atts[i++];
1144 if (ctxt->html) {
1145 while (att != NULL) {
1146 attribute(ctxt, att, value);
1147 att = atts[i++];
1148 value = atts[i++];
1149 }
1150 } else {
1151 while ((att != NULL) && (value != NULL)) {
1152 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
1153 attribute(ctxt, att, value);
1154
1155 /*
1156 * Next ones
1157 */
1158 att = atts[i++];
1159 value = atts[i++];
1160 }
1161 }
1162 }
1163
1164 /*
1165 * If it's the Document root, finish the Dtd validation and
1166 * check the document root element for validity
1167 */
1168 if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1169 ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1170 ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1171 ctxt->vctxt.finishDtd = 1;
1172 }
1173
1174 if (prefix != NULL)
1175 xmlFree(prefix);
1176 if (name != NULL)
1177 xmlFree(name);
1178
1179}
1180
1181/**
1182 * endElement:
1183 * @ctx: the user data (XML parser context)
1184 * @name: The element name
1185 *
1186 * called when the end of an element has been detected.
1187 */
1188void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001189endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001190{
1191 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1192 xmlParserNodeInfo node_info;
1193 xmlNodePtr cur = ctxt->node;
1194
1195#ifdef DEBUG_SAX
1196 if (name == NULL)
1197 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1198 else
1199 xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1200#endif
1201
1202 /* Capture end position and add node */
1203 if (cur != NULL && ctxt->record_info) {
1204 node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1205 node_info.end_line = ctxt->input->line;
1206 node_info.node = cur;
1207 xmlParserAddNodeInfo(ctxt, &node_info);
1208 }
1209 ctxt->nodemem = -1;
1210
1211 if (ctxt->validate && ctxt->wellFormed &&
1212 ctxt->myDoc && ctxt->myDoc->intSubset)
1213 ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1214 cur);
1215
1216
1217 /*
1218 * end of parsing of this node.
1219 */
1220#ifdef DEBUG_SAX_TREE
1221 xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1222#endif
1223 nodePop(ctxt);
1224}
1225
1226/**
1227 * reference:
1228 * @ctx: the user data (XML parser context)
1229 * @name: The entity name
1230 *
1231 * called when an entity reference is detected.
1232 */
1233void
1234reference(void *ctx, const xmlChar *name)
1235{
1236 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1237 xmlNodePtr ret;
1238
1239#ifdef DEBUG_SAX
1240 xmlGenericError(xmlGenericErrorContext,
1241 "SAX.reference(%s)\n", name);
1242#endif
1243 if (name[0] == '#')
1244 ret = xmlNewCharRef(ctxt->myDoc, name);
1245 else
1246 ret = xmlNewReference(ctxt->myDoc, name);
1247#ifdef DEBUG_SAX_TREE
1248 xmlGenericError(xmlGenericErrorContext,
1249 "add reference %s to %s \n", name, ctxt->node->name);
1250#endif
1251 xmlAddChild(ctxt->node, ret);
1252}
1253
1254/**
1255 * characters:
1256 * @ctx: the user data (XML parser context)
1257 * @ch: a xmlChar string
1258 * @len: the number of xmlChar
1259 *
1260 * receiving some chars from the parser.
1261 * Question: how much at a time ???
1262 */
1263void
1264characters(void *ctx, const xmlChar *ch, int len)
1265{
1266 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1267 xmlNodePtr lastChild;
1268
1269#ifdef DEBUG_SAX
1270 xmlGenericError(xmlGenericErrorContext,
1271 "SAX.characters(%.30s, %d)\n", ch, len);
1272#endif
1273 /*
1274 * Handle the data if any. If there is no child
1275 * add it as content, otherwise if the last child is text,
1276 * concatenate it, else create a new node of type text.
1277 */
1278
1279 if (ctxt->node == NULL) {
1280#ifdef DEBUG_SAX_TREE
1281 xmlGenericError(xmlGenericErrorContext,
1282 "add chars: ctxt->node == NULL !\n");
1283#endif
1284 return;
1285 }
1286 lastChild = xmlGetLastChild(ctxt->node);
1287#ifdef DEBUG_SAX_TREE
1288 xmlGenericError(xmlGenericErrorContext,
1289 "add chars to %s \n", ctxt->node->name);
1290#endif
1291
1292 /*
1293 * Here we needed an accelerator mechanism in case of very large
1294 * elements. Use an attribute in the structure !!!
1295 */
1296 if (lastChild == NULL) {
1297 /* first node, first time */
1298 xmlNodeAddContentLen(ctxt->node, ch, len);
1299#ifndef XML_USE_BUFFER_CONTENT
1300 if (ctxt->node->children != NULL) {
1301 ctxt->nodelen = len;
1302 ctxt->nodemem = len + 1;
1303 }
1304#endif
1305 } else {
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001306 int coalesceText = (lastChild != NULL) &&
1307 (lastChild->type == XML_TEXT_NODE) &&
1308 (lastChild->name == xmlStringText);
1309 if ((coalesceText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001310#ifndef XML_USE_BUFFER_CONTENT
1311 /*
1312 * The whole point of maintaining nodelen and nodemem,
1313 * xmlTextConcat is too costly, i.e. compute lenght,
1314 * reallocate a new buffer, move data, append ch. Here
1315 * We try to minimaze realloc() uses and avoid copying
1316 * and recomputing lenght over and over.
1317 */
1318 if (ctxt->nodelen + len >= ctxt->nodemem) {
1319 xmlChar *newbuf;
1320 int size;
1321
1322 size = ctxt->nodemem + len;
1323 size *= 2;
1324 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1325 if (newbuf == NULL) {
1326 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1327 ctxt->sax->error(ctxt->userData,
1328 "SAX.characters(): out of memory\n");
1329 return;
1330 }
1331 ctxt->nodemem = size;
1332 lastChild->content = newbuf;
1333 }
1334 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1335 ctxt->nodelen += len;
1336 lastChild->content[ctxt->nodelen] = 0;
1337#else
1338 xmlTextConcat(lastChild, ch, len);
1339#endif
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001340 } else if (coalesceText) {
Daniel Veillard80f32572001-03-07 19:45:40 +00001341 xmlTextConcat(lastChild, ch, len);
1342 if (ctxt->node->children != NULL) {
1343 ctxt->nodelen = xmlStrlen(lastChild->content);
1344 ctxt->nodemem = ctxt->nodelen + 1;
1345 }
Owen Taylor3473f882001-02-23 17:55:21 +00001346 } else {
1347 /* Mixed content, first time */
1348 lastChild = xmlNewTextLen(ch, len);
1349 xmlAddChild(ctxt->node, lastChild);
1350#ifndef XML_USE_BUFFER_CONTENT
1351 if (ctxt->node->children != NULL) {
1352 ctxt->nodelen = len;
1353 ctxt->nodemem = len + 1;
1354 }
1355#endif
1356 }
1357 }
1358}
1359
1360/**
1361 * ignorableWhitespace:
1362 * @ctx: the user data (XML parser context)
1363 * @ch: a xmlChar string
1364 * @len: the number of xmlChar
1365 *
1366 * receiving some ignorable whitespaces from the parser.
1367 * Question: how much at a time ???
1368 */
1369void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001370ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001371{
1372 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1373#ifdef DEBUG_SAX
1374 xmlGenericError(xmlGenericErrorContext,
1375 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1376#endif
1377}
1378
1379/**
1380 * processingInstruction:
1381 * @ctx: the user data (XML parser context)
1382 * @target: the target name
1383 * @data: the PI data's
1384 *
1385 * A processing instruction has been parsed.
1386 */
1387void
1388processingInstruction(void *ctx, const xmlChar *target,
1389 const xmlChar *data)
1390{
1391 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1392 xmlNodePtr ret;
1393 xmlNodePtr parent = ctxt->node;
1394
1395#ifdef DEBUG_SAX
1396 xmlGenericError(xmlGenericErrorContext,
1397 "SAX.processingInstruction(%s, %s)\n", target, data);
1398#endif
1399
1400 ret = xmlNewPI(target, data);
1401 if (ret == NULL) return;
1402 parent = ctxt->node;
1403
1404 if (ctxt->inSubset == 1) {
1405 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1406 return;
1407 } else if (ctxt->inSubset == 2) {
1408 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1409 return;
1410 }
1411 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1412#ifdef DEBUG_SAX_TREE
1413 xmlGenericError(xmlGenericErrorContext,
1414 "Setting PI %s as root\n", target);
1415#endif
1416 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1417 return;
1418 }
1419 if (parent->type == XML_ELEMENT_NODE) {
1420#ifdef DEBUG_SAX_TREE
1421 xmlGenericError(xmlGenericErrorContext,
1422 "adding PI %s child to %s\n", target, parent->name);
1423#endif
1424 xmlAddChild(parent, ret);
1425 } else {
1426#ifdef DEBUG_SAX_TREE
1427 xmlGenericError(xmlGenericErrorContext,
1428 "adding PI %s sibling to ", target);
1429 xmlDebugDumpOneNode(stderr, parent, 0);
1430#endif
1431 xmlAddSibling(parent, ret);
1432 }
1433}
1434
1435/**
1436 * globalNamespace:
1437 * @ctx: the user data (XML parser context)
1438 * @href: the namespace associated URN
1439 * @prefix: the namespace prefix
1440 *
1441 * An old global namespace has been parsed.
1442 */
1443void
1444globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1445{
1446 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1447#ifdef DEBUG_SAX
1448 xmlGenericError(xmlGenericErrorContext,
1449 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1450#endif
1451 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1452}
1453
1454/**
1455 * setNamespace:
1456 * @ctx: the user data (XML parser context)
1457 * @name: the namespace prefix
1458 *
1459 * Set the current element namespace.
1460 */
1461
1462void
1463setNamespace(void *ctx, const xmlChar *name)
1464{
1465 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1466 xmlNsPtr ns;
1467 xmlNodePtr parent;
1468
1469#ifdef DEBUG_SAX
1470 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1471#endif
1472 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1473 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1474 if (ctxt->nodeNr >= 2) {
1475 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1476 if (parent != NULL)
1477 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1478 }
1479 }
1480 xmlSetNs(ctxt->node, ns);
1481}
1482
1483/**
1484 * getNamespace:
1485 * @ctx: the user data (XML parser context)
1486 *
1487 * Get the current element namespace.
1488 *
1489 * Returns the xmlNsPtr or NULL if none
1490 */
1491
1492xmlNsPtr
1493getNamespace(void *ctx)
1494{
1495 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1496 xmlNsPtr ret;
1497
1498#ifdef DEBUG_SAX
1499 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1500#endif
1501 ret = ctxt->node->ns;
1502 return(ret);
1503}
1504
1505/**
1506 * checkNamespace:
1507 * @ctx: the user data (XML parser context)
1508 * @namespace: the namespace to check against
1509 *
1510 * Check that the current element namespace is the same as the
1511 * one read upon parsing.
1512 *
1513 * Returns 1 if true 0 otherwise
1514 */
1515
1516int
1517checkNamespace(void *ctx, xmlChar *namespace)
1518{
1519 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1520 xmlNodePtr cur = ctxt->node;
1521
1522#ifdef DEBUG_SAX
1523 xmlGenericError(xmlGenericErrorContext,
1524 "SAX.checkNamespace(%s)\n", namespace);
1525#endif
1526
1527 /*
1528 * Check that the Name in the ETag is the same as in the STag.
1529 */
1530 if (namespace == NULL) {
1531 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1532 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1533 ctxt->sax->error(ctxt,
1534 "End tags for %s don't hold the namespace %s\n",
1535 cur->name, cur->ns->prefix);
1536 ctxt->wellFormed = 0;
1537 }
1538 } else {
1539 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1540 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1541 ctxt->sax->error(ctxt,
1542 "End tags %s holds a prefix %s not used by the open tag\n",
1543 cur->name, namespace);
1544 ctxt->wellFormed = 0;
1545 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1546 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1547 ctxt->sax->error(ctxt,
1548 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1549 cur->name, cur->ns->prefix, namespace);
1550 ctxt->wellFormed = 0;
1551 } else
1552 return(1);
1553 }
1554 return(0);
1555}
1556
1557/**
1558 * namespaceDecl:
1559 * @ctx: the user data (XML parser context)
1560 * @href: the namespace associated URN
1561 * @prefix: the namespace prefix
1562 *
1563 * A namespace has been parsed.
1564 */
1565void
1566namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1567{
1568 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1569#ifdef DEBUG_SAX
1570 if (prefix == NULL)
1571 xmlGenericError(xmlGenericErrorContext,
1572 "SAX.namespaceDecl(%s, NULL)\n", href);
1573 else
1574 xmlGenericError(xmlGenericErrorContext,
1575 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1576#endif
1577 xmlNewNs(ctxt->node, href, prefix);
1578}
1579
1580/**
1581 * comment:
1582 * @ctx: the user data (XML parser context)
1583 * @value: the comment content
1584 *
1585 * A comment has been parsed.
1586 */
1587void
1588comment(void *ctx, const xmlChar *value)
1589{
1590 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1591 xmlNodePtr ret;
1592 xmlNodePtr parent = ctxt->node;
1593
1594#ifdef DEBUG_SAX
1595 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1596#endif
1597 ret = xmlNewDocComment(ctxt->myDoc, value);
1598 if (ret == NULL) return;
1599
1600 if (ctxt->inSubset == 1) {
1601 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1602 return;
1603 } else if (ctxt->inSubset == 2) {
1604 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1605 return;
1606 }
1607 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1608#ifdef DEBUG_SAX_TREE
1609 xmlGenericError(xmlGenericErrorContext,
1610 "Setting comment as root\n");
1611#endif
1612 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1613 return;
1614 }
1615 if (parent->type == XML_ELEMENT_NODE) {
1616#ifdef DEBUG_SAX_TREE
1617 xmlGenericError(xmlGenericErrorContext,
1618 "adding comment child to %s\n", parent->name);
1619#endif
1620 xmlAddChild(parent, ret);
1621 } else {
1622#ifdef DEBUG_SAX_TREE
1623 xmlGenericError(xmlGenericErrorContext,
1624 "adding comment sibling to ");
1625 xmlDebugDumpOneNode(stderr, parent, 0);
1626#endif
1627 xmlAddSibling(parent, ret);
1628 }
1629}
1630
1631/**
1632 * cdataBlock:
1633 * @ctx: the user data (XML parser context)
1634 * @value: The pcdata content
1635 * @len: the block length
1636 *
1637 * called when a pcdata block has been parsed
1638 */
1639void
1640cdataBlock(void *ctx, const xmlChar *value, int len)
1641{
1642 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1643 xmlNodePtr ret, lastChild;
1644
1645#ifdef DEBUG_SAX
1646 xmlGenericError(xmlGenericErrorContext,
1647 "SAX.pcdata(%.10s, %d)\n", value, len);
1648#endif
1649 lastChild = xmlGetLastChild(ctxt->node);
1650#ifdef DEBUG_SAX_TREE
1651 xmlGenericError(xmlGenericErrorContext,
1652 "add chars to %s \n", ctxt->node->name);
1653#endif
1654 if ((lastChild != NULL) &&
1655 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1656 xmlTextConcat(lastChild, value, len);
1657 } else {
1658 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1659 xmlAddChild(ctxt->node, ret);
1660 }
1661}
1662
1663/*
1664 * Default handler for XML, builds the DOM tree
1665 */
1666xmlSAXHandler xmlDefaultSAXHandler = {
1667 internalSubset,
1668 isStandalone,
1669 hasInternalSubset,
1670 hasExternalSubset,
1671 resolveEntity,
1672 getEntity,
1673 entityDecl,
1674 notationDecl,
1675 attributeDecl,
1676 elementDecl,
1677 unparsedEntityDecl,
1678 setDocumentLocator,
1679 startDocument,
1680 endDocument,
1681 startElement,
1682 endElement,
1683 reference,
1684 characters,
1685 ignorableWhitespace,
1686 processingInstruction,
1687 comment,
1688 xmlParserWarning,
1689 xmlParserError,
1690 xmlParserError,
1691 getParameterEntity,
1692 cdataBlock,
1693 externalSubset,
1694};
1695
1696/**
1697 * xmlDefaultSAXHandlerInit:
1698 *
1699 * Initialize the default SAX handler
1700 */
1701void
1702xmlDefaultSAXHandlerInit(void)
1703{
Daniel Veillard7583a592001-07-08 13:15:55 +00001704 static int xmlSAXInitialized = 0;
1705 if (xmlSAXInitialized)
1706 return;
1707
Owen Taylor3473f882001-02-23 17:55:21 +00001708 xmlDefaultSAXHandler.internalSubset = internalSubset;
1709 xmlDefaultSAXHandler.externalSubset = externalSubset;
1710 xmlDefaultSAXHandler.isStandalone = isStandalone;
1711 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1712 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1713 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1714 xmlDefaultSAXHandler.getEntity = getEntity;
1715 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1716 xmlDefaultSAXHandler.entityDecl = entityDecl;
1717 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1718 xmlDefaultSAXHandler.elementDecl = elementDecl;
1719 xmlDefaultSAXHandler.notationDecl = notationDecl;
1720 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1721 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1722 xmlDefaultSAXHandler.startDocument = startDocument;
1723 xmlDefaultSAXHandler.endDocument = endDocument;
1724 xmlDefaultSAXHandler.startElement = startElement;
1725 xmlDefaultSAXHandler.endElement = endElement;
1726 xmlDefaultSAXHandler.reference = reference;
1727 xmlDefaultSAXHandler.characters = characters;
1728 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1729 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1730 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1731 xmlDefaultSAXHandler.comment = comment;
1732 if (xmlGetWarningsDefaultValue == 0)
1733 xmlDefaultSAXHandler.warning = NULL;
1734 else
1735 xmlDefaultSAXHandler.warning = xmlParserWarning;
1736 xmlDefaultSAXHandler.error = xmlParserError;
1737 xmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001738
1739 xmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001740}
1741
Daniel Veillardeae522a2001-04-23 13:41:34 +00001742#ifdef LIBXML_HTML_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001743/*
1744 * Default handler for HTML, builds the DOM tree
1745 */
1746xmlSAXHandler htmlDefaultSAXHandler = {
1747 internalSubset,
1748 NULL,
1749 NULL,
1750 NULL,
1751 NULL,
1752 getEntity,
1753 NULL,
1754 NULL,
1755 NULL,
1756 NULL,
1757 NULL,
1758 setDocumentLocator,
1759 startDocument,
1760 endDocument,
1761 startElement,
1762 endElement,
1763 NULL,
1764 characters,
1765 ignorableWhitespace,
1766 NULL,
1767 comment,
1768 xmlParserWarning,
1769 xmlParserError,
1770 xmlParserError,
1771 getParameterEntity,
1772 cdataBlock,
1773 NULL,
1774};
1775
1776/**
1777 * htmlDefaultSAXHandlerInit:
1778 *
1779 * Initialize the default SAX handler
1780 */
1781void
1782htmlDefaultSAXHandlerInit(void)
1783{
Daniel Veillard7583a592001-07-08 13:15:55 +00001784 static int htmlSAXInitialized = 0;
1785 if (htmlSAXInitialized)
1786 return;
1787
Owen Taylor3473f882001-02-23 17:55:21 +00001788 htmlDefaultSAXHandler.internalSubset = internalSubset;
1789 htmlDefaultSAXHandler.externalSubset = NULL;
1790 htmlDefaultSAXHandler.isStandalone = NULL;
1791 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1792 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1793 htmlDefaultSAXHandler.resolveEntity = NULL;
1794 htmlDefaultSAXHandler.getEntity = getEntity;
1795 htmlDefaultSAXHandler.getParameterEntity = NULL;
1796 htmlDefaultSAXHandler.entityDecl = NULL;
1797 htmlDefaultSAXHandler.attributeDecl = NULL;
1798 htmlDefaultSAXHandler.elementDecl = NULL;
1799 htmlDefaultSAXHandler.notationDecl = NULL;
1800 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1801 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1802 htmlDefaultSAXHandler.startDocument = startDocument;
1803 htmlDefaultSAXHandler.endDocument = endDocument;
1804 htmlDefaultSAXHandler.startElement = startElement;
1805 htmlDefaultSAXHandler.endElement = endElement;
1806 htmlDefaultSAXHandler.reference = NULL;
1807 htmlDefaultSAXHandler.characters = characters;
1808 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1809 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1810 htmlDefaultSAXHandler.processingInstruction = NULL;
1811 htmlDefaultSAXHandler.comment = comment;
1812 htmlDefaultSAXHandler.warning = xmlParserWarning;
1813 htmlDefaultSAXHandler.error = xmlParserError;
1814 htmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001815
1816 htmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001817}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001818#endif /* LIBXML_HTML_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001819
Daniel Veillardeae522a2001-04-23 13:41:34 +00001820#ifdef LIBXML_DOCB_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001821/*
Daniel Veillardeae522a2001-04-23 13:41:34 +00001822 * Default handler for SGML DocBook, builds the DOM tree
Owen Taylor3473f882001-02-23 17:55:21 +00001823 */
Daniel Veillardeae522a2001-04-23 13:41:34 +00001824xmlSAXHandler docbDefaultSAXHandler = {
Owen Taylor3473f882001-02-23 17:55:21 +00001825 internalSubset,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001826 isStandalone,
1827 hasInternalSubset,
1828 hasExternalSubset,
1829 resolveEntity,
Owen Taylor3473f882001-02-23 17:55:21 +00001830 getEntity,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001831 entityDecl,
Owen Taylor3473f882001-02-23 17:55:21 +00001832 NULL,
1833 NULL,
1834 NULL,
1835 NULL,
1836 setDocumentLocator,
1837 startDocument,
1838 endDocument,
1839 startElement,
1840 endElement,
Daniel Veillard1034da22001-04-25 19:06:28 +00001841 reference,
Owen Taylor3473f882001-02-23 17:55:21 +00001842 characters,
1843 ignorableWhitespace,
1844 NULL,
1845 comment,
1846 xmlParserWarning,
1847 xmlParserError,
1848 xmlParserError,
1849 getParameterEntity,
1850 NULL,
1851 NULL,
1852};
1853
1854/**
Daniel Veillardeae522a2001-04-23 13:41:34 +00001855 * docbDefaultSAXHandlerInit:
Owen Taylor3473f882001-02-23 17:55:21 +00001856 *
1857 * Initialize the default SAX handler
1858 */
1859void
Daniel Veillardeae522a2001-04-23 13:41:34 +00001860docbDefaultSAXHandlerInit(void)
Owen Taylor3473f882001-02-23 17:55:21 +00001861{
Daniel Veillard7583a592001-07-08 13:15:55 +00001862 static int docbSAXInitialized = 0;
1863 if (docbSAXInitialized)
1864 return;
1865
Daniel Veillardeae522a2001-04-23 13:41:34 +00001866 docbDefaultSAXHandler.internalSubset = internalSubset;
1867 docbDefaultSAXHandler.externalSubset = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001868 docbDefaultSAXHandler.isStandalone = isStandalone;
1869 docbDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1870 docbDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1871 docbDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001872 docbDefaultSAXHandler.getEntity = getEntity;
1873 docbDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001874 docbDefaultSAXHandler.entityDecl = entityDecl;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001875 docbDefaultSAXHandler.attributeDecl = NULL;
1876 docbDefaultSAXHandler.elementDecl = NULL;
1877 docbDefaultSAXHandler.notationDecl = NULL;
1878 docbDefaultSAXHandler.unparsedEntityDecl = NULL;
1879 docbDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1880 docbDefaultSAXHandler.startDocument = startDocument;
1881 docbDefaultSAXHandler.endDocument = endDocument;
1882 docbDefaultSAXHandler.startElement = startElement;
1883 docbDefaultSAXHandler.endElement = endElement;
Daniel Veillard1034da22001-04-25 19:06:28 +00001884 docbDefaultSAXHandler.reference = reference;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001885 docbDefaultSAXHandler.characters = characters;
1886 docbDefaultSAXHandler.cdataBlock = NULL;
1887 docbDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1888 docbDefaultSAXHandler.processingInstruction = NULL;
1889 docbDefaultSAXHandler.comment = comment;
1890 docbDefaultSAXHandler.warning = xmlParserWarning;
1891 docbDefaultSAXHandler.error = xmlParserError;
1892 docbDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001893
1894 docbSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001895}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001896
1897#endif /* LIBXML_DOCB_ENABLED */