SAX2.c revision fc484dd0a01b5f8f2187dd8a6791d5f8677fa816
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 * TODO:
34 *
35 * macro to flag unimplemented blocks
36 * XML_CATALOG_PREFER user env to select between system/public prefered
37 * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
38 *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
39 *> values "system" and "public".  I have made the default be "system" to
40 *> match yours.
41 */
42#define TODO 								\
43    xmlGenericError(xmlGenericErrorContext,				\
44	    "Unimplemented block at %s:%d\n",				\
45            __FILE__, __LINE__);
46
47/*
48 * xmlSAX2ErrMemory:
49 * @ctxt:  an XML validation parser context
50 * @msg:   a string to accompany the error message
51 */
52static void
53xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
54    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
55        ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
56    ctxt->errNo = XML_ERR_NO_MEMORY;
57    ctxt->instate = XML_PARSER_EOF;
58    ctxt->disableSAX = 1;
59}
60
61/**
62 * xmlValidError:
63 * @ctxt:  an XML validation parser context
64 * @error:  the error number
65 * @msg:  the error message
66 * @str1:  extra data
67 * @str2:  extra data
68 *
69 * Handle a validation error
70 */
71static void
72xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
73            const char *msg, const char *str1, const char *str2)
74{
75    xmlStructuredErrorFunc schannel = NULL;
76
77    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
78        (ctxt->instate == XML_PARSER_EOF))
79	return;
80    ctxt->errNo = error;
81    if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
82        schannel = ctxt->sax->serror;
83    __xmlRaiseError(schannel,
84                    ctxt->vctxt.error, ctxt->vctxt.userData,
85                    ctxt, NULL, XML_FROM_DTD, error,
86                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
87		    (const char *) str2, NULL, 0, 0,
88		    msg, (const char *) str1, (const char *) str2);
89    ctxt->valid = 0;
90}
91
92/**
93 * xmlSAX2GetPublicId:
94 * @ctx: the user data (XML parser context)
95 *
96 * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
97 *
98 * Returns a xmlChar *
99 */
100const xmlChar *
101xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
102{
103    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
104    return(NULL);
105}
106
107/**
108 * xmlSAX2GetSystemId:
109 * @ctx: the user data (XML parser context)
110 *
111 * Provides the system ID, basically URL or filename e.g.
112 * http://www.sgmlsource.com/dtds/memo.dtd
113 *
114 * Returns a xmlChar *
115 */
116const xmlChar *
117xmlSAX2GetSystemId(void *ctx)
118{
119    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
120    return((const xmlChar *) ctxt->input->filename);
121}
122
123/**
124 * xmlSAX2GetLineNumber:
125 * @ctx: the user data (XML parser context)
126 *
127 * Provide the line number of the current parsing point.
128 *
129 * Returns an int
130 */
131int
132xmlSAX2GetLineNumber(void *ctx)
133{
134    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
135    return(ctxt->input->line);
136}
137
138/**
139 * xmlSAX2GetColumnNumber:
140 * @ctx: the user data (XML parser context)
141 *
142 * Provide the column number of the current parsing point.
143 *
144 * Returns an int
145 */
146int
147xmlSAX2GetColumnNumber(void *ctx)
148{
149    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
150    return(ctxt->input->col);
151}
152
153/**
154 * xmlSAX2IsStandalone:
155 * @ctx: the user data (XML parser context)
156 *
157 * Is this document tagged standalone ?
158 *
159 * Returns 1 if true
160 */
161int
162xmlSAX2IsStandalone(void *ctx)
163{
164    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
165    return(ctxt->myDoc->standalone == 1);
166}
167
168/**
169 * xmlSAX2HasInternalSubset:
170 * @ctx: the user data (XML parser context)
171 *
172 * Does this document has an internal subset
173 *
174 * Returns 1 if true
175 */
176int
177xmlSAX2HasInternalSubset(void *ctx)
178{
179    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
180    return(ctxt->myDoc->intSubset != NULL);
181}
182
183/**
184 * xmlSAX2HasExternalSubset:
185 * @ctx: the user data (XML parser context)
186 *
187 * Does this document has an external subset
188 *
189 * Returns 1 if true
190 */
191int
192xmlSAX2HasExternalSubset(void *ctx)
193{
194    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
195    return(ctxt->myDoc->extSubset != NULL);
196}
197
198/**
199 * xmlSAX2InternalSubset:
200 * @ctx:  the user data (XML parser context)
201 * @name:  the root element name
202 * @ExternalID:  the external ID
203 * @SystemID:  the SYSTEM ID (e.g. filename or URL)
204 *
205 * Callback on internal subset declaration.
206 */
207void
208xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
209	       const xmlChar *ExternalID, const xmlChar *SystemID)
210{
211    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
212    xmlDtdPtr dtd;
213#ifdef DEBUG_SAX
214    xmlGenericError(xmlGenericErrorContext,
215	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
216            name, ExternalID, SystemID);
217#endif
218
219    if (ctxt->myDoc == NULL)
220	return;
221    dtd = xmlGetIntSubset(ctxt->myDoc);
222    if (dtd != NULL) {
223	if (ctxt->html)
224	    return;
225	xmlUnlinkNode((xmlNodePtr) dtd);
226	xmlFreeDtd(dtd);
227	ctxt->myDoc->intSubset = NULL;
228    }
229    ctxt->myDoc->intSubset =
230	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
231    if (ctxt->myDoc->intSubset == NULL)
232        xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
233}
234
235/**
236 * xmlSAX2ExternalSubset:
237 * @ctx: the user data (XML parser context)
238 * @name:  the root element name
239 * @ExternalID:  the external ID
240 * @SystemID:  the SYSTEM ID (e.g. filename or URL)
241 *
242 * Callback on external subset declaration.
243 */
244void
245xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
246	       const xmlChar *ExternalID, const xmlChar *SystemID)
247{
248    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
249#ifdef DEBUG_SAX
250    xmlGenericError(xmlGenericErrorContext,
251	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
252            name, ExternalID, SystemID);
253#endif
254    if (((ExternalID != NULL) || (SystemID != NULL)) &&
255        (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
256	 (ctxt->wellFormed && ctxt->myDoc))) {
257	/*
258	 * Try to fetch and parse the external subset.
259	 */
260	xmlParserInputPtr oldinput;
261	int oldinputNr;
262	int oldinputMax;
263	xmlParserInputPtr *oldinputTab;
264	xmlParserInputPtr input = NULL;
265	xmlCharEncoding enc;
266	int oldcharset;
267
268	/*
269	 * Ask the Entity resolver to load the damn thing
270	 */
271	if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
272	    input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
273	                                        SystemID);
274	if (input == NULL) {
275	    return;
276	}
277
278	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
279
280	/*
281	 * make sure we won't destroy the main document context
282	 */
283	oldinput = ctxt->input;
284	oldinputNr = ctxt->inputNr;
285	oldinputMax = ctxt->inputMax;
286	oldinputTab = ctxt->inputTab;
287	oldcharset = ctxt->charset;
288
289	ctxt->inputTab = (xmlParserInputPtr *)
290	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
291	if (ctxt->inputTab == NULL) {
292	    xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
293	    ctxt->input = oldinput;
294	    ctxt->inputNr = oldinputNr;
295	    ctxt->inputMax = oldinputMax;
296	    ctxt->inputTab = oldinputTab;
297	    ctxt->charset = oldcharset;
298	    return;
299	}
300	ctxt->inputNr = 0;
301	ctxt->inputMax = 5;
302	ctxt->input = NULL;
303	xmlPushInput(ctxt, input);
304
305	/*
306	 * On the fly encoding conversion if needed
307	 */
308	if (ctxt->input->length >= 4) {
309	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
310	    xmlSwitchEncoding(ctxt, enc);
311	}
312
313	if (input->filename == NULL)
314	    input->filename = (char *) xmlCanonicPath(SystemID);
315	input->line = 1;
316	input->col = 1;
317	input->base = ctxt->input->cur;
318	input->cur = ctxt->input->cur;
319	input->free = NULL;
320
321	/*
322	 * let's parse that entity knowing it's an external subset.
323	 */
324	xmlParseExternalSubset(ctxt, ExternalID, SystemID);
325
326        /*
327	 * Free up the external entities
328	 */
329
330	while (ctxt->inputNr > 1)
331	    xmlPopInput(ctxt);
332	xmlFreeInputStream(ctxt->input);
333        xmlFree(ctxt->inputTab);
334
335	/*
336	 * Restore the parsing context of the main entity
337	 */
338	ctxt->input = oldinput;
339	ctxt->inputNr = oldinputNr;
340	ctxt->inputMax = oldinputMax;
341	ctxt->inputTab = oldinputTab;
342	ctxt->charset = oldcharset;
343	/* ctxt->wellFormed = oldwellFormed; */
344    }
345}
346
347/**
348 * xmlSAX2ResolveEntity:
349 * @ctx: the user data (XML parser context)
350 * @publicId: The public ID of the entity
351 * @systemId: The system ID of the entity
352 *
353 * The entity loader, to control the loading of external entities,
354 * the application can either:
355 *    - override this xmlSAX2ResolveEntity() callback in the SAX block
356 *    - or better use the xmlSetExternalEntityLoader() function to
357 *      set up it's own entity resolution routine
358 *
359 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
360 */
361xmlParserInputPtr
362xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
363{
364    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
365    xmlParserInputPtr ret;
366    xmlChar *URI;
367    const char *base = NULL;
368
369    if (ctxt->input != NULL)
370	base = ctxt->input->filename;
371    if (base == NULL)
372	base = ctxt->directory;
373
374    URI = xmlBuildURI(systemId, (const xmlChar *) base);
375
376#ifdef DEBUG_SAX
377    xmlGenericError(xmlGenericErrorContext,
378	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
379#endif
380
381    ret = xmlLoadExternalEntity((const char *) URI,
382				(const char *) publicId, ctxt);
383    if (URI != NULL)
384	xmlFree(URI);
385    return(ret);
386}
387
388/**
389 * xmlSAX2GetEntity:
390 * @ctx: the user data (XML parser context)
391 * @name: The entity name
392 *
393 * Get an entity by name
394 *
395 * Returns the xmlEntityPtr if found.
396 */
397xmlEntityPtr
398xmlSAX2GetEntity(void *ctx, const xmlChar *name)
399{
400    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
401    xmlEntityPtr ret = NULL;
402
403#ifdef DEBUG_SAX
404    xmlGenericError(xmlGenericErrorContext,
405	    "SAX.xmlSAX2GetEntity(%s)\n", name);
406#endif
407
408    if (ctxt->inSubset == 0) {
409	ret = xmlGetPredefinedEntity(name);
410	if (ret != NULL)
411	    return(ret);
412    }
413    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
414	if (ctxt->inSubset == 2) {
415	    ctxt->myDoc->standalone = 0;
416	    ret = xmlGetDocEntity(ctxt->myDoc, name);
417	    ctxt->myDoc->standalone = 1;
418	} else {
419	    ret = xmlGetDocEntity(ctxt->myDoc, name);
420	    if (ret == NULL) {
421		ctxt->myDoc->standalone = 0;
422		ret = xmlGetDocEntity(ctxt->myDoc, name);
423		if (ret != NULL) {
424		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
425			ctxt->sax->error(ctxt->userData,
426		 "Entity(%s) document marked standalone but requires external subset\n",
427					 name);
428		    ctxt->valid = 0;
429		    ctxt->wellFormed = 0;
430		}
431		ctxt->myDoc->standalone = 1;
432	    }
433	}
434    } else {
435	ret = xmlGetDocEntity(ctxt->myDoc, name);
436    }
437    if ((ret != NULL) &&
438	((ctxt->validate) || (ctxt->replaceEntities)) &&
439	(ret->children == NULL) &&
440	(ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
441	int val;
442
443	/*
444	 * for validation purposes we really need to fetch and
445	 * parse the external entity
446	 */
447	xmlNodePtr children;
448
449        val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
450		                         ret->ExternalID, &children);
451	if (val == 0) {
452	    xmlAddChildList((xmlNodePtr) ret, children);
453	} else {
454	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
455	        ctxt->sax->error(ctxt->userData,
456		 "Failure to process entity %s\n", name);
457	    ctxt->wellFormed = 0;
458	    ctxt->valid = 0;
459	    ctxt->validate = 0;
460	    return(NULL);
461	}
462	ret->owner = 1;
463    }
464    return(ret);
465}
466
467/**
468 * xmlSAX2GetParameterEntity:
469 * @ctx: the user data (XML parser context)
470 * @name: The entity name
471 *
472 * Get a parameter entity by name
473 *
474 * Returns the xmlEntityPtr if found.
475 */
476xmlEntityPtr
477xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
478{
479    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
480    xmlEntityPtr ret;
481
482#ifdef DEBUG_SAX
483    xmlGenericError(xmlGenericErrorContext,
484	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
485#endif
486
487    ret = xmlGetParameterEntity(ctxt->myDoc, name);
488    return(ret);
489}
490
491
492/**
493 * xmlSAX2EntityDecl:
494 * @ctx: the user data (XML parser context)
495 * @name:  the entity name
496 * @type:  the entity type
497 * @publicId: The public ID of the entity
498 * @systemId: The system ID of the entity
499 * @content: the entity value (without processing).
500 *
501 * An entity definition has been parsed
502 */
503void
504xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
505          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
506{
507    xmlEntityPtr ent;
508    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
509
510#ifdef DEBUG_SAX
511    xmlGenericError(xmlGenericErrorContext,
512	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
513            name, type, publicId, systemId, content);
514#endif
515    if (ctxt->inSubset == 1) {
516	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
517		              systemId, content);
518	if ((ent == NULL) && (ctxt->pedantic) &&
519	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
520	    ctxt->sax->warning(ctxt->userData,
521	     "Entity(%s) already defined in the internal subset\n", name);
522	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
523	    xmlChar *URI;
524	    const char *base = NULL;
525
526	    if (ctxt->input != NULL)
527		base = ctxt->input->filename;
528	    if (base == NULL)
529		base = ctxt->directory;
530
531	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
532	    ent->URI = URI;
533	}
534    } else if (ctxt->inSubset == 2) {
535	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
536		              systemId, content);
537	if ((ent == NULL) && (ctxt->pedantic) &&
538	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
539	    ctxt->sax->warning(ctxt->userData,
540	     "Entity(%s) already defined in the external subset\n", name);
541	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
542	    xmlChar *URI;
543	    const char *base = NULL;
544
545	    if (ctxt->input != NULL)
546		base = ctxt->input->filename;
547	    if (base == NULL)
548		base = ctxt->directory;
549
550	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
551	    ent->URI = URI;
552	}
553    } else {
554	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
555	    ctxt->sax->error(ctxt->userData,
556	     "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", name);
557    }
558}
559
560/**
561 * xmlSAX2AttributeDecl:
562 * @ctx: the user data (XML parser context)
563 * @elem:  the name of the element
564 * @fullname:  the attribute name
565 * @type:  the attribute type
566 * @def:  the type of default value
567 * @defaultValue: the attribute default value
568 * @tree:  the tree of enumerated value set
569 *
570 * An attribute definition has been parsed
571 */
572void
573xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
574              int type, int def, const xmlChar *defaultValue,
575	      xmlEnumerationPtr tree)
576{
577    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
578    xmlAttributePtr attr;
579    xmlChar *name = NULL, *prefix = NULL;
580
581#ifdef DEBUG_SAX
582    xmlGenericError(xmlGenericErrorContext,
583	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
584            elem, fullname, type, def, defaultValue);
585#endif
586    if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
587        (type != XML_ATTRIBUTE_ID)) {
588	/*
589	 * Raise the error but keep the validity flag
590	 */
591	int tmp = ctxt->valid;
592	xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
593	      "xml:id : attribute type should be ID\n", NULL, NULL);
594	ctxt->valid = tmp;
595    }
596    /* TODO: optimize name/prefix allocation */
597    name = xmlSplitQName(ctxt, fullname, &prefix);
598    ctxt->vctxt.valid = 1;
599    if (ctxt->inSubset == 1)
600	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
601	       name, prefix, (xmlAttributeType) type,
602	       (xmlAttributeDefault) def, defaultValue, tree);
603    else if (ctxt->inSubset == 2)
604	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
605	   name, prefix, (xmlAttributeType) type,
606	   (xmlAttributeDefault) def, defaultValue, tree);
607    else {
608	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
609	    ctxt->sax->error(ctxt->userData,
610	     "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
611	xmlFreeEnumeration(tree);
612	return;
613    }
614#ifdef LIBXML_VALID_ENABLED
615    if (ctxt->vctxt.valid == 0)
616	ctxt->valid = 0;
617    if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
618        (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
619	ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
620	                                        attr);
621#endif /* LIBXML_VALID_ENABLED */
622    if (prefix != NULL)
623	xmlFree(prefix);
624    if (name != NULL)
625	xmlFree(name);
626}
627
628/**
629 * xmlSAX2ElementDecl:
630 * @ctx: the user data (XML parser context)
631 * @name:  the element name
632 * @type:  the element type
633 * @content: the element value tree
634 *
635 * An element definition has been parsed
636 */
637void
638xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
639            xmlElementContentPtr content)
640{
641    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
642    xmlElementPtr elem = NULL;
643
644#ifdef DEBUG_SAX
645    xmlGenericError(xmlGenericErrorContext,
646                    "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
647#endif
648
649    if (ctxt->inSubset == 1)
650        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
651                                 name, (xmlElementTypeVal) type, content);
652    else if (ctxt->inSubset == 2)
653        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
654                                 name, (xmlElementTypeVal) type, content);
655    else {
656        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
657            ctxt->sax->error(ctxt->userData,
658                             "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
659                             name);
660        return;
661    }
662#ifdef LIBXML_VALID_ENABLED
663    if (elem == NULL)
664        ctxt->valid = 0;
665    if (ctxt->validate && ctxt->wellFormed &&
666        ctxt->myDoc && ctxt->myDoc->intSubset)
667        ctxt->valid &=
668            xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
669#endif /* LIBXML_VALID_ENABLED */
670}
671
672/**
673 * xmlSAX2NotationDecl:
674 * @ctx: the user data (XML parser context)
675 * @name: The name of the notation
676 * @publicId: The public ID of the entity
677 * @systemId: The system ID of the entity
678 *
679 * What to do when a notation declaration has been parsed.
680 */
681void
682xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
683	     const xmlChar *publicId, const xmlChar *systemId)
684{
685    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
686    xmlNotationPtr nota = NULL;
687
688#ifdef DEBUG_SAX
689    xmlGenericError(xmlGenericErrorContext,
690	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
691#endif
692
693    if ((publicId == NULL) && (systemId == NULL)) {
694	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
695	    ctxt->sax->error(ctxt->userData,
696	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
697	ctxt->valid = 0;
698	ctxt->wellFormed = 0;
699	return;
700    } else if (ctxt->inSubset == 1)
701	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
702                              publicId, systemId);
703    else if (ctxt->inSubset == 2)
704	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
705                              publicId, systemId);
706    else {
707	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
708	    ctxt->sax->error(ctxt->userData,
709	     "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
710	return;
711    }
712#ifdef LIBXML_VALID_ENABLED
713    if (nota == NULL) ctxt->valid = 0;
714    if (ctxt->validate && ctxt->wellFormed &&
715        ctxt->myDoc && ctxt->myDoc->intSubset)
716	ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
717	                                       nota);
718#endif /* LIBXML_VALID_ENABLED */
719}
720
721/**
722 * xmlSAX2UnparsedEntityDecl:
723 * @ctx: the user data (XML parser context)
724 * @name: The name of the entity
725 * @publicId: The public ID of the entity
726 * @systemId: The system ID of the entity
727 * @notationName: the name of the notation
728 *
729 * What to do when an unparsed entity declaration is parsed
730 */
731void
732xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
733		   const xmlChar *publicId, const xmlChar *systemId,
734		   const xmlChar *notationName)
735{
736    xmlEntityPtr ent;
737    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
738#ifdef DEBUG_SAX
739    xmlGenericError(xmlGenericErrorContext,
740	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
741            name, publicId, systemId, notationName);
742#endif
743    if (ctxt->inSubset == 1) {
744	ent = xmlAddDocEntity(ctxt->myDoc, name,
745			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
746			publicId, systemId, notationName);
747	if ((ent == NULL) && (ctxt->pedantic) &&
748	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
749	    ctxt->sax->warning(ctxt->userData,
750	     "Entity(%s) already defined in the internal subset\n", name);
751	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
752	    xmlChar *URI;
753	    const char *base = NULL;
754
755	    if (ctxt->input != NULL)
756		base = ctxt->input->filename;
757	    if (base == NULL)
758		base = ctxt->directory;
759
760	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
761	    ent->URI = URI;
762	}
763    } else if (ctxt->inSubset == 2) {
764	ent = xmlAddDtdEntity(ctxt->myDoc, name,
765			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
766			publicId, systemId, notationName);
767	if ((ent == NULL) && (ctxt->pedantic) &&
768	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
769	    ctxt->sax->warning(ctxt->userData,
770	     "Entity(%s) already defined in the external subset\n", name);
771	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
772	    xmlChar *URI;
773	    const char *base = NULL;
774
775	    if (ctxt->input != NULL)
776		base = ctxt->input->filename;
777	    if (base == NULL)
778		base = ctxt->directory;
779
780	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
781	    ent->URI = URI;
782	}
783    } else {
784	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
785	    ctxt->sax->error(ctxt->userData,
786	     "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
787    }
788}
789
790/**
791 * xmlSAX2SetDocumentLocator:
792 * @ctx: the user data (XML parser context)
793 * @loc: A SAX Locator
794 *
795 * Receive the document locator at startup, actually xmlDefaultSAXLocator
796 * Everything is available on the context, so this is useless in our case.
797 */
798void
799xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
800{
801    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
802#ifdef DEBUG_SAX
803    xmlGenericError(xmlGenericErrorContext,
804	    "SAX.xmlSAX2SetDocumentLocator()\n");
805#endif
806}
807
808/**
809 * xmlSAX2StartDocument:
810 * @ctx: the user data (XML parser context)
811 *
812 * called when the document start being processed.
813 */
814void
815xmlSAX2StartDocument(void *ctx)
816{
817    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
818    xmlDocPtr doc;
819
820#ifdef DEBUG_SAX
821    xmlGenericError(xmlGenericErrorContext,
822	    "SAX.xmlSAX2StartDocument()\n");
823#endif
824    if (ctxt->html) {
825#ifdef LIBXML_HTML_ENABLED
826	if (ctxt->myDoc == NULL)
827	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
828	if (ctxt->myDoc == NULL) {
829	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
830	    return;
831	}
832#else
833        xmlGenericError(xmlGenericErrorContext,
834		"libxml2 built without HTML support\n");
835	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
836	ctxt->instate = XML_PARSER_EOF;
837	ctxt->disableSAX = 1;
838	return;
839#endif
840    } else {
841	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
842	if (doc != NULL) {
843	    if (ctxt->encoding != NULL)
844		doc->encoding = xmlStrdup(ctxt->encoding);
845	    else
846		doc->encoding = NULL;
847	    doc->standalone = ctxt->standalone;
848	} else {
849	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
850	    return;
851	}
852	if ((ctxt->dictNames) && (doc != NULL)) {
853	    doc->dict = ctxt->dict;
854	    xmlDictReference(doc->dict);
855	}
856    }
857    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
858	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
859	ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
860	if (ctxt->myDoc->URL == NULL)
861	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
862    }
863}
864
865/**
866 * xmlSAX2EndDocument:
867 * @ctx: the user data (XML parser context)
868 *
869 * called when the document end has been detected.
870 */
871void
872xmlSAX2EndDocument(void *ctx)
873{
874    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
875#ifdef DEBUG_SAX
876    xmlGenericError(xmlGenericErrorContext,
877	    "SAX.xmlSAX2EndDocument()\n");
878#endif
879#ifdef LIBXML_VALID_ENABLED
880    if (ctxt->validate && ctxt->wellFormed &&
881        ctxt->myDoc && ctxt->myDoc->intSubset)
882	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
883#endif /* LIBXML_VALID_ENABLED */
884
885    /*
886     * Grab the encoding if it was added on-the-fly
887     */
888    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
889	(ctxt->myDoc->encoding == NULL)) {
890	ctxt->myDoc->encoding = ctxt->encoding;
891	ctxt->encoding = NULL;
892    }
893    if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
894	(ctxt->myDoc->encoding == NULL)) {
895	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
896    }
897    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
898	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
899	ctxt->myDoc->charset = ctxt->charset;
900    }
901}
902
903#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED)
904/**
905 * xmlSAX2AttributeInternal:
906 * @ctx: the user data (XML parser context)
907 * @fullname:  The attribute name, including namespace prefix
908 * @value:  The attribute value
909 * @prefix: the prefix on the element node
910 *
911 * Handle an attribute that has been read by the parser.
912 * The default handling is to convert the attribute into an
913 * DOM subtree and past it in a new xmlAttr element added to
914 * the element.
915 */
916static void
917xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
918             const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
919{
920    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
921    xmlAttrPtr ret;
922    xmlChar *name;
923    xmlChar *ns;
924    xmlChar *nval;
925    xmlNsPtr namespace;
926
927    /*
928     * Split the full name into a namespace prefix and the tag name
929     */
930    name = xmlSplitQName(ctxt, fullname, &ns);
931    if ((name != NULL) && (name[0] == 0)) {
932        if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
933	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
934		ctxt->sax->error(ctxt->userData,
935		     "invalid namespace declaration '%s'\n", fullname);
936	} else {
937	    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
938		ctxt->sax->warning(ctxt->userData,
939		     "Avoid attribute ending with ':' like '%s'\n", fullname);
940	}
941	if (ns != NULL)
942	    xmlFree(ns);
943	ns = NULL;
944	xmlFree(name);
945	name = xmlStrdup(fullname);
946    }
947    if (name == NULL) {
948        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
949	if (ns != NULL)
950	    xmlFree(ns);
951	return;
952    }
953
954#ifdef LIBXML_VALID_ENABLED
955    /*
956     * Do the last stage of the attribute normalization
957     * Needed for HTML too:
958     *   http://www.w3.org/TR/html4/types.html#h-6.2
959     */
960    ctxt->vctxt.valid = 1;
961    nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
962	                                   ctxt->myDoc, ctxt->node,
963					   fullname, value);
964    if (ctxt->vctxt.valid != 1) {
965	ctxt->valid = 0;
966    }
967    if (nval != NULL)
968	value = nval;
969#else
970    nval = NULL;
971#endif /* LIBXML_VALID_ENABLED */
972
973    /*
974     * Check whether it's a namespace definition
975     */
976    if ((!ctxt->html) && (ns == NULL) &&
977        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
978        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
979	xmlNsPtr nsret;
980	xmlChar *val;
981
982        if (!ctxt->replaceEntities) {
983	    ctxt->depth++;
984	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
985		                          0,0,0);
986	    ctxt->depth--;
987	} else {
988	    val = (xmlChar *) value;
989	}
990
991	if (val[0] != 0) {
992	    xmlURIPtr uri;
993
994	    uri = xmlParseURI((const char *)val);
995	    if (uri == NULL) {
996		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
997		    ctxt->sax->warning(ctxt->userData,
998			 "xmlns: %s not a valid URI\n", val);
999	    } else {
1000		if (uri->scheme == NULL) {
1001		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1002			ctxt->sax->warning(ctxt->userData,
1003			     "xmlns: URI %s is not absolute\n", val);
1004		}
1005		xmlFreeURI(uri);
1006	    }
1007	}
1008
1009	/* a default namespace definition */
1010	nsret = xmlNewNs(ctxt->node, val, NULL);
1011
1012#ifdef LIBXML_VALID_ENABLED
1013	/*
1014	 * Validate also for namespace decls, they are attributes from
1015	 * an XML-1.0 perspective
1016	 */
1017        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1018	    ctxt->myDoc && ctxt->myDoc->intSubset)
1019	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1020					   ctxt->node, prefix, nsret, val);
1021#endif /* LIBXML_VALID_ENABLED */
1022	if (name != NULL)
1023	    xmlFree(name);
1024	if (nval != NULL)
1025	    xmlFree(nval);
1026	if (val != value)
1027	    xmlFree(val);
1028	return;
1029    }
1030    if ((!ctxt->html) &&
1031	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1032        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1033	xmlNsPtr nsret;
1034	xmlChar *val;
1035
1036        if (!ctxt->replaceEntities) {
1037	    ctxt->depth++;
1038	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1039		                          0,0,0);
1040	    ctxt->depth--;
1041	    if (val == NULL) {
1042	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1043	        xmlFree(ns);
1044		if (name != NULL)
1045		    xmlFree(name);
1046		return;
1047	    }
1048	} else {
1049	    val = (xmlChar *) value;
1050	}
1051
1052	if (val[0] == 0) {
1053	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1054		ctxt->sax->error(ctxt->userData,
1055		     "Empty namespace name for prefix %s\n", name);
1056	}
1057	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1058	    xmlURIPtr uri;
1059
1060	    uri = xmlParseURI((const char *)val);
1061	    if (uri == NULL) {
1062		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1063		    ctxt->sax->warning(ctxt->userData,
1064			 "xmlns:%s: %s not a valid URI\n", name, value);
1065	    } else {
1066		if (uri->scheme == NULL) {
1067		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1068			ctxt->sax->warning(ctxt->userData,
1069			   "xmlns:%s: URI %s is not absolute\n", name, value);
1070		}
1071		xmlFreeURI(uri);
1072	    }
1073	}
1074
1075	/* a standard namespace definition */
1076	nsret = xmlNewNs(ctxt->node, val, name);
1077	xmlFree(ns);
1078#ifdef LIBXML_VALID_ENABLED
1079	/*
1080	 * Validate also for namespace decls, they are attributes from
1081	 * an XML-1.0 perspective
1082	 */
1083        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1084	    ctxt->myDoc && ctxt->myDoc->intSubset)
1085	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1086					   ctxt->node, prefix, nsret, value);
1087#endif /* LIBXML_VALID_ENABLED */
1088	if (name != NULL)
1089	    xmlFree(name);
1090	if (nval != NULL)
1091	    xmlFree(nval);
1092	if (val != value)
1093	    xmlFree(val);
1094	return;
1095    }
1096
1097    if (ns != NULL) {
1098	xmlAttrPtr prop;
1099	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1100	if (namespace == NULL) {
1101	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1102		ctxt->sax->error(ctxt->userData,
1103		    "Namespace prefix %s of attribute %s is not defined\n",
1104		             ns, name);
1105	}
1106
1107	prop = ctxt->node->properties;
1108	while (prop != NULL) {
1109	    if (prop->ns != NULL) {
1110		if ((xmlStrEqual(name, prop->name)) &&
1111		    ((namespace == prop->ns) ||
1112		     (xmlStrEqual(namespace->href, prop->ns->href)))) {
1113		    ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1114		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1115			ctxt->sax->error(ctxt->userData,
1116			        "Attribute %s in %s redefined\n",
1117			                 name, namespace->href);
1118		    ctxt->wellFormed = 0;
1119		    if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1120		    goto error;
1121		}
1122	    }
1123	    prop = prop->next;
1124	}
1125    } else {
1126	namespace = NULL;
1127    }
1128
1129    /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1130    ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1131
1132    if (ret != NULL) {
1133        if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1134	    xmlNodePtr tmp;
1135
1136	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1137	    tmp = ret->children;
1138	    while (tmp != NULL) {
1139		tmp->parent = (xmlNodePtr) ret;
1140		if (tmp->next == NULL)
1141		    ret->last = tmp;
1142		tmp = tmp->next;
1143	    }
1144	} else if (value != NULL) {
1145	    ret->children = xmlNewDocText(ctxt->myDoc, value);
1146	    ret->last = ret->children;
1147	    if (ret->children != NULL)
1148		ret->children->parent = (xmlNodePtr) ret;
1149	}
1150    }
1151
1152#ifdef LIBXML_VALID_ENABLED
1153    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1154        ctxt->myDoc && ctxt->myDoc->intSubset) {
1155
1156	/*
1157	 * If we don't substitute entities, the validation should be
1158	 * done on a value with replaced entities anyway.
1159	 */
1160        if (!ctxt->replaceEntities) {
1161	    xmlChar *val;
1162
1163	    ctxt->depth++;
1164	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1165		                          0,0,0);
1166	    ctxt->depth--;
1167
1168	    if (val == NULL)
1169		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1170				ctxt->myDoc, ctxt->node, ret, value);
1171	    else {
1172		xmlChar *nvalnorm;
1173
1174		/*
1175		 * Do the last stage of the attribute normalization
1176		 * It need to be done twice ... it's an extra burden related
1177		 * to the ability to keep xmlSAX2References in attributes
1178		 */
1179		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1180					    ctxt->node, fullname, val);
1181		if (nvalnorm != NULL) {
1182		    xmlFree(val);
1183		    val = nvalnorm;
1184		}
1185
1186		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1187			        ctxt->myDoc, ctxt->node, ret, val);
1188                xmlFree(val);
1189	    }
1190	} else {
1191	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1192					       ctxt->node, ret, value);
1193	}
1194    } else
1195#endif /* LIBXML_VALID_ENABLED */
1196           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1197	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1198	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1199        /*
1200	 * when validating, the ID registration is done at the attribute
1201	 * validation level. Otherwise we have to do specific handling here.
1202	 */
1203	if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1204	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1205	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1206	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1207	else if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1208	    /*
1209	     * Add the xml:id value
1210	     *
1211	     * Open issue: normalization of the value.
1212	     */
1213	    if (xmlValidateNCName(value, 1) != 0) {
1214	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1215		      "xml:id : attribute value %s is not an NCName\n",
1216			    (const char *) value, NULL);
1217	    }
1218	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1219	}
1220    }
1221
1222error:
1223    if (nval != NULL)
1224	xmlFree(nval);
1225    if (ns != NULL)
1226	xmlFree(ns);
1227}
1228
1229/*
1230 * xmlCheckDefaultedAttributes:
1231 *
1232 * Check defaulted attributes from the DTD
1233 */
1234static void
1235xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1236	const xmlChar *prefix, const xmlChar **atts) {
1237    xmlElementPtr elemDecl;
1238    const xmlChar *att;
1239    int internal = 1;
1240    int i;
1241
1242    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1243    if (elemDecl == NULL) {
1244	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1245	internal = 0;
1246    }
1247
1248process_external_subset:
1249
1250    if (elemDecl != NULL) {
1251	xmlAttributePtr attr = elemDecl->attributes;
1252	/*
1253	 * Check against defaulted attributes from the external subset
1254	 * if the document is stamped as standalone
1255	 */
1256	if ((ctxt->myDoc->standalone == 1) &&
1257	    (ctxt->myDoc->extSubset != NULL) &&
1258	    (ctxt->validate)) {
1259	    while (attr != NULL) {
1260		if ((attr->defaultValue != NULL) &&
1261		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1262					attr->elem, attr->name,
1263					attr->prefix) == attr) &&
1264		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1265					attr->elem, attr->name,
1266					attr->prefix) == NULL)) {
1267		    xmlChar *fulln;
1268
1269		    if (attr->prefix != NULL) {
1270			fulln = xmlStrdup(attr->prefix);
1271			fulln = xmlStrcat(fulln, BAD_CAST ":");
1272			fulln = xmlStrcat(fulln, attr->name);
1273		    } else {
1274			fulln = xmlStrdup(attr->name);
1275		    }
1276
1277		    /*
1278		     * Check that the attribute is not declared in the
1279		     * serialization
1280		     */
1281		    att = NULL;
1282		    if (atts != NULL) {
1283			i = 0;
1284			att = atts[i];
1285			while (att != NULL) {
1286			    if (xmlStrEqual(att, fulln))
1287				break;
1288			    i += 2;
1289			    att = atts[i];
1290			}
1291		    }
1292		    if (att == NULL) {
1293		        xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1294      "standalone: attribute %s on %s defaulted from external subset\n",
1295				    (const char *)fulln,
1296				    (const char *)attr->elem);
1297		    }
1298		}
1299		attr = attr->nexth;
1300	    }
1301	}
1302
1303	/*
1304	 * Actually insert defaulted values when needed
1305	 */
1306	attr = elemDecl->attributes;
1307	while (attr != NULL) {
1308	    /*
1309	     * Make sure that attributes redefinition occuring in the
1310	     * internal subset are not overriden by definitions in the
1311	     * external subset.
1312	     */
1313	    if (attr->defaultValue != NULL) {
1314		/*
1315		 * the element should be instantiated in the tree if:
1316		 *  - this is a namespace prefix
1317		 *  - the user required for completion in the tree
1318		 *    like XSLT
1319		 *  - there isn't already an attribute definition
1320		 *    in the internal subset overriding it.
1321		 */
1322		if (((attr->prefix != NULL) &&
1323		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1324		    ((attr->prefix == NULL) &&
1325		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1326		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1327		    xmlAttributePtr tst;
1328
1329		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1330					     attr->elem, attr->name,
1331					     attr->prefix);
1332		    if ((tst == attr) || (tst == NULL)) {
1333		        xmlChar fn[50];
1334			xmlChar *fulln;
1335
1336                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1337			if (fulln == NULL) {
1338			    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1339			    return;
1340			}
1341
1342			/*
1343			 * Check that the attribute is not declared in the
1344			 * serialization
1345			 */
1346			att = NULL;
1347			if (atts != NULL) {
1348			    i = 0;
1349			    att = atts[i];
1350			    while (att != NULL) {
1351				if (xmlStrEqual(att, fulln))
1352				    break;
1353				i += 2;
1354				att = atts[i];
1355			    }
1356			}
1357			if (att == NULL) {
1358			    xmlSAX2AttributeInternal(ctxt, fulln,
1359						 attr->defaultValue, prefix);
1360			}
1361			if ((fulln != fn) && (fulln != attr->name))
1362			    xmlFree(fulln);
1363		    }
1364		}
1365	    }
1366	    attr = attr->nexth;
1367	}
1368	if (internal == 1) {
1369	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1370		                             name, prefix);
1371	    internal = 0;
1372	    goto process_external_subset;
1373	}
1374    }
1375}
1376
1377/**
1378 * xmlSAX2StartElement:
1379 * @ctx: the user data (XML parser context)
1380 * @fullname:  The element name, including namespace prefix
1381 * @atts:  An array of name/value attributes pairs, NULL terminated
1382 *
1383 * called when an opening tag has been processed.
1384 */
1385void
1386xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1387{
1388    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1389    xmlNodePtr ret;
1390    xmlNodePtr parent = ctxt->node;
1391    xmlNsPtr ns;
1392    xmlChar *name;
1393    xmlChar *prefix;
1394    const xmlChar *att;
1395    const xmlChar *value;
1396    int i;
1397
1398#ifdef DEBUG_SAX
1399    xmlGenericError(xmlGenericErrorContext,
1400	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
1401#endif
1402
1403    /*
1404     * First check on validity:
1405     */
1406    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1407        ((ctxt->myDoc->intSubset == NULL) ||
1408	 ((ctxt->myDoc->intSubset->notations == NULL) &&
1409	  (ctxt->myDoc->intSubset->elements == NULL) &&
1410	  (ctxt->myDoc->intSubset->attributes == NULL) &&
1411	  (ctxt->myDoc->intSubset->entities == NULL)))) {
1412	xmlErrValid(ctxt, XML_ERR_NO_DTD,
1413	  "Validation failed: no DTD found !", NULL, NULL);
1414	ctxt->validate = 0;
1415    }
1416
1417
1418    /*
1419     * Split the full name into a namespace prefix and the tag name
1420     */
1421    name = xmlSplitQName(ctxt, fullname, &prefix);
1422
1423
1424    /*
1425     * Note : the namespace resolution is deferred until the end of the
1426     *        attributes parsing, since local namespace can be defined as
1427     *        an attribute at this level.
1428     */
1429    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1430    if (ret == NULL) {
1431        if (prefix != NULL)
1432	    xmlFree(prefix);
1433	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1434        return;
1435    }
1436    if (ctxt->myDoc->children == NULL) {
1437#ifdef DEBUG_SAX_TREE
1438	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1439#endif
1440        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1441    } else if (parent == NULL) {
1442        parent = ctxt->myDoc->children;
1443    }
1444    ctxt->nodemem = -1;
1445    if (ctxt->linenumbers) {
1446	if (ctxt->input != NULL) {
1447	    if (ctxt->input->line < 65535)
1448		ret->line = (short) ctxt->input->line;
1449	    else
1450	        ret->line = 65535;
1451	}
1452    }
1453
1454    /*
1455     * We are parsing a new node.
1456     */
1457#ifdef DEBUG_SAX_TREE
1458    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1459#endif
1460    nodePush(ctxt, ret);
1461
1462    /*
1463     * Link the child element
1464     */
1465    if (parent != NULL) {
1466        if (parent->type == XML_ELEMENT_NODE) {
1467#ifdef DEBUG_SAX_TREE
1468	    xmlGenericError(xmlGenericErrorContext,
1469		    "adding child %s to %s\n", name, parent->name);
1470#endif
1471	    xmlAddChild(parent, ret);
1472	} else {
1473#ifdef DEBUG_SAX_TREE
1474	    xmlGenericError(xmlGenericErrorContext,
1475		    "adding sibling %s to ", name);
1476	    xmlDebugDumpOneNode(stderr, parent, 0);
1477#endif
1478	    xmlAddSibling(parent, ret);
1479	}
1480    }
1481
1482    /*
1483     * Insert all the defaulted attributes from the DTD especially namespaces
1484     */
1485    if ((!ctxt->html) &&
1486	((ctxt->myDoc->intSubset != NULL) ||
1487	 (ctxt->myDoc->extSubset != NULL))) {
1488	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1489    }
1490
1491    /*
1492     * process all the attributes whose name start with "xmlns"
1493     */
1494    if (atts != NULL) {
1495        i = 0;
1496	att = atts[i++];
1497	value = atts[i++];
1498	if (!ctxt->html) {
1499	    while ((att != NULL) && (value != NULL)) {
1500		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1501		    (att[3] == 'n') && (att[4] == 's'))
1502		    xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1503
1504		att = atts[i++];
1505		value = atts[i++];
1506	    }
1507	}
1508    }
1509
1510    /*
1511     * Search the namespace, note that since the attributes have been
1512     * processed, the local namespaces are available.
1513     */
1514    ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1515    if ((ns == NULL) && (parent != NULL))
1516	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1517    if ((prefix != NULL) && (ns == NULL)) {
1518	ns = xmlNewNs(ret, NULL, prefix);
1519	if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1520	    ctxt->sax->warning(ctxt->userData,
1521		 "Namespace prefix %s is not defined\n", prefix);
1522    }
1523
1524    /*
1525     * set the namespace node, making sure that if the default namspace
1526     * is unbound on a parent we simply kee it NULL
1527     */
1528    if ((ns != NULL) && (ns->href != NULL) &&
1529	((ns->href[0] != 0) || (ns->prefix != NULL)))
1530	xmlSetNs(ret, ns);
1531
1532    /*
1533     * process all the other attributes
1534     */
1535    if (atts != NULL) {
1536        i = 0;
1537	att = atts[i++];
1538	value = atts[i++];
1539	if (ctxt->html) {
1540	    while (att != NULL) {
1541		xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1542		att = atts[i++];
1543		value = atts[i++];
1544	    }
1545	} else {
1546	    while ((att != NULL) && (value != NULL)) {
1547		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1548		    (att[3] != 'n') || (att[4] != 's'))
1549		    xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1550
1551		/*
1552		 * Next ones
1553		 */
1554		att = atts[i++];
1555		value = atts[i++];
1556	    }
1557	}
1558    }
1559
1560#ifdef LIBXML_VALID_ENABLED
1561    /*
1562     * If it's the Document root, finish the DTD validation and
1563     * check the document root element for validity
1564     */
1565    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1566	int chk;
1567
1568	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1569	if (chk <= 0)
1570	    ctxt->valid = 0;
1571	if (chk < 0)
1572	    ctxt->wellFormed = 0;
1573	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1574	ctxt->vctxt.finishDtd = 1;
1575    }
1576#endif /* LIBXML_VALID_ENABLED */
1577
1578    if (prefix != NULL)
1579	xmlFree(prefix);
1580
1581}
1582
1583/**
1584 * xmlSAX2EndElement:
1585 * @ctx: the user data (XML parser context)
1586 * @name:  The element name
1587 *
1588 * called when the end of an element has been detected.
1589 */
1590void
1591xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1592{
1593    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1594    xmlParserNodeInfo node_info;
1595    xmlNodePtr cur = ctxt->node;
1596
1597#ifdef DEBUG_SAX
1598    if (name == NULL)
1599        xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1600    else
1601	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1602#endif
1603
1604    /* Capture end position and add node */
1605    if (cur != NULL && ctxt->record_info) {
1606      node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1607      node_info.end_line = ctxt->input->line;
1608      node_info.node = cur;
1609      xmlParserAddNodeInfo(ctxt, &node_info);
1610    }
1611    ctxt->nodemem = -1;
1612
1613#ifdef LIBXML_VALID_ENABLED
1614    if (ctxt->validate && ctxt->wellFormed &&
1615        ctxt->myDoc && ctxt->myDoc->intSubset)
1616        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1617					     cur);
1618#endif /* LIBXML_VALID_ENABLED */
1619
1620
1621    /*
1622     * end of parsing of this node.
1623     */
1624#ifdef DEBUG_SAX_TREE
1625    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1626#endif
1627    nodePop(ctxt);
1628}
1629#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
1630
1631/*
1632 * xmlSAX2TextNode:
1633 * @ctxt:  the parser context
1634 * @str:  the input string
1635 * @len: the string length
1636 *
1637 * Remove the entities from an attribute value
1638 *
1639 * Returns the newly allocated string or NULL if not needed or error
1640 */
1641static xmlNodePtr
1642xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1643    xmlNodePtr ret;
1644    const xmlChar *intern = NULL;
1645
1646    /*
1647     * Allocate
1648     */
1649    if (ctxt->freeElems != NULL) {
1650	ret = ctxt->freeElems;
1651	ctxt->freeElems = ret->next;
1652	ctxt->freeElemsNr--;
1653    } else {
1654	ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1655    }
1656    if (ret == NULL) {
1657        xmlErrMemory(ctxt, "xmlSAX2Characters");
1658	return(NULL);
1659    }
1660    /*
1661     * intern the formatting blanks found between tags, or the
1662     * very short strings
1663     */
1664    if (ctxt->dictNames) {
1665        xmlChar cur = str[len];
1666
1667	if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1668	    ((cur == '<') && (str[len + 1] != '!')))) {
1669	    intern = xmlDictLookup(ctxt->dict, str, len);
1670	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1671	           (str[len + 1] != '!')) {
1672	    int i;
1673
1674	    for (i = 1;i < len;i++) {
1675		if (!IS_BLANK_CH(str[i])) goto skip;
1676	    }
1677	    intern = xmlDictLookup(ctxt->dict, str, len);
1678	}
1679    }
1680skip:
1681    memset(ret, 0, sizeof(xmlNode));
1682    ret->type = XML_TEXT_NODE;
1683
1684    ret->name = xmlStringText;
1685    if (intern == NULL) {
1686	ret->content = xmlStrndup(str, len);
1687	if (ret->content == NULL) {
1688	    xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1689	    xmlFree(ret);
1690	    return(NULL);
1691	}
1692    } else
1693	ret->content = (xmlChar *) intern;
1694
1695    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1696	xmlRegisterNodeDefaultValue(ret);
1697    return(ret);
1698}
1699
1700#ifdef LIBXML_VALID_ENABLED
1701/*
1702 * xmlSAX2DecodeAttrEntities:
1703 * @ctxt:  the parser context
1704 * @str:  the input string
1705 * @len: the string length
1706 *
1707 * Remove the entities from an attribute value
1708 *
1709 * Returns the newly allocated string or NULL if not needed or error
1710 */
1711static xmlChar *
1712xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1713                          const xmlChar *end) {
1714    const xmlChar *in;
1715    xmlChar *ret;
1716
1717    in = str;
1718    while (in < end)
1719        if (*in++ == '&')
1720	    goto decode;
1721    return(NULL);
1722decode:
1723    ctxt->depth++;
1724    ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1725				     XML_SUBSTITUTE_REF, 0,0,0);
1726    ctxt->depth--;
1727    return(ret);
1728}
1729#endif /* LIBXML_VALID_ENABLED */
1730
1731/**
1732 * xmlSAX2AttributeNs:
1733 * @ctx: the user data (XML parser context)
1734 * @localname:  the local name of the attribute
1735 * @prefix:  the attribute namespace prefix if available
1736 * @URI:  the attribute namespace name if available
1737 * @value:  Start of the attribute value
1738 * @valueend: end of the attribute value
1739 *
1740 * Handle an attribute that has been read by the parser.
1741 * The default handling is to convert the attribute into an
1742 * DOM subtree and past it in a new xmlAttr element added to
1743 * the element.
1744 */
1745static void
1746xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1747                   const xmlChar * localname,
1748                   const xmlChar * prefix,
1749		   const xmlChar * value,
1750		   const xmlChar * valueend)
1751{
1752    xmlAttrPtr ret;
1753    xmlNsPtr namespace = NULL;
1754    xmlChar *dup = NULL;
1755
1756    /*
1757     * Note: if prefix == NULL, the attribute is not in the default namespace
1758     */
1759    if (prefix != NULL)
1760	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1761
1762    /*
1763     * allocate the node
1764     */
1765    if (ctxt->freeAttrs != NULL) {
1766        ret = ctxt->freeAttrs;
1767	ctxt->freeAttrs = ret->next;
1768	ctxt->freeAttrsNr--;
1769	memset(ret, 0, sizeof(xmlAttr));
1770	ret->type = XML_ATTRIBUTE_NODE;
1771
1772	ret->parent = ctxt->node;
1773	ret->doc = ctxt->myDoc;
1774	ret->ns = namespace;
1775
1776	if (ctxt->dictNames)
1777	    ret->name = localname;
1778	else
1779	    ret->name = xmlStrdup(localname);
1780
1781        /* link at the end to preserv order, TODO speed up with a last */
1782	if (ctxt->node->properties == NULL) {
1783	    ctxt->node->properties = ret;
1784	} else {
1785	    xmlAttrPtr prev = ctxt->node->properties;
1786
1787	    while (prev->next != NULL) prev = prev->next;
1788	    prev->next = ret;
1789	    ret->prev = prev;
1790	}
1791
1792	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1793	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1794    } else {
1795	if (ctxt->dictNames)
1796	    ret = xmlNewNsPropEatName(ctxt->node, namespace,
1797	                              (xmlChar *) localname, NULL);
1798	else
1799	    ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1800	if (ret == NULL) {
1801	    xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
1802	    return;
1803	}
1804    }
1805
1806    if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1807	xmlNodePtr tmp;
1808
1809	/*
1810	 * We know that if there is an entity reference, then
1811	 * the string has been dup'ed and terminates with 0
1812	 * otherwise with ' or "
1813	 */
1814	if (*valueend != 0) {
1815	    tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1816	    ret->children = tmp;
1817	    ret->last = tmp;
1818	    if (tmp != NULL) {
1819		tmp->doc = ret->doc;
1820		tmp->parent = (xmlNodePtr) ret;
1821	    }
1822	} else {
1823	    ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1824						    valueend - value);
1825	    tmp = ret->children;
1826	    while (tmp != NULL) {
1827	        tmp->doc = ret->doc;
1828		tmp->parent = (xmlNodePtr) ret;
1829		if (tmp->next == NULL)
1830		    ret->last = tmp;
1831		tmp = tmp->next;
1832	    }
1833	}
1834    } else if (value != NULL) {
1835	xmlNodePtr tmp;
1836
1837	tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1838	ret->children = tmp;
1839	ret->last = tmp;
1840	if (tmp != NULL) {
1841	    tmp->doc = ret->doc;
1842	    tmp->parent = (xmlNodePtr) ret;
1843	}
1844    }
1845
1846#ifdef LIBXML_VALID_ENABLED
1847    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1848        ctxt->myDoc && ctxt->myDoc->intSubset) {
1849	/*
1850	 * If we don't substitute entities, the validation should be
1851	 * done on a value with replaced entities anyway.
1852	 */
1853        if (!ctxt->replaceEntities) {
1854	    dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1855	    if (dup == NULL) {
1856	        if (*valueend == 0) {
1857		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1858				    ctxt->myDoc, ctxt->node, ret, value);
1859		} else {
1860		    /*
1861		     * That should already be normalized.
1862		     * cheaper to finally allocate here than duplicate
1863		     * entry points in the full validation code
1864		     */
1865		    dup = xmlStrndup(value, valueend - value);
1866
1867		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1868				    ctxt->myDoc, ctxt->node, ret, dup);
1869		}
1870	    } else {
1871	        /*
1872		 * dup now contains a string of the flattened attribute
1873		 * content with entities substitued. Check if we need to
1874		 * apply an extra layer of normalization.
1875		 * It need to be done twice ... it's an extra burden related
1876		 * to the ability to keep references in attributes
1877		 */
1878		if (ctxt->attsSpecial != NULL) {
1879		    xmlChar *nvalnorm;
1880		    xmlChar fn[50];
1881		    xmlChar *fullname;
1882
1883		    fullname = xmlBuildQName(localname, prefix, fn, 50);
1884		    if (fullname != NULL) {
1885			ctxt->vctxt.valid = 1;
1886		        nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1887			                 &ctxt->vctxt, ctxt->myDoc,
1888					 ctxt->node, fullname, dup);
1889			if (ctxt->vctxt.valid != 1)
1890			    ctxt->valid = 0;
1891
1892			if ((fullname != fn) && (fullname != localname))
1893			    xmlFree(fullname);
1894			if (nvalnorm != NULL) {
1895			    xmlFree(dup);
1896			    dup = nvalnorm;
1897			}
1898		    }
1899		}
1900
1901		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1902			        ctxt->myDoc, ctxt->node, ret, dup);
1903	    }
1904	} else {
1905	    /*
1906	     * if entities already have been substitued, then
1907	     * the attribute as passed is already normalized
1908	     */
1909	    dup = xmlStrndup(value, valueend - value);
1910
1911	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1912	                             ctxt->myDoc, ctxt->node, ret, dup);
1913	}
1914    } else
1915#endif /* LIBXML_VALID_ENABLED */
1916           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1917	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1918	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1919        /*
1920	 * when validating, the ID registration is done at the attribute
1921	 * validation level. Otherwise we have to do specific handling here.
1922	 */
1923	if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
1924	    /* might be worth duplicate entry points and not copy */
1925	    if (dup == NULL)
1926	        dup = xmlStrndup(value, valueend - value);
1927	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1928	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
1929	    if (dup == NULL)
1930	        dup = xmlStrndup(value, valueend - value);
1931	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1932        } else if ((prefix == ctxt->str_xml) &&
1933	           (localname[0] == 'i') && (localname[1] == 'd') &&
1934		   (localname[2] == 0)) {
1935	    /*
1936	     * Add the xml:id value
1937	     *
1938	     * Open issue: normalization of the value.
1939	     */
1940	    if (dup == NULL)
1941	        dup = xmlStrndup(value, valueend - value);
1942#ifdef LIBXML_VALID_ENABLED
1943	    if (xmlValidateNCName(dup, 1) != 0) {
1944	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1945		      "xml:id : attribute value %s is not an NCName\n",
1946			    (const char *) dup, NULL);
1947	    }
1948#endif
1949	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
1950	}
1951    }
1952    if (dup != NULL)
1953	xmlFree(dup);
1954}
1955
1956/**
1957 * xmlSAX2StartElementNs:
1958 * @ctx:  the user data (XML parser context)
1959 * @localname:  the local name of the element
1960 * @prefix:  the element namespace prefix if available
1961 * @URI:  the element namespace name if available
1962 * @nb_namespaces:  number of namespace definitions on that node
1963 * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
1964 * @nb_attributes:  the number of attributes on that node
1965 * @nb_defaulted:  the number of defaulted attributes.
1966 * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
1967 *               attribute values.
1968 *
1969 * SAX2 callback when an element start has been detected by the parser.
1970 * It provides the namespace informations for the element, as well as
1971 * the new namespace declarations on the element.
1972 */
1973void
1974xmlSAX2StartElementNs(void *ctx,
1975                      const xmlChar *localname,
1976		      const xmlChar *prefix,
1977		      const xmlChar *URI,
1978		      int nb_namespaces,
1979		      const xmlChar **namespaces,
1980		      int nb_attributes,
1981		      int nb_defaulted,
1982		      const xmlChar **attributes)
1983{
1984    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1985    xmlNodePtr ret;
1986    xmlNodePtr parent = ctxt->node;
1987    xmlNsPtr last = NULL, ns;
1988    const xmlChar *uri, *pref;
1989    int i, j;
1990
1991    /*
1992     * First check on validity:
1993     */
1994    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1995        ((ctxt->myDoc->intSubset == NULL) ||
1996	 ((ctxt->myDoc->intSubset->notations == NULL) &&
1997	  (ctxt->myDoc->intSubset->elements == NULL) &&
1998	  (ctxt->myDoc->intSubset->attributes == NULL) &&
1999	  (ctxt->myDoc->intSubset->entities == NULL)))) {
2000	xmlErrValid(ctxt, XML_ERR_NO_DTD,
2001	  "Validation failed: no DTD found !", NULL, NULL);
2002	ctxt->validate = 0;
2003    }
2004
2005    /*
2006     * allocate the node
2007     */
2008    if (ctxt->freeElems != NULL) {
2009        ret = ctxt->freeElems;
2010	ctxt->freeElems = ret->next;
2011	ctxt->freeElemsNr--;
2012	memset(ret, 0, sizeof(xmlNode));
2013	ret->type = XML_ELEMENT_NODE;
2014
2015	if (ctxt->dictNames)
2016	    ret->name = localname;
2017	else {
2018	    ret->name = xmlStrdup(localname);
2019	    if (ret->name == NULL) {
2020	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2021		return;
2022	    }
2023	}
2024	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2025	    xmlRegisterNodeDefaultValue(ret);
2026    } else {
2027	if (ctxt->dictNames)
2028	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2029	                               (xmlChar *) localname, NULL);
2030	else
2031	    ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2032	if (ret == NULL) {
2033	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2034	    return;
2035	}
2036    }
2037    if (ctxt->linenumbers) {
2038	if (ctxt->input != NULL) {
2039	    if (ctxt->input->line < 65535)
2040		ret->line = (short) ctxt->input->line;
2041	    else
2042	        ret->line = 65535;
2043	}
2044    }
2045
2046    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2047        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2048    }
2049    /*
2050     * Build the namespace list
2051     */
2052    for (i = 0,j = 0;j < nb_namespaces;j++) {
2053        pref = namespaces[i++];
2054	uri = namespaces[i++];
2055	ns = xmlNewNs(NULL, uri, pref);
2056	if (ns != NULL) {
2057	    if (last == NULL) {
2058	        ret->nsDef = last = ns;
2059	    } else {
2060	        last->next = ns;
2061		last = ns;
2062	    }
2063	    if ((URI != NULL) && (prefix == pref))
2064		ret->ns = ns;
2065	} else {
2066	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2067	    return;
2068	}
2069#ifdef LIBXML_VALID_ENABLED
2070	if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2071	    ctxt->myDoc && ctxt->myDoc->intSubset) {
2072	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2073	                                           ret, prefix, ns, uri);
2074	}
2075#endif /* LIBXML_VALID_ENABLED */
2076    }
2077    ctxt->nodemem = -1;
2078
2079    /*
2080     * We are parsing a new node.
2081     */
2082    nodePush(ctxt, ret);
2083
2084    /*
2085     * Link the child element
2086     */
2087    if (parent != NULL) {
2088        if (parent->type == XML_ELEMENT_NODE) {
2089	    xmlAddChild(parent, ret);
2090	} else {
2091	    xmlAddSibling(parent, ret);
2092	}
2093    }
2094
2095    /*
2096     * Insert the defaulted attributes from the DTD only if requested:
2097     */
2098    if ((nb_defaulted != 0) &&
2099        ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2100	nb_attributes -= nb_defaulted;
2101
2102    /*
2103     * Search the namespace if it wasn't already found
2104     * Note that, if prefix is NULL, this searches for the default Ns
2105     */
2106    if ((URI != NULL) && (ret->ns == NULL)) {
2107        ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2108	if (ret->ns == NULL) {
2109	    ns = xmlNewNs(ret, NULL, prefix);
2110	    if (ns == NULL) {
2111	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2112		return;
2113	    }
2114	    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
2115		ctxt->sax->warning(ctxt->userData,
2116		     "Namespace prefix %s was not found\n", prefix);
2117	}
2118    }
2119
2120    /*
2121     * process all the other attributes
2122     */
2123    if (nb_attributes > 0) {
2124        for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2125	    xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2126	                       attributes[j+3], attributes[j+4]);
2127	}
2128    }
2129
2130#ifdef LIBXML_VALID_ENABLED
2131    /*
2132     * If it's the Document root, finish the DTD validation and
2133     * check the document root element for validity
2134     */
2135    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
2136	int chk;
2137
2138	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2139	if (chk <= 0)
2140	    ctxt->valid = 0;
2141	if (chk < 0)
2142	    ctxt->wellFormed = 0;
2143	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2144	ctxt->vctxt.finishDtd = 1;
2145    }
2146#endif /* LIBXML_VALID_ENABLED */
2147}
2148
2149/**
2150 * xmlSAX2EndElementNs:
2151 * @ctx:  the user data (XML parser context)
2152 * @localname:  the local name of the element
2153 * @prefix:  the element namespace prefix if available
2154 * @URI:  the element namespace name if available
2155 *
2156 * SAX2 callback when an element end has been detected by the parser.
2157 * It provides the namespace informations for the element.
2158 */
2159void
2160xmlSAX2EndElementNs(void *ctx,
2161                    const xmlChar * localname ATTRIBUTE_UNUSED,
2162                    const xmlChar * prefix ATTRIBUTE_UNUSED,
2163		    const xmlChar * URI ATTRIBUTE_UNUSED)
2164{
2165    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2166    xmlParserNodeInfo node_info;
2167    xmlNodePtr cur = ctxt->node;
2168
2169    /* Capture end position and add node */
2170    if ((ctxt->record_info) && (cur != NULL)) {
2171        node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2172        node_info.end_line = ctxt->input->line;
2173        node_info.node = cur;
2174        xmlParserAddNodeInfo(ctxt, &node_info);
2175    }
2176    ctxt->nodemem = -1;
2177
2178#ifdef LIBXML_VALID_ENABLED
2179    if (ctxt->validate && ctxt->wellFormed &&
2180        ctxt->myDoc && ctxt->myDoc->intSubset)
2181        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
2182#endif /* LIBXML_VALID_ENABLED */
2183
2184    /*
2185     * end of parsing of this node.
2186     */
2187    nodePop(ctxt);
2188}
2189
2190/**
2191 * xmlSAX2Reference:
2192 * @ctx: the user data (XML parser context)
2193 * @name:  The entity name
2194 *
2195 * called when an entity xmlSAX2Reference is detected.
2196 */
2197void
2198xmlSAX2Reference(void *ctx, const xmlChar *name)
2199{
2200    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2201    xmlNodePtr ret;
2202
2203#ifdef DEBUG_SAX
2204    xmlGenericError(xmlGenericErrorContext,
2205	    "SAX.xmlSAX2Reference(%s)\n", name);
2206#endif
2207    if (name[0] == '#')
2208	ret = xmlNewCharRef(ctxt->myDoc, name);
2209    else
2210	ret = xmlNewReference(ctxt->myDoc, name);
2211#ifdef DEBUG_SAX_TREE
2212    xmlGenericError(xmlGenericErrorContext,
2213	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2214#endif
2215    xmlAddChild(ctxt->node, ret);
2216}
2217
2218/**
2219 * xmlSAX2Characters:
2220 * @ctx: the user data (XML parser context)
2221 * @ch:  a xmlChar string
2222 * @len: the number of xmlChar
2223 *
2224 * receiving some chars from the parser.
2225 */
2226void
2227xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2228{
2229    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2230    xmlNodePtr lastChild;
2231
2232#ifdef DEBUG_SAX
2233    xmlGenericError(xmlGenericErrorContext,
2234	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2235#endif
2236    /*
2237     * Handle the data if any. If there is no child
2238     * add it as content, otherwise if the last child is text,
2239     * concatenate it, else create a new node of type text.
2240     */
2241
2242    if (ctxt->node == NULL) {
2243#ifdef DEBUG_SAX_TREE
2244	xmlGenericError(xmlGenericErrorContext,
2245		"add chars: ctxt->node == NULL !\n");
2246#endif
2247        return;
2248    }
2249    lastChild = ctxt->node->last;
2250#ifdef DEBUG_SAX_TREE
2251    xmlGenericError(xmlGenericErrorContext,
2252	    "add chars to %s \n", ctxt->node->name);
2253#endif
2254
2255    /*
2256     * Here we needed an accelerator mechanism in case of very large
2257     * elements. Use an attribute in the structure !!!
2258     */
2259    if (lastChild == NULL) {
2260        lastChild = xmlSAX2TextNode(ctxt, ch, len);
2261	if (lastChild != NULL) {
2262	    ctxt->node->children = lastChild;
2263	    ctxt->node->last = lastChild;
2264	    lastChild->parent = ctxt->node;
2265	    lastChild->doc = ctxt->node->doc;
2266	    ctxt->nodelen = len;
2267	    ctxt->nodemem = len + 1;
2268	} else {
2269	    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2270	    return;
2271	}
2272    } else {
2273	int coalesceText = (lastChild != NULL) &&
2274	    (lastChild->type == XML_TEXT_NODE) &&
2275	    (lastChild->name == xmlStringText);
2276	if ((coalesceText) && (ctxt->nodemem != 0)) {
2277	    /*
2278	     * The whole point of maintaining nodelen and nodemem,
2279	     * xmlTextConcat is too costly, i.e. compute length,
2280	     * reallocate a new buffer, move data, append ch. Here
2281	     * We try to minimaze realloc() uses and avoid copying
2282	     * and recomputing length over and over.
2283	     */
2284	    if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2285	        (xmlDictOwns(ctxt->dict, lastChild->content))) {
2286		lastChild->content = xmlStrdup(lastChild->content);
2287	    }
2288	    if (ctxt->nodelen + len >= ctxt->nodemem) {
2289		xmlChar *newbuf;
2290		int size;
2291
2292		size = ctxt->nodemem + len;
2293		size *= 2;
2294                newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2295		if (newbuf == NULL) {
2296		    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2297		    return;
2298		}
2299		ctxt->nodemem = size;
2300		lastChild->content = newbuf;
2301	    }
2302	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2303	    ctxt->nodelen += len;
2304	    lastChild->content[ctxt->nodelen] = 0;
2305	} else if (coalesceText) {
2306	    if (xmlTextConcat(lastChild, ch, len)) {
2307		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2308	    }
2309	    if (ctxt->node->children != NULL) {
2310		ctxt->nodelen = xmlStrlen(lastChild->content);
2311		ctxt->nodemem = ctxt->nodelen + 1;
2312	    }
2313	} else {
2314	    /* Mixed content, first time */
2315	    lastChild = xmlSAX2TextNode(ctxt, ch, len);
2316	    if (lastChild != NULL) {
2317		xmlAddChild(ctxt->node, lastChild);
2318		if (ctxt->node->children != NULL) {
2319		    ctxt->nodelen = len;
2320		    ctxt->nodemem = len + 1;
2321		}
2322	    }
2323	}
2324    }
2325}
2326
2327/**
2328 * xmlSAX2IgnorableWhitespace:
2329 * @ctx: the user data (XML parser context)
2330 * @ch:  a xmlChar string
2331 * @len: the number of xmlChar
2332 *
2333 * receiving some ignorable whitespaces from the parser.
2334 * UNUSED: by default the DOM building will use xmlSAX2Characters
2335 */
2336void
2337xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2338{
2339    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2340#ifdef DEBUG_SAX
2341    xmlGenericError(xmlGenericErrorContext,
2342	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2343#endif
2344}
2345
2346/**
2347 * xmlSAX2ProcessingInstruction:
2348 * @ctx: the user data (XML parser context)
2349 * @target:  the target name
2350 * @data: the PI data's
2351 *
2352 * A processing instruction has been parsed.
2353 */
2354void
2355xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2356                      const xmlChar *data)
2357{
2358    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2359    xmlNodePtr ret;
2360    xmlNodePtr parent = ctxt->node;
2361
2362#ifdef DEBUG_SAX
2363    xmlGenericError(xmlGenericErrorContext,
2364	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2365#endif
2366
2367    ret = xmlNewPI(target, data);
2368    if (ret == NULL) return;
2369    parent = ctxt->node;
2370
2371    if (ctxt->inSubset == 1) {
2372	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2373	return;
2374    } else if (ctxt->inSubset == 2) {
2375	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2376	return;
2377    }
2378    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2379#ifdef DEBUG_SAX_TREE
2380	    xmlGenericError(xmlGenericErrorContext,
2381		    "Setting PI %s as root\n", target);
2382#endif
2383        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2384	return;
2385    }
2386    if (parent->type == XML_ELEMENT_NODE) {
2387#ifdef DEBUG_SAX_TREE
2388	xmlGenericError(xmlGenericErrorContext,
2389		"adding PI %s child to %s\n", target, parent->name);
2390#endif
2391	xmlAddChild(parent, ret);
2392    } else {
2393#ifdef DEBUG_SAX_TREE
2394	xmlGenericError(xmlGenericErrorContext,
2395		"adding PI %s sibling to ", target);
2396	xmlDebugDumpOneNode(stderr, parent, 0);
2397#endif
2398	xmlAddSibling(parent, ret);
2399    }
2400}
2401
2402/**
2403 * xmlSAX2Comment:
2404 * @ctx: the user data (XML parser context)
2405 * @value:  the xmlSAX2Comment content
2406 *
2407 * A xmlSAX2Comment has been parsed.
2408 */
2409void
2410xmlSAX2Comment(void *ctx, const xmlChar *value)
2411{
2412    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2413    xmlNodePtr ret;
2414    xmlNodePtr parent = ctxt->node;
2415
2416#ifdef DEBUG_SAX
2417    xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2418#endif
2419    ret = xmlNewDocComment(ctxt->myDoc, value);
2420    if (ret == NULL) return;
2421
2422    if (ctxt->inSubset == 1) {
2423	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2424	return;
2425    } else if (ctxt->inSubset == 2) {
2426	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2427	return;
2428    }
2429    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2430#ifdef DEBUG_SAX_TREE
2431	    xmlGenericError(xmlGenericErrorContext,
2432		    "Setting xmlSAX2Comment as root\n");
2433#endif
2434        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2435	return;
2436    }
2437    if (parent->type == XML_ELEMENT_NODE) {
2438#ifdef DEBUG_SAX_TREE
2439	xmlGenericError(xmlGenericErrorContext,
2440		"adding xmlSAX2Comment child to %s\n", parent->name);
2441#endif
2442	xmlAddChild(parent, ret);
2443    } else {
2444#ifdef DEBUG_SAX_TREE
2445	xmlGenericError(xmlGenericErrorContext,
2446		"adding xmlSAX2Comment sibling to ");
2447	xmlDebugDumpOneNode(stderr, parent, 0);
2448#endif
2449	xmlAddSibling(parent, ret);
2450    }
2451}
2452
2453/**
2454 * xmlSAX2CDataBlock:
2455 * @ctx: the user data (XML parser context)
2456 * @value:  The pcdata content
2457 * @len:  the block length
2458 *
2459 * called when a pcdata block has been parsed
2460 */
2461void
2462xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2463{
2464    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2465    xmlNodePtr ret, lastChild;
2466
2467#ifdef DEBUG_SAX
2468    xmlGenericError(xmlGenericErrorContext,
2469	    "SAX.pcdata(%.10s, %d)\n", value, len);
2470#endif
2471    lastChild = xmlGetLastChild(ctxt->node);
2472#ifdef DEBUG_SAX_TREE
2473    xmlGenericError(xmlGenericErrorContext,
2474	    "add chars to %s \n", ctxt->node->name);
2475#endif
2476    if ((lastChild != NULL) &&
2477        (lastChild->type == XML_CDATA_SECTION_NODE)) {
2478	xmlTextConcat(lastChild, value, len);
2479    } else {
2480	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2481	xmlAddChild(ctxt->node, ret);
2482    }
2483}
2484
2485static int xmlSAX2DefaultVersionValue = 2;
2486
2487#ifdef LIBXML_SAX1_ENABLED
2488/**
2489 * xmlSAXDefaultVersion:
2490 * @version:  the version, 1 or 2
2491 *
2492 * Set the default version of SAX used globally by the library.
2493 * By default, during initialization the default is set to 2.
2494 * Note that it is generally a better coding style to use
2495 * xmlSAXVersion() to set up the version explicitly for a given
2496 * parsing context.
2497 *
2498 * Returns the previous value in case of success and -1 in case of error.
2499 */
2500int
2501xmlSAXDefaultVersion(int version)
2502{
2503    int ret = xmlSAX2DefaultVersionValue;
2504
2505    if ((version != 1) && (version != 2))
2506        return(-1);
2507    xmlSAX2DefaultVersionValue = version;
2508    return(ret);
2509}
2510#endif /* LIBXML_SAX1_ENABLED */
2511
2512/**
2513 * xmlSAXVersion:
2514 * @hdlr:  the SAX handler
2515 * @version:  the version, 1 or 2
2516 *
2517 * Initialize the default XML SAX handler according to the version
2518 *
2519 * Returns 0 in case of success and -1 in case of error.
2520 */
2521int
2522xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2523{
2524    if (hdlr == NULL) return(-1);
2525    if (version == 2) {
2526	hdlr->startElement = NULL;
2527	hdlr->endElement = NULL;
2528	hdlr->startElementNs = xmlSAX2StartElementNs;
2529	hdlr->endElementNs = xmlSAX2EndElementNs;
2530	hdlr->serror = NULL;
2531	hdlr->initialized = XML_SAX2_MAGIC;
2532#ifdef LIBXML_SAX1_ENABLED
2533    } else if (version == 1) {
2534	hdlr->startElement = xmlSAX2StartElement;
2535	hdlr->endElement = xmlSAX2EndElement;
2536	hdlr->initialized = 1;
2537#endif /* LIBXML_SAX1_ENABLED */
2538    } else
2539        return(-1);
2540    hdlr->internalSubset = xmlSAX2InternalSubset;
2541    hdlr->externalSubset = xmlSAX2ExternalSubset;
2542    hdlr->isStandalone = xmlSAX2IsStandalone;
2543    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2544    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2545    hdlr->resolveEntity = xmlSAX2ResolveEntity;
2546    hdlr->getEntity = xmlSAX2GetEntity;
2547    hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2548    hdlr->entityDecl = xmlSAX2EntityDecl;
2549    hdlr->attributeDecl = xmlSAX2AttributeDecl;
2550    hdlr->elementDecl = xmlSAX2ElementDecl;
2551    hdlr->notationDecl = xmlSAX2NotationDecl;
2552    hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2553    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2554    hdlr->startDocument = xmlSAX2StartDocument;
2555    hdlr->endDocument = xmlSAX2EndDocument;
2556    hdlr->reference = xmlSAX2Reference;
2557    hdlr->characters = xmlSAX2Characters;
2558    hdlr->cdataBlock = xmlSAX2CDataBlock;
2559    hdlr->ignorableWhitespace = xmlSAX2Characters;
2560    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2561    hdlr->comment = xmlSAX2Comment;
2562    hdlr->warning = xmlParserWarning;
2563    hdlr->error = xmlParserError;
2564    hdlr->fatalError = xmlParserError;
2565
2566    return(0);
2567}
2568
2569/**
2570 * xmlSAX2InitDefaultSAXHandler:
2571 * @hdlr:  the SAX handler
2572 * @warning:  flag if non-zero sets the handler warning procedure
2573 *
2574 * Initialize the default XML SAX2 handler
2575 */
2576void
2577xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2578{
2579    if ((hdlr == NULL) || (hdlr->initialized != 0))
2580	return;
2581
2582    xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2583    if (warning == 0)
2584	hdlr->warning = NULL;
2585    else
2586	hdlr->warning = xmlParserWarning;
2587}
2588
2589/**
2590 * xmlDefaultSAXHandlerInit:
2591 *
2592 * Initialize the default SAX2 handler
2593 */
2594void
2595xmlDefaultSAXHandlerInit(void)
2596{
2597#ifdef LIBXML_SAX1_ENABLED
2598    xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
2599#endif /* LIBXML_SAX1_ENABLED */
2600}
2601
2602#ifdef LIBXML_HTML_ENABLED
2603
2604/**
2605 * xmlSAX2InitHtmlDefaultSAXHandler:
2606 * @hdlr:  the SAX handler
2607 *
2608 * Initialize the default HTML SAX2 handler
2609 */
2610void
2611xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2612{
2613    if(hdlr->initialized != 0)
2614	return;
2615
2616    hdlr->internalSubset = xmlSAX2InternalSubset;
2617    hdlr->externalSubset = NULL;
2618    hdlr->isStandalone = NULL;
2619    hdlr->hasInternalSubset = NULL;
2620    hdlr->hasExternalSubset = NULL;
2621    hdlr->resolveEntity = NULL;
2622    hdlr->getEntity = xmlSAX2GetEntity;
2623    hdlr->getParameterEntity = NULL;
2624    hdlr->entityDecl = NULL;
2625    hdlr->attributeDecl = NULL;
2626    hdlr->elementDecl = NULL;
2627    hdlr->notationDecl = NULL;
2628    hdlr->unparsedEntityDecl = NULL;
2629    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2630    hdlr->startDocument = xmlSAX2StartDocument;
2631    hdlr->endDocument = xmlSAX2EndDocument;
2632    hdlr->startElement = xmlSAX2StartElement;
2633    hdlr->endElement = xmlSAX2EndElement;
2634    hdlr->reference = NULL;
2635    hdlr->characters = xmlSAX2Characters;
2636    hdlr->cdataBlock = xmlSAX2CDataBlock;
2637    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2638    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2639    hdlr->comment = xmlSAX2Comment;
2640    hdlr->warning = xmlParserWarning;
2641    hdlr->error = xmlParserError;
2642    hdlr->fatalError = xmlParserError;
2643
2644    hdlr->initialized = 1;
2645}
2646
2647/**
2648 * htmlDefaultSAXHandlerInit:
2649 *
2650 * Initialize the default SAX handler
2651 */
2652void
2653htmlDefaultSAXHandlerInit(void)
2654{
2655    xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
2656}
2657
2658#endif /* LIBXML_HTML_ENABLED */
2659
2660#ifdef LIBXML_DOCB_ENABLED
2661
2662/**
2663 * xmlSAX2InitDocbDefaultSAXHandler:
2664 * @hdlr:  the SAX handler
2665 *
2666 * Initialize the default DocBook SAX2 handler
2667 */
2668void
2669xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2670{
2671    if(hdlr->initialized != 0)
2672	return;
2673
2674    hdlr->internalSubset = xmlSAX2InternalSubset;
2675    hdlr->externalSubset = NULL;
2676    hdlr->isStandalone = xmlSAX2IsStandalone;
2677    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2678    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2679    hdlr->resolveEntity = xmlSAX2ResolveEntity;
2680    hdlr->getEntity = xmlSAX2GetEntity;
2681    hdlr->getParameterEntity = NULL;
2682    hdlr->entityDecl = xmlSAX2EntityDecl;
2683    hdlr->attributeDecl = NULL;
2684    hdlr->elementDecl = NULL;
2685    hdlr->notationDecl = NULL;
2686    hdlr->unparsedEntityDecl = NULL;
2687    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2688    hdlr->startDocument = xmlSAX2StartDocument;
2689    hdlr->endDocument = xmlSAX2EndDocument;
2690    hdlr->startElement = xmlSAX2StartElement;
2691    hdlr->endElement = xmlSAX2EndElement;
2692    hdlr->reference = xmlSAX2Reference;
2693    hdlr->characters = xmlSAX2Characters;
2694    hdlr->cdataBlock = NULL;
2695    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2696    hdlr->processingInstruction = NULL;
2697    hdlr->comment = xmlSAX2Comment;
2698    hdlr->warning = xmlParserWarning;
2699    hdlr->error = xmlParserError;
2700    hdlr->fatalError = xmlParserError;
2701
2702    hdlr->initialized = 1;
2703}
2704
2705/**
2706 * docbDefaultSAXHandlerInit:
2707 *
2708 * Initialize the default SAX handler
2709 */
2710void
2711docbDefaultSAXHandlerInit(void)
2712{
2713    xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
2714}
2715
2716#endif /* LIBXML_DOCB_ENABLED */
2717