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