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