blob: b54215794d4d7ecd648aef6ddc3c86994c9b6d08 [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 Veillardf300b7e2001-08-13 10:43:15 +00001310 int coalesceText = (lastChild != NULL) &&
1311 (lastChild->type == XML_TEXT_NODE) &&
1312 (lastChild->name == xmlStringText);
1313 if ((coalesceText) && (ctxt->nodemem != 0)) {
Owen Taylor3473f882001-02-23 17:55:21 +00001314#ifndef XML_USE_BUFFER_CONTENT
1315 /*
1316 * The whole point of maintaining nodelen and nodemem,
1317 * xmlTextConcat is too costly, i.e. compute lenght,
1318 * reallocate a new buffer, move data, append ch. Here
1319 * We try to minimaze realloc() uses and avoid copying
1320 * and recomputing lenght over and over.
1321 */
1322 if (ctxt->nodelen + len >= ctxt->nodemem) {
1323 xmlChar *newbuf;
1324 int size;
1325
1326 size = ctxt->nodemem + len;
1327 size *= 2;
1328 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1329 if (newbuf == NULL) {
1330 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1331 ctxt->sax->error(ctxt->userData,
1332 "SAX.characters(): out of memory\n");
1333 return;
1334 }
1335 ctxt->nodemem = size;
1336 lastChild->content = newbuf;
1337 }
1338 memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1339 ctxt->nodelen += len;
1340 lastChild->content[ctxt->nodelen] = 0;
1341#else
1342 xmlTextConcat(lastChild, ch, len);
1343#endif
Daniel Veillardf300b7e2001-08-13 10:43:15 +00001344 } else if (coalesceText) {
Daniel Veillard80f32572001-03-07 19:45:40 +00001345 xmlTextConcat(lastChild, ch, len);
1346 if (ctxt->node->children != NULL) {
1347 ctxt->nodelen = xmlStrlen(lastChild->content);
1348 ctxt->nodemem = ctxt->nodelen + 1;
1349 }
Owen Taylor3473f882001-02-23 17:55:21 +00001350 } else {
1351 /* Mixed content, first time */
1352 lastChild = xmlNewTextLen(ch, len);
1353 xmlAddChild(ctxt->node, lastChild);
1354#ifndef XML_USE_BUFFER_CONTENT
1355 if (ctxt->node->children != NULL) {
1356 ctxt->nodelen = len;
1357 ctxt->nodemem = len + 1;
1358 }
1359#endif
1360 }
1361 }
1362}
1363
1364/**
1365 * ignorableWhitespace:
1366 * @ctx: the user data (XML parser context)
1367 * @ch: a xmlChar string
1368 * @len: the number of xmlChar
1369 *
1370 * receiving some ignorable whitespaces from the parser.
1371 * Question: how much at a time ???
1372 */
1373void
Daniel Veillardc86a4fa2001-03-26 16:28:29 +00001374ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
Owen Taylor3473f882001-02-23 17:55:21 +00001375{
1376 /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1377#ifdef DEBUG_SAX
1378 xmlGenericError(xmlGenericErrorContext,
1379 "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1380#endif
1381}
1382
1383/**
1384 * processingInstruction:
1385 * @ctx: the user data (XML parser context)
1386 * @target: the target name
1387 * @data: the PI data's
1388 *
1389 * A processing instruction has been parsed.
1390 */
1391void
1392processingInstruction(void *ctx, const xmlChar *target,
1393 const xmlChar *data)
1394{
1395 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1396 xmlNodePtr ret;
1397 xmlNodePtr parent = ctxt->node;
1398
1399#ifdef DEBUG_SAX
1400 xmlGenericError(xmlGenericErrorContext,
1401 "SAX.processingInstruction(%s, %s)\n", target, data);
1402#endif
1403
1404 ret = xmlNewPI(target, data);
1405 if (ret == NULL) return;
1406 parent = ctxt->node;
1407
1408 if (ctxt->inSubset == 1) {
1409 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1410 return;
1411 } else if (ctxt->inSubset == 2) {
1412 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1413 return;
1414 }
1415 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1416#ifdef DEBUG_SAX_TREE
1417 xmlGenericError(xmlGenericErrorContext,
1418 "Setting PI %s as root\n", target);
1419#endif
1420 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1421 return;
1422 }
1423 if (parent->type == XML_ELEMENT_NODE) {
1424#ifdef DEBUG_SAX_TREE
1425 xmlGenericError(xmlGenericErrorContext,
1426 "adding PI %s child to %s\n", target, parent->name);
1427#endif
1428 xmlAddChild(parent, ret);
1429 } else {
1430#ifdef DEBUG_SAX_TREE
1431 xmlGenericError(xmlGenericErrorContext,
1432 "adding PI %s sibling to ", target);
1433 xmlDebugDumpOneNode(stderr, parent, 0);
1434#endif
1435 xmlAddSibling(parent, ret);
1436 }
1437}
1438
1439/**
1440 * globalNamespace:
1441 * @ctx: the user data (XML parser context)
1442 * @href: the namespace associated URN
1443 * @prefix: the namespace prefix
1444 *
1445 * An old global namespace has been parsed.
1446 */
1447void
1448globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1449{
1450 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1451#ifdef DEBUG_SAX
1452 xmlGenericError(xmlGenericErrorContext,
1453 "SAX.globalNamespace(%s, %s)\n", href, prefix);
1454#endif
1455 xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1456}
1457
1458/**
1459 * setNamespace:
1460 * @ctx: the user data (XML parser context)
1461 * @name: the namespace prefix
1462 *
1463 * Set the current element namespace.
1464 */
1465
1466void
1467setNamespace(void *ctx, const xmlChar *name)
1468{
1469 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1470 xmlNsPtr ns;
1471 xmlNodePtr parent;
1472
1473#ifdef DEBUG_SAX
1474 xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1475#endif
1476 ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1477 if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1478 if (ctxt->nodeNr >= 2) {
1479 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1480 if (parent != NULL)
1481 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1482 }
1483 }
1484 xmlSetNs(ctxt->node, ns);
1485}
1486
1487/**
1488 * getNamespace:
1489 * @ctx: the user data (XML parser context)
1490 *
1491 * Get the current element namespace.
1492 *
1493 * Returns the xmlNsPtr or NULL if none
1494 */
1495
1496xmlNsPtr
1497getNamespace(void *ctx)
1498{
1499 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1500 xmlNsPtr ret;
1501
1502#ifdef DEBUG_SAX
1503 xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1504#endif
1505 ret = ctxt->node->ns;
1506 return(ret);
1507}
1508
1509/**
1510 * checkNamespace:
1511 * @ctx: the user data (XML parser context)
1512 * @namespace: the namespace to check against
1513 *
1514 * Check that the current element namespace is the same as the
1515 * one read upon parsing.
1516 *
1517 * Returns 1 if true 0 otherwise
1518 */
1519
1520int
1521checkNamespace(void *ctx, xmlChar *namespace)
1522{
1523 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1524 xmlNodePtr cur = ctxt->node;
1525
1526#ifdef DEBUG_SAX
1527 xmlGenericError(xmlGenericErrorContext,
1528 "SAX.checkNamespace(%s)\n", namespace);
1529#endif
1530
1531 /*
1532 * Check that the Name in the ETag is the same as in the STag.
1533 */
1534 if (namespace == NULL) {
1535 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1536 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1537 ctxt->sax->error(ctxt,
1538 "End tags for %s don't hold the namespace %s\n",
1539 cur->name, cur->ns->prefix);
1540 ctxt->wellFormed = 0;
1541 }
1542 } else {
1543 if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1544 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1545 ctxt->sax->error(ctxt,
1546 "End tags %s holds a prefix %s not used by the open tag\n",
1547 cur->name, namespace);
1548 ctxt->wellFormed = 0;
1549 } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1550 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1551 ctxt->sax->error(ctxt,
1552 "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1553 cur->name, cur->ns->prefix, namespace);
1554 ctxt->wellFormed = 0;
1555 } else
1556 return(1);
1557 }
1558 return(0);
1559}
1560
1561/**
1562 * namespaceDecl:
1563 * @ctx: the user data (XML parser context)
1564 * @href: the namespace associated URN
1565 * @prefix: the namespace prefix
1566 *
1567 * A namespace has been parsed.
1568 */
1569void
1570namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1571{
1572 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1573#ifdef DEBUG_SAX
1574 if (prefix == NULL)
1575 xmlGenericError(xmlGenericErrorContext,
1576 "SAX.namespaceDecl(%s, NULL)\n", href);
1577 else
1578 xmlGenericError(xmlGenericErrorContext,
1579 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1580#endif
1581 xmlNewNs(ctxt->node, href, prefix);
1582}
1583
1584/**
1585 * comment:
1586 * @ctx: the user data (XML parser context)
1587 * @value: the comment content
1588 *
1589 * A comment has been parsed.
1590 */
1591void
1592comment(void *ctx, const xmlChar *value)
1593{
1594 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1595 xmlNodePtr ret;
1596 xmlNodePtr parent = ctxt->node;
1597
1598#ifdef DEBUG_SAX
1599 xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1600#endif
1601 ret = xmlNewDocComment(ctxt->myDoc, value);
1602 if (ret == NULL) return;
1603
1604 if (ctxt->inSubset == 1) {
1605 xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1606 return;
1607 } else if (ctxt->inSubset == 2) {
1608 xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1609 return;
1610 }
1611 if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1612#ifdef DEBUG_SAX_TREE
1613 xmlGenericError(xmlGenericErrorContext,
1614 "Setting comment as root\n");
1615#endif
1616 xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1617 return;
1618 }
1619 if (parent->type == XML_ELEMENT_NODE) {
1620#ifdef DEBUG_SAX_TREE
1621 xmlGenericError(xmlGenericErrorContext,
1622 "adding comment child to %s\n", parent->name);
1623#endif
1624 xmlAddChild(parent, ret);
1625 } else {
1626#ifdef DEBUG_SAX_TREE
1627 xmlGenericError(xmlGenericErrorContext,
1628 "adding comment sibling to ");
1629 xmlDebugDumpOneNode(stderr, parent, 0);
1630#endif
1631 xmlAddSibling(parent, ret);
1632 }
1633}
1634
1635/**
1636 * cdataBlock:
1637 * @ctx: the user data (XML parser context)
1638 * @value: The pcdata content
1639 * @len: the block length
1640 *
1641 * called when a pcdata block has been parsed
1642 */
1643void
1644cdataBlock(void *ctx, const xmlChar *value, int len)
1645{
1646 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1647 xmlNodePtr ret, lastChild;
1648
1649#ifdef DEBUG_SAX
1650 xmlGenericError(xmlGenericErrorContext,
1651 "SAX.pcdata(%.10s, %d)\n", value, len);
1652#endif
1653 lastChild = xmlGetLastChild(ctxt->node);
1654#ifdef DEBUG_SAX_TREE
1655 xmlGenericError(xmlGenericErrorContext,
1656 "add chars to %s \n", ctxt->node->name);
1657#endif
1658 if ((lastChild != NULL) &&
1659 (lastChild->type == XML_CDATA_SECTION_NODE)) {
1660 xmlTextConcat(lastChild, value, len);
1661 } else {
1662 ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
1663 xmlAddChild(ctxt->node, ret);
1664 }
1665}
1666
1667/*
1668 * Default handler for XML, builds the DOM tree
1669 */
1670xmlSAXHandler xmlDefaultSAXHandler = {
1671 internalSubset,
1672 isStandalone,
1673 hasInternalSubset,
1674 hasExternalSubset,
1675 resolveEntity,
1676 getEntity,
1677 entityDecl,
1678 notationDecl,
1679 attributeDecl,
1680 elementDecl,
1681 unparsedEntityDecl,
1682 setDocumentLocator,
1683 startDocument,
1684 endDocument,
1685 startElement,
1686 endElement,
1687 reference,
1688 characters,
1689 ignorableWhitespace,
1690 processingInstruction,
1691 comment,
1692 xmlParserWarning,
1693 xmlParserError,
1694 xmlParserError,
1695 getParameterEntity,
1696 cdataBlock,
1697 externalSubset,
1698};
1699
1700/**
1701 * xmlDefaultSAXHandlerInit:
1702 *
1703 * Initialize the default SAX handler
1704 */
1705void
1706xmlDefaultSAXHandlerInit(void)
1707{
Daniel Veillard7583a592001-07-08 13:15:55 +00001708 static int xmlSAXInitialized = 0;
1709 if (xmlSAXInitialized)
1710 return;
1711
Owen Taylor3473f882001-02-23 17:55:21 +00001712 xmlDefaultSAXHandler.internalSubset = internalSubset;
1713 xmlDefaultSAXHandler.externalSubset = externalSubset;
1714 xmlDefaultSAXHandler.isStandalone = isStandalone;
1715 xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1716 xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1717 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
1718 xmlDefaultSAXHandler.getEntity = getEntity;
1719 xmlDefaultSAXHandler.getParameterEntity = getParameterEntity;
1720 xmlDefaultSAXHandler.entityDecl = entityDecl;
1721 xmlDefaultSAXHandler.attributeDecl = attributeDecl;
1722 xmlDefaultSAXHandler.elementDecl = elementDecl;
1723 xmlDefaultSAXHandler.notationDecl = notationDecl;
1724 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
1725 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1726 xmlDefaultSAXHandler.startDocument = startDocument;
1727 xmlDefaultSAXHandler.endDocument = endDocument;
1728 xmlDefaultSAXHandler.startElement = startElement;
1729 xmlDefaultSAXHandler.endElement = endElement;
1730 xmlDefaultSAXHandler.reference = reference;
1731 xmlDefaultSAXHandler.characters = characters;
1732 xmlDefaultSAXHandler.cdataBlock = cdataBlock;
1733 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1734 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
1735 xmlDefaultSAXHandler.comment = comment;
1736 if (xmlGetWarningsDefaultValue == 0)
1737 xmlDefaultSAXHandler.warning = NULL;
1738 else
1739 xmlDefaultSAXHandler.warning = xmlParserWarning;
1740 xmlDefaultSAXHandler.error = xmlParserError;
1741 xmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001742
1743 xmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001744}
1745
Daniel Veillardeae522a2001-04-23 13:41:34 +00001746#ifdef LIBXML_HTML_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001747/*
1748 * Default handler for HTML, builds the DOM tree
1749 */
1750xmlSAXHandler htmlDefaultSAXHandler = {
1751 internalSubset,
1752 NULL,
1753 NULL,
1754 NULL,
1755 NULL,
1756 getEntity,
1757 NULL,
1758 NULL,
1759 NULL,
1760 NULL,
1761 NULL,
1762 setDocumentLocator,
1763 startDocument,
1764 endDocument,
1765 startElement,
1766 endElement,
1767 NULL,
1768 characters,
1769 ignorableWhitespace,
1770 NULL,
1771 comment,
1772 xmlParserWarning,
1773 xmlParserError,
1774 xmlParserError,
1775 getParameterEntity,
1776 cdataBlock,
1777 NULL,
1778};
1779
1780/**
1781 * htmlDefaultSAXHandlerInit:
1782 *
1783 * Initialize the default SAX handler
1784 */
1785void
1786htmlDefaultSAXHandlerInit(void)
1787{
Daniel Veillard7583a592001-07-08 13:15:55 +00001788 static int htmlSAXInitialized = 0;
1789 if (htmlSAXInitialized)
1790 return;
1791
Owen Taylor3473f882001-02-23 17:55:21 +00001792 htmlDefaultSAXHandler.internalSubset = internalSubset;
1793 htmlDefaultSAXHandler.externalSubset = NULL;
1794 htmlDefaultSAXHandler.isStandalone = NULL;
1795 htmlDefaultSAXHandler.hasInternalSubset = NULL;
1796 htmlDefaultSAXHandler.hasExternalSubset = NULL;
1797 htmlDefaultSAXHandler.resolveEntity = NULL;
1798 htmlDefaultSAXHandler.getEntity = getEntity;
1799 htmlDefaultSAXHandler.getParameterEntity = NULL;
1800 htmlDefaultSAXHandler.entityDecl = NULL;
1801 htmlDefaultSAXHandler.attributeDecl = NULL;
1802 htmlDefaultSAXHandler.elementDecl = NULL;
1803 htmlDefaultSAXHandler.notationDecl = NULL;
1804 htmlDefaultSAXHandler.unparsedEntityDecl = NULL;
1805 htmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1806 htmlDefaultSAXHandler.startDocument = startDocument;
1807 htmlDefaultSAXHandler.endDocument = endDocument;
1808 htmlDefaultSAXHandler.startElement = startElement;
1809 htmlDefaultSAXHandler.endElement = endElement;
1810 htmlDefaultSAXHandler.reference = NULL;
1811 htmlDefaultSAXHandler.characters = characters;
1812 htmlDefaultSAXHandler.cdataBlock = cdataBlock;
1813 htmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1814 htmlDefaultSAXHandler.processingInstruction = NULL;
1815 htmlDefaultSAXHandler.comment = comment;
1816 htmlDefaultSAXHandler.warning = xmlParserWarning;
1817 htmlDefaultSAXHandler.error = xmlParserError;
1818 htmlDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001819
1820 htmlSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001821}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001822#endif /* LIBXML_HTML_ENABLED */
Owen Taylor3473f882001-02-23 17:55:21 +00001823
Daniel Veillardeae522a2001-04-23 13:41:34 +00001824#ifdef LIBXML_DOCB_ENABLED
Owen Taylor3473f882001-02-23 17:55:21 +00001825/*
Daniel Veillardeae522a2001-04-23 13:41:34 +00001826 * Default handler for SGML DocBook, builds the DOM tree
Owen Taylor3473f882001-02-23 17:55:21 +00001827 */
Daniel Veillardeae522a2001-04-23 13:41:34 +00001828xmlSAXHandler docbDefaultSAXHandler = {
Owen Taylor3473f882001-02-23 17:55:21 +00001829 internalSubset,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001830 isStandalone,
1831 hasInternalSubset,
1832 hasExternalSubset,
1833 resolveEntity,
Owen Taylor3473f882001-02-23 17:55:21 +00001834 getEntity,
Daniel Veillard61b33d52001-04-24 13:55:12 +00001835 entityDecl,
Owen Taylor3473f882001-02-23 17:55:21 +00001836 NULL,
1837 NULL,
1838 NULL,
1839 NULL,
1840 setDocumentLocator,
1841 startDocument,
1842 endDocument,
1843 startElement,
1844 endElement,
Daniel Veillard1034da22001-04-25 19:06:28 +00001845 reference,
Owen Taylor3473f882001-02-23 17:55:21 +00001846 characters,
1847 ignorableWhitespace,
1848 NULL,
1849 comment,
1850 xmlParserWarning,
1851 xmlParserError,
1852 xmlParserError,
1853 getParameterEntity,
1854 NULL,
1855 NULL,
1856};
1857
1858/**
Daniel Veillardeae522a2001-04-23 13:41:34 +00001859 * docbDefaultSAXHandlerInit:
Owen Taylor3473f882001-02-23 17:55:21 +00001860 *
1861 * Initialize the default SAX handler
1862 */
1863void
Daniel Veillardeae522a2001-04-23 13:41:34 +00001864docbDefaultSAXHandlerInit(void)
Owen Taylor3473f882001-02-23 17:55:21 +00001865{
Daniel Veillard7583a592001-07-08 13:15:55 +00001866 static int docbSAXInitialized = 0;
1867 if (docbSAXInitialized)
1868 return;
1869
Daniel Veillardeae522a2001-04-23 13:41:34 +00001870 docbDefaultSAXHandler.internalSubset = internalSubset;
1871 docbDefaultSAXHandler.externalSubset = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001872 docbDefaultSAXHandler.isStandalone = isStandalone;
1873 docbDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
1874 docbDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
1875 docbDefaultSAXHandler.resolveEntity = resolveEntity;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001876 docbDefaultSAXHandler.getEntity = getEntity;
1877 docbDefaultSAXHandler.getParameterEntity = NULL;
Daniel Veillard61b33d52001-04-24 13:55:12 +00001878 docbDefaultSAXHandler.entityDecl = entityDecl;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001879 docbDefaultSAXHandler.attributeDecl = NULL;
1880 docbDefaultSAXHandler.elementDecl = NULL;
1881 docbDefaultSAXHandler.notationDecl = NULL;
1882 docbDefaultSAXHandler.unparsedEntityDecl = NULL;
1883 docbDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
1884 docbDefaultSAXHandler.startDocument = startDocument;
1885 docbDefaultSAXHandler.endDocument = endDocument;
1886 docbDefaultSAXHandler.startElement = startElement;
1887 docbDefaultSAXHandler.endElement = endElement;
Daniel Veillard1034da22001-04-25 19:06:28 +00001888 docbDefaultSAXHandler.reference = reference;
Daniel Veillardeae522a2001-04-23 13:41:34 +00001889 docbDefaultSAXHandler.characters = characters;
1890 docbDefaultSAXHandler.cdataBlock = NULL;
1891 docbDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
1892 docbDefaultSAXHandler.processingInstruction = NULL;
1893 docbDefaultSAXHandler.comment = comment;
1894 docbDefaultSAXHandler.warning = xmlParserWarning;
1895 docbDefaultSAXHandler.error = xmlParserError;
1896 docbDefaultSAXHandler.fatalError = xmlParserError;
Daniel Veillard7583a592001-07-08 13:15:55 +00001897
1898 docbSAXInitialized = 1;
Owen Taylor3473f882001-02-23 17:55:21 +00001899}
Daniel Veillardeae522a2001-04-23 13:41:34 +00001900
1901#endif /* LIBXML_DOCB_ENABLED */