updated libxml2 to 2.5.10
[TestXSLT.git] / libxml2 / SAX.c
1 /*
2  * SAX.c : Default SAX 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_SAX */
30 /* #define DEBUG_SAX_TREE */
31
32 /**
33  * getPublicId:
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  */
40 const xmlChar *
41 getPublicId(void *ctx ATTRIBUTE_UNUSED)
42 {
43     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
44     return(NULL);
45 }
46
47 /**
48  * getSystemId:
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  */
56 const xmlChar *
57 getSystemId(void *ctx)
58 {
59     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
60     return((const xmlChar *) ctxt->input->filename); 
61 }
62
63 /**
64  * getLineNumber:
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  */
71 int
72 getLineNumber(void *ctx)
73 {
74     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
75     return(ctxt->input->line);
76 }
77
78 /**
79  * getColumnNumber:
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  */
86 int
87 getColumnNumber(void *ctx)
88 {
89     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
90     return(ctxt->input->col);
91 }
92
93 /**
94  * isStandalone:
95  * @ctx: the user data (XML parser context)
96  *
97  * Is this document tagged standalone ?
98  *
99  * Returns 1 if true
100  */
101 int
102 isStandalone(void *ctx)
103 {
104     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
105     return(ctxt->myDoc->standalone == 1);
106 }
107
108 /**
109  * hasInternalSubset:
110  * @ctx: the user data (XML parser context)
111  *
112  * Does this document has an internal subset
113  *
114  * Returns 1 if true
115  */
116 int
117 hasInternalSubset(void *ctx)
118 {
119     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
120     return(ctxt->myDoc->intSubset != NULL);
121 }
122
123 /**
124  * hasExternalSubset:
125  * @ctx: the user data (XML parser context)
126  *
127  * Does this document has an external subset
128  *
129  * Returns 1 if true
130  */
131 int
132 hasExternalSubset(void *ctx)
133 {
134     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
135     return(ctxt->myDoc->extSubset != NULL);
136 }
137
138 /**
139  * internalSubset:
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  */
147 void
148 internalSubset(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.internalSubset(%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  * externalSubset:
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  */
182 void
183 externalSubset(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.externalSubset(%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                      "externalSubset: 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  * resolveEntity:
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 resolveEntity() 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  */
305 xmlParserInputPtr
306 resolveEntity(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.resolveEntity(%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  * getEntity:
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  */
341 xmlEntityPtr
342 getEntity(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.getEntity(%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  * getParameterEntity:
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  */
419 xmlEntityPtr
420 getParameterEntity(void *ctx, const xmlChar *name)
421 {
422     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
423     xmlEntityPtr ret;
424
425 #ifdef DEBUG_SAX
426     xmlGenericError(xmlGenericErrorContext,
427             "SAX.getParameterEntity(%s)\n", name);
428 #endif
429
430     ret = xmlGetParameterEntity(ctxt->myDoc, name);
431     return(ret);
432 }
433
434
435 /**
436  * entityDecl:
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  */
446 void
447 entityDecl(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.entityDecl(%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.entityDecl(%s) called while not in subset\n", name);
500     }
501 }
502
503 /**
504  * attributeDecl:
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  */
515 void
516 attributeDecl(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.attributeDecl(%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.attributeDecl(%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  * elementDecl:
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  */
566 void
567 elementDecl(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.elementDecl(%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.elementDecl(%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  * notationDecl:
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  */
608 void
609 notationDecl(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.notationDecl(%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.notationDecl(%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.notationDecl(%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  * unparsedEntityDecl:
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  */
656 void
657 unparsedEntityDecl(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.unparsedEntityDecl(%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.unparsedEntityDecl(%s) called while not in subset\n", name);
712     }
713 }
714
715 /**
716  * setDocumentLocator:
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  */
723 void
724 setDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
725 {
726     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
727 #ifdef DEBUG_SAX
728     xmlGenericError(xmlGenericErrorContext,
729             "SAX.setDocumentLocator()\n");
730 #endif
731 }
732
733 /**
734  * startDocument:
735  * @ctx: the user data (XML parser context)
736  *
737  * called when the document start being processed.
738  */
739 void
740 startDocument(void *ctx)
741 {
742     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
743     xmlDocPtr doc;
744
745 #ifdef DEBUG_SAX
746     xmlGenericError(xmlGenericErrorContext,
747             "SAX.startDocument()\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.startDocument(): 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.startDocument(): 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  * endDocument:
798  * @ctx: the user data (XML parser context)
799  *
800  * called when the document end has been detected.
801  */
802 void
803 endDocument(void *ctx)
804 {
805     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
806 #ifdef DEBUG_SAX
807     xmlGenericError(xmlGenericErrorContext,
808             "SAX.endDocument()\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  * my_attribute:
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  */
844 static void
845 my_attribute(void *ctx, const xmlChar *fullname, const xmlChar *value,
846              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 #ifdef DEBUG_SAX
857     xmlGenericError(xmlGenericErrorContext,
858     "SAX.attribute(%s, %s)\n", fullname, value);
859 #endif
860  ****************/
861     /*
862      * Split the full name into a namespace prefix and the tag name
863      */
864     name = xmlSplitQName(ctxt, fullname, &ns);
865     if ((name != NULL) && (name[0] == 0)) {
866         if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
867             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
868                 ctxt->sax->error(ctxt->userData, 
869                      "invalid namespace declaration '%s'\n", fullname);
870         } else {
871             if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
872                 ctxt->sax->warning(ctxt->userData, 
873                      "Avoid attribute ending with ':' like '%s'\n", fullname);
874         }
875         if (ns != NULL)
876             xmlFree(ns);
877         ns = NULL;
878         xmlFree(name);
879         name = xmlStrdup(fullname);
880     }
881     if (name == NULL) {
882         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
883             ctxt->sax->error(ctxt->userData, 
884                  "SAX.startElement(): out of memory\n");
885         ctxt->errNo = XML_ERR_NO_MEMORY;
886         ctxt->instate = XML_PARSER_EOF;
887         ctxt->disableSAX = 1;
888         if (ns != NULL)
889             xmlFree(ns);
890         return;
891     }
892
893     /*
894      * Do the last stage of the attribute normalization
895      * Needed for HTML too:
896      *   http://www.w3.org/TR/html4/types.html#h-6.2
897      */
898     ctxt->vctxt.valid = 1;
899     nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
900                                            ctxt->myDoc, ctxt->node,
901                                            fullname, value);
902     if (ctxt->vctxt.valid != 1) {
903         ctxt->valid = 0;
904     }
905     if (nval != NULL)
906         value = nval;
907
908     /*
909      * Check whether it's a namespace definition
910      */
911     if ((!ctxt->html) && (ns == NULL) &&
912         (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
913         (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
914         xmlNsPtr nsret;
915         xmlChar *val;
916
917         if (!ctxt->replaceEntities) {
918             ctxt->depth++;
919             val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
920                                           0,0,0);
921             ctxt->depth--;
922         } else {
923             val = (xmlChar *) value;
924         }
925
926         if (val[0] != 0) {
927             xmlURIPtr uri;
928
929             uri = xmlParseURI((const char *)val);
930             if (uri == NULL) {
931                 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
932                     ctxt->sax->warning(ctxt->userData, 
933                          "nmlns: %s not a valid URI\n", val);
934             } else {
935                 if (uri->scheme == NULL) {
936                     if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
937                         ctxt->sax->warning(ctxt->userData, 
938                              "xmlns: URI %s is not absolute\n", val);
939                 }
940                 xmlFreeURI(uri);
941             }
942         }
943
944         /* a default namespace definition */
945         nsret = xmlNewNs(ctxt->node, val, NULL);
946
947         /*
948          * Validate also for namespace decls, they are attributes from
949          * an XML-1.0 perspective
950          */
951         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
952             ctxt->myDoc && ctxt->myDoc->intSubset)
953             ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
954                                            ctxt->node, prefix, nsret, val);
955         if (name != NULL) 
956             xmlFree(name);
957         if (nval != NULL)
958             xmlFree(nval);
959         if (val != value)
960             xmlFree(val);
961         return;
962     }
963     if ((!ctxt->html) &&
964         (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
965         (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
966         xmlNsPtr nsret;
967         xmlChar *val;
968
969         if (!ctxt->replaceEntities) {
970             ctxt->depth++;
971             val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
972                                           0,0,0);
973             ctxt->depth--;
974             if (val == NULL) {
975                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
976                     ctxt->sax->error(ctxt->userData, 
977                          "SAX.startElement(): out of memory\n");
978                 ctxt->errNo = XML_ERR_NO_MEMORY;
979                 ctxt->instate = XML_PARSER_EOF;
980                 ctxt->disableSAX = 1;
981                 xmlFree(ns);
982                 if (name != NULL) 
983                     xmlFree(name);
984                 return;
985             }
986         } else {
987             val = (xmlChar *) value;
988         }
989
990         if (val[0] == 0) {
991             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
992                 ctxt->sax->error(ctxt->userData, 
993                      "Empty namespace name for prefix %s\n", name);
994         }
995         if ((ctxt->pedantic != 0) && (val[0] != 0)) {
996             xmlURIPtr uri;
997
998             uri = xmlParseURI((const char *)val);
999             if (uri == NULL) {
1000                 if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1001                     ctxt->sax->warning(ctxt->userData, 
1002                          "xmlns:%s: %s not a valid URI\n", name, value);
1003             } else {
1004                 if (uri->scheme == NULL) {
1005                     if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1006                         ctxt->sax->warning(ctxt->userData, 
1007                            "xmlns:%s: URI %s is not absolute\n", name, value);
1008                 }
1009                 xmlFreeURI(uri);
1010             }
1011         }
1012
1013         /* a standard namespace definition */
1014         nsret = xmlNewNs(ctxt->node, val, name);
1015         xmlFree(ns);
1016         /*
1017          * Validate also for namespace decls, they are attributes from
1018          * an XML-1.0 perspective
1019          */
1020         if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1021             ctxt->myDoc && ctxt->myDoc->intSubset)
1022             ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1023                                            ctxt->node, prefix, nsret, value);
1024         if (name != NULL) 
1025             xmlFree(name);
1026         if (nval != NULL)
1027             xmlFree(nval);
1028         if (val != value)
1029             xmlFree(val);
1030         return;
1031     }
1032
1033     if (ns != NULL) {
1034         xmlAttrPtr prop;
1035         namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1036
1037         prop = ctxt->node->properties;
1038         while (prop != NULL) {
1039             if (prop->ns != NULL) {
1040                 if ((xmlStrEqual(name, prop->name)) &&
1041                     ((namespace == prop->ns) ||
1042                      (xmlStrEqual(namespace->href, prop->ns->href)))) {
1043                     ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1044                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1045                         ctxt->sax->error(ctxt->userData,
1046                                 "Attribute %s in %s redefined\n",
1047                                          name, namespace->href);
1048                     ctxt->wellFormed = 0;
1049                     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1050                     goto error;
1051                 }
1052             }
1053             prop = prop->next;
1054         }
1055     } else {
1056         namespace = NULL;
1057     }
1058
1059     /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1060     ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1061
1062     if (ret != NULL) {
1063         if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1064             xmlNodePtr tmp;
1065
1066             ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1067             tmp = ret->children;
1068             while (tmp != NULL) {
1069                 tmp->parent = (xmlNodePtr) ret;
1070                 if (tmp->next == NULL)
1071                     ret->last = tmp;
1072                 tmp = tmp->next;
1073             }
1074         } else if (value != NULL) {
1075             ret->children = xmlNewDocText(ctxt->myDoc, value);
1076             ret->last = ret->children;
1077             if (ret->children != NULL)
1078                 ret->children->parent = (xmlNodePtr) ret;
1079         }
1080     }
1081
1082     if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1083         ctxt->myDoc && ctxt->myDoc->intSubset) {
1084         
1085         /*
1086          * If we don't substitute entities, the validation should be
1087          * done on a value with replaced entities anyway.
1088          */
1089         if (!ctxt->replaceEntities) {
1090             xmlChar *val;
1091
1092             ctxt->depth++;
1093             val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1094                                           0,0,0);
1095             ctxt->depth--;
1096             
1097             if (val == NULL)
1098                 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1099                                 ctxt->myDoc, ctxt->node, ret, value);
1100             else {
1101                 xmlChar *nvalnorm;
1102
1103                 /*
1104                  * Do the last stage of the attribute normalization
1105                  * It need to be done twice ... it's an extra burden related
1106                  * to the ability to keep references in attributes
1107                  */
1108                 nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1109                                             ctxt->node, fullname, val);
1110                 if (nvalnorm != NULL) {
1111                     xmlFree(val);
1112                     val = nvalnorm;
1113                 }
1114
1115                 ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1116                                 ctxt->myDoc, ctxt->node, ret, val);
1117                 xmlFree(val);
1118             }
1119         } else {
1120             ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1121                                                ctxt->node, ret, value);
1122         }
1123     } else if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1124                (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1125                 ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1126         /*
1127          * when validating, the ID registration is done at the attribute
1128          * validation level. Otherwise we have to do specific handling here.
1129          */
1130         if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1131             xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1132         else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1133             xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1134     }
1135
1136 error:
1137     if (nval != NULL)
1138         xmlFree(nval);
1139     if (ns != NULL) 
1140         xmlFree(ns);
1141 }
1142
1143 /**
1144  * attribute:
1145  * @ctx: the user data (XML parser context)
1146  * @fullname:  The attribute name, including namespace prefix
1147  * @value:  The attribute value
1148  *
1149  * Handle an attribute that has been read by the parser.
1150  * The default handling is to convert the attribute into an
1151  * DOM subtree and past it in a new xmlAttr element added to
1152  * the element.
1153  */
1154 void
1155 attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
1156 {
1157     my_attribute(ctx, fullname, value, NULL);
1158 }
1159
1160 /*
1161  * xmlCheckDefaultedAttributes:
1162  *
1163  * Check defaulted attributes from the DTD
1164  */
1165 static void
1166 xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1167         const xmlChar *prefix, const xmlChar **atts) {
1168     xmlElementPtr elemDecl;
1169     const xmlChar *att;
1170     int internal = 1;
1171     int i;
1172
1173     elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1174     if (elemDecl == NULL) {
1175         elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1176         internal = 0;
1177     }
1178
1179 process_external_subset:
1180
1181     if (elemDecl != NULL) {
1182         xmlAttributePtr attr = elemDecl->attributes;
1183         /*
1184          * Check against defaulted attributes from the external subset
1185          * if the document is stamped as standalone
1186          */
1187         if ((ctxt->myDoc->standalone == 1) &&
1188             (ctxt->myDoc->extSubset != NULL) &&
1189             (ctxt->validate)) {
1190             while (attr != NULL) {
1191                 if ((attr->defaultValue != NULL) &&
1192                     (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1193                                         attr->elem, attr->name,
1194                                         attr->prefix) == attr) &&
1195                     (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1196                                         attr->elem, attr->name,
1197                                         attr->prefix) == NULL)) {
1198                     xmlChar *fulln;
1199
1200                     if (attr->prefix != NULL) {
1201                         fulln = xmlStrdup(attr->prefix);
1202                         fulln = xmlStrcat(fulln, BAD_CAST ":");
1203                         fulln = xmlStrcat(fulln, attr->name);
1204                     } else {
1205                         fulln = xmlStrdup(attr->name);
1206                     }
1207
1208                     /*
1209                      * Check that the attribute is not declared in the
1210                      * serialization
1211                      */
1212                     att = NULL;
1213                     if (atts != NULL) {
1214                         i = 0;
1215                         att = atts[i];
1216                         while (att != NULL) {
1217                             if (xmlStrEqual(att, fulln))
1218                                 break;
1219                             i += 2;
1220                             att = atts[i];
1221                         }
1222                     }
1223                     if (att == NULL) {
1224                         if (ctxt->vctxt.error != NULL)
1225                             ctxt->vctxt.error(ctxt->vctxt.userData,
1226       "standalone: attribute %s on %s defaulted from external subset\n",
1227                                               fulln, attr->elem);
1228                         ctxt->valid = 0;
1229                     }
1230                 }
1231                 attr = attr->nexth;
1232             }
1233         }
1234
1235         /*
1236          * Actually insert defaulted values when needed
1237          */
1238         attr = elemDecl->attributes;
1239         while (attr != NULL) {
1240             /*
1241              * Make sure that attributes redefinition occuring in the
1242              * internal subset are not overriden by definitions in the
1243              * external subset.
1244              */
1245             if (attr->defaultValue != NULL) {
1246                 /*
1247                  * the element should be instantiated in the tree if:
1248                  *  - this is a namespace prefix
1249                  *  - the user required for completion in the tree
1250                  *    like XSLT
1251                  *  - there isn't already an attribute definition 
1252                  *    in the internal subset overriding it.
1253                  */
1254                 if (((attr->prefix != NULL) &&
1255                      (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1256                     ((attr->prefix == NULL) &&
1257                      (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1258                     (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1259                     xmlAttributePtr tst;
1260
1261                     tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1262                                              attr->elem, attr->name,
1263                                              attr->prefix);
1264                     if ((tst == attr) || (tst == NULL)) {
1265                         xmlChar fn[50];
1266                         xmlChar *fulln;
1267
1268                         fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1269                         if (fulln == NULL) {
1270                             if ((ctxt->sax != NULL) &&
1271                                 (ctxt->sax->error != NULL))
1272                                 ctxt->sax->error(ctxt->userData, 
1273                                      "SAX.startElement(): out of memory\n");
1274                             ctxt->errNo = XML_ERR_NO_MEMORY;
1275                             ctxt->instate = XML_PARSER_EOF;
1276                             ctxt->disableSAX = 1;
1277                             return;
1278                         }
1279
1280                         /*
1281                          * Check that the attribute is not declared in the
1282                          * serialization
1283                          */
1284                         att = NULL;
1285                         if (atts != NULL) {
1286                             i = 0;
1287                             att = atts[i];
1288                             while (att != NULL) {
1289                                 if (xmlStrEqual(att, fulln))
1290                                     break;
1291                                 i += 2;
1292                                 att = atts[i];
1293                             }
1294                         }
1295                         if (att == NULL) {
1296                             my_attribute(ctxt, fulln, attr->defaultValue,
1297                                          prefix);
1298                         }
1299                         if ((fulln != fn) && (fulln != attr->name))
1300                             xmlFree(fulln);
1301                     }
1302                 }
1303             }
1304             attr = attr->nexth;
1305         }
1306         if (internal == 1) {
1307             elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1308                                              name, prefix);
1309             internal = 0;
1310             goto process_external_subset;
1311         }
1312     }
1313 }
1314
1315 /**
1316  * startElement:
1317  * @ctx: the user data (XML parser context)
1318  * @fullname:  The element name, including namespace prefix
1319  * @atts:  An array of name/value attributes pairs, NULL terminated
1320  *
1321  * called when an opening tag has been processed.
1322  */
1323 void
1324 startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1325 {
1326     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1327     xmlNodePtr ret;
1328     xmlNodePtr parent = ctxt->node;
1329     xmlNsPtr ns;
1330     xmlChar *name;
1331     xmlChar *prefix;
1332     const xmlChar *att;
1333     const xmlChar *value;
1334     int i;
1335
1336 #ifdef DEBUG_SAX
1337     xmlGenericError(xmlGenericErrorContext,
1338             "SAX.startElement(%s)\n", fullname);
1339 #endif
1340
1341     /*
1342      * First check on validity:
1343      */
1344     if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 
1345         ((ctxt->myDoc->intSubset == NULL) ||
1346          ((ctxt->myDoc->intSubset->notations == NULL) && 
1347           (ctxt->myDoc->intSubset->elements == NULL) &&
1348           (ctxt->myDoc->intSubset->attributes == NULL) && 
1349           (ctxt->myDoc->intSubset->entities == NULL)))) {
1350         if (ctxt->vctxt.error != NULL) {
1351             ctxt->vctxt.error(ctxt->vctxt.userData,
1352               "Validation failed: no DTD found !\n");
1353         }
1354         ctxt->validate = 0;
1355         ctxt->valid = 0;
1356         ctxt->errNo = XML_ERR_NO_DTD;
1357     }
1358        
1359
1360     /*
1361      * Split the full name into a namespace prefix and the tag name
1362      */
1363     name = xmlSplitQName(ctxt, fullname, &prefix);
1364
1365
1366     /*
1367      * Note : the namespace resolution is deferred until the end of the
1368      *        attributes parsing, since local namespace can be defined as
1369      *        an attribute at this level.
1370      */
1371     ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1372     if (ret == NULL) {
1373         if (prefix != NULL)
1374             xmlFree(prefix);
1375         ctxt->errNo = XML_ERR_NO_MEMORY;
1376         ctxt->instate = XML_PARSER_EOF;
1377         ctxt->disableSAX = 1;
1378         return;
1379     }
1380     if (ctxt->myDoc->children == NULL) {
1381 #ifdef DEBUG_SAX_TREE
1382         xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1383 #endif
1384         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1385     } else if (parent == NULL) {
1386         parent = ctxt->myDoc->children;
1387     }
1388     ctxt->nodemem = -1;
1389     if (ctxt->linenumbers) {
1390         if (ctxt->input != NULL)
1391             ret->content = (void *) (long) ctxt->input->line;
1392     }
1393
1394     /*
1395      * We are parsing a new node.
1396      */
1397 #ifdef DEBUG_SAX_TREE
1398     xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1399 #endif
1400     nodePush(ctxt, ret);
1401
1402     /*
1403      * Link the child element
1404      */
1405     if (parent != NULL) {
1406         if (parent->type == XML_ELEMENT_NODE) {
1407 #ifdef DEBUG_SAX_TREE
1408             xmlGenericError(xmlGenericErrorContext,
1409                     "adding child %s to %s\n", name, parent->name);
1410 #endif
1411             xmlAddChild(parent, ret);
1412         } else {
1413 #ifdef DEBUG_SAX_TREE
1414             xmlGenericError(xmlGenericErrorContext,
1415                     "adding sibling %s to ", name);
1416             xmlDebugDumpOneNode(stderr, parent, 0);
1417 #endif
1418             xmlAddSibling(parent, ret);
1419         }
1420     }
1421
1422     /*
1423      * Insert all the defaulted attributes from the DTD especially namespaces
1424      */
1425     if ((!ctxt->html) &&
1426         ((ctxt->myDoc->intSubset != NULL) ||
1427          (ctxt->myDoc->extSubset != NULL))) {
1428         xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1429     }
1430
1431     /*
1432      * process all the attributes whose name start with "xmlns"
1433      */
1434     if (atts != NULL) {
1435         i = 0;
1436         att = atts[i++];
1437         value = atts[i++];
1438         if (!ctxt->html) {
1439             while ((att != NULL) && (value != NULL)) {
1440                 if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1441                     (att[3] == 'n') && (att[4] == 's'))
1442                     my_attribute(ctxt, att, value, prefix);
1443
1444                 att = atts[i++];
1445                 value = atts[i++];
1446             }
1447         }
1448     }
1449
1450     /*
1451      * Search the namespace, note that since the attributes have been
1452      * processed, the local namespaces are available.
1453      */
1454     ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1455     if ((ns == NULL) && (parent != NULL))
1456         ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1457     if ((prefix != NULL) && (ns == NULL)) {
1458         ns = xmlNewNs(ret, NULL, prefix);
1459         if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1460             ctxt->sax->warning(ctxt->userData, 
1461                  "Namespace prefix %s is not defined\n", prefix);
1462     }
1463
1464     /*
1465      * set the namespace node, making sure that if the default namspace
1466      * is unbound on a parent we simply kee it NULL
1467      */
1468     if ((ns != NULL) && (ns->href != NULL) &&
1469         ((ns->href[0] != 0) || (ns->prefix != NULL)))
1470         xmlSetNs(ret, ns);
1471
1472     /*
1473      * process all the other attributes
1474      */
1475     if (atts != NULL) {
1476         i = 0;
1477         att = atts[i++];
1478         value = atts[i++];
1479         if (ctxt->html) {
1480             while (att != NULL) {
1481                 attribute(ctxt, att, value);
1482                 att = atts[i++];
1483                 value = atts[i++];
1484             }
1485         } else {
1486             while ((att != NULL) && (value != NULL)) {
1487                 if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1488                     (att[3] != 'n') || (att[4] != 's'))
1489                     attribute(ctxt, att, value);
1490
1491                 /*
1492                  * Next ones
1493                  */
1494                 att = atts[i++];
1495                 value = atts[i++];
1496             }
1497         }
1498     }
1499
1500     /*
1501      * If it's the Document root, finish the DTD validation and
1502      * check the document root element for validity
1503      */
1504     if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
1505         int chk;
1506
1507         chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1508         if (chk <= 0)
1509             ctxt->valid = 0;
1510         if (chk < 0)
1511             ctxt->wellFormed = 0;
1512         ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1513         ctxt->vctxt.finishDtd = 1;
1514     }
1515
1516     if (prefix != NULL)
1517         xmlFree(prefix);
1518
1519 }
1520
1521 /**
1522  * endElement:
1523  * @ctx: the user data (XML parser context)
1524  * @name:  The element name
1525  *
1526  * called when the end of an element has been detected.
1527  */
1528 void
1529 endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1530 {
1531     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1532     xmlParserNodeInfo node_info;
1533     xmlNodePtr cur = ctxt->node;
1534
1535 #ifdef DEBUG_SAX
1536     if (name == NULL)
1537         xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
1538     else
1539         xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
1540 #endif
1541     
1542     /* Capture end position and add node */
1543     if (cur != NULL && ctxt->record_info) {
1544       node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1545       node_info.end_line = ctxt->input->line;
1546       node_info.node = cur;
1547       xmlParserAddNodeInfo(ctxt, &node_info);
1548     }
1549     ctxt->nodemem = -1;
1550
1551     if (ctxt->validate && ctxt->wellFormed &&
1552         ctxt->myDoc && ctxt->myDoc->intSubset)
1553         ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1554                                              cur);
1555
1556     
1557     /*
1558      * end of parsing of this node.
1559      */
1560 #ifdef DEBUG_SAX_TREE
1561     xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1562 #endif
1563     nodePop(ctxt);
1564 }
1565
1566 /**
1567  * reference:
1568  * @ctx: the user data (XML parser context)
1569  * @name:  The entity name
1570  *
1571  * called when an entity reference is detected. 
1572  */
1573 void
1574 reference(void *ctx, const xmlChar *name)
1575 {
1576     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1577     xmlNodePtr ret;
1578
1579 #ifdef DEBUG_SAX
1580     xmlGenericError(xmlGenericErrorContext,
1581             "SAX.reference(%s)\n", name);
1582 #endif
1583     if (name[0] == '#')
1584         ret = xmlNewCharRef(ctxt->myDoc, name);
1585     else
1586         ret = xmlNewReference(ctxt->myDoc, name);
1587 #ifdef DEBUG_SAX_TREE
1588     xmlGenericError(xmlGenericErrorContext,
1589             "add reference %s to %s \n", name, ctxt->node->name);
1590 #endif
1591     xmlAddChild(ctxt->node, ret);
1592 }
1593
1594 /**
1595  * characters:
1596  * @ctx: the user data (XML parser context)
1597  * @ch:  a xmlChar string
1598  * @len: the number of xmlChar
1599  *
1600  * receiving some chars from the parser.
1601  */
1602 void
1603 characters(void *ctx, const xmlChar *ch, int len)
1604 {
1605     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1606     xmlNodePtr lastChild;
1607
1608 #ifdef DEBUG_SAX
1609     xmlGenericError(xmlGenericErrorContext,
1610             "SAX.characters(%.30s, %d)\n", ch, len);
1611 #endif
1612     /*
1613      * Handle the data if any. If there is no child
1614      * add it as content, otherwise if the last child is text,
1615      * concatenate it, else create a new node of type text.
1616      */
1617
1618     if (ctxt->node == NULL) {
1619 #ifdef DEBUG_SAX_TREE
1620         xmlGenericError(xmlGenericErrorContext,
1621                 "add chars: ctxt->node == NULL !\n");
1622 #endif
1623         return;
1624     }
1625     lastChild = xmlGetLastChild(ctxt->node);
1626 #ifdef DEBUG_SAX_TREE
1627     xmlGenericError(xmlGenericErrorContext,
1628             "add chars to %s \n", ctxt->node->name);
1629 #endif
1630
1631     /*
1632      * Here we needed an accelerator mechanism in case of very large
1633      * elements. Use an attribute in the structure !!!
1634      */
1635     if (lastChild == NULL) {
1636         /* first node, first time */
1637         xmlNodeAddContentLen(ctxt->node, ch, len);
1638         if (ctxt->node->children != NULL) {
1639             ctxt->nodelen = len;
1640             ctxt->nodemem = len + 1;
1641         }
1642     } else {
1643         int coalesceText = (lastChild != NULL) &&
1644             (lastChild->type == XML_TEXT_NODE) &&
1645             (lastChild->name == xmlStringText);
1646         if ((coalesceText) && (ctxt->nodemem != 0)) {
1647             /*
1648              * The whole point of maintaining nodelen and nodemem,
1649              * xmlTextConcat is too costly, i.e. compute length,
1650              * reallocate a new buffer, move data, append ch. Here
1651              * We try to minimaze realloc() uses and avoid copying
1652              * and recomputing length over and over.
1653              */
1654             if (ctxt->nodelen + len >= ctxt->nodemem) {
1655                 xmlChar *newbuf;
1656                 int size;
1657
1658                 size = ctxt->nodemem + len;
1659                 size *= 2;
1660                 newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
1661                 if (newbuf == NULL) {
1662                     if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1663                         ctxt->sax->error(ctxt->userData, 
1664                              "SAX.characters(): out of memory\n");
1665                     ctxt->errNo = XML_ERR_NO_MEMORY;
1666                     ctxt->instate = XML_PARSER_EOF;
1667                     ctxt->disableSAX = 1;
1668                     return;
1669                 }
1670                 ctxt->nodemem = size;
1671                 lastChild->content = newbuf;
1672             }
1673             memcpy(&lastChild->content[ctxt->nodelen], ch, len);
1674             ctxt->nodelen += len;
1675             lastChild->content[ctxt->nodelen] = 0;
1676         } else if (coalesceText) {
1677             if (xmlTextConcat(lastChild, ch, len)) {
1678                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1679                     ctxt->sax->error(ctxt->userData, 
1680                          "SAX.characters(): out of memory\n");
1681                 ctxt->errNo = XML_ERR_NO_MEMORY;
1682                 ctxt->instate = XML_PARSER_EOF;
1683                 ctxt->disableSAX = 1;
1684             }
1685             if (ctxt->node->children != NULL) {
1686                 ctxt->nodelen = xmlStrlen(lastChild->content);
1687                 ctxt->nodemem = ctxt->nodelen + 1;
1688             }
1689         } else {
1690             /* Mixed content, first time */
1691             lastChild = xmlNewTextLen(ch, len);
1692             if (lastChild == NULL) {
1693                 if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1694                     ctxt->sax->error(ctxt->userData, 
1695                          "SAX.characters(): out of memory\n");
1696                 ctxt->errNo = XML_ERR_NO_MEMORY;
1697                 ctxt->instate = XML_PARSER_EOF;
1698                 ctxt->disableSAX = 1;
1699             } else {
1700                 xmlAddChild(ctxt->node, lastChild);
1701                 if (ctxt->node->children != NULL) {
1702                     ctxt->nodelen = len;
1703                     ctxt->nodemem = len + 1;
1704                 }
1705             }
1706         }
1707     }
1708 }
1709
1710 /**
1711  * ignorableWhitespace:
1712  * @ctx: the user data (XML parser context)
1713  * @ch:  a xmlChar string
1714  * @len: the number of xmlChar
1715  *
1716  * receiving some ignorable whitespaces from the parser.
1717  * UNUSED: by default the DOM building will use characters
1718  */
1719 void
1720 ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
1721 {
1722     /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
1723 #ifdef DEBUG_SAX
1724     xmlGenericError(xmlGenericErrorContext,
1725             "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
1726 #endif
1727 }
1728
1729 /**
1730  * processingInstruction:
1731  * @ctx: the user data (XML parser context)
1732  * @target:  the target name
1733  * @data: the PI data's
1734  *
1735  * A processing instruction has been parsed.
1736  */
1737 void
1738 processingInstruction(void *ctx, const xmlChar *target,
1739                       const xmlChar *data)
1740 {
1741     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1742     xmlNodePtr ret;
1743     xmlNodePtr parent = ctxt->node;
1744
1745 #ifdef DEBUG_SAX
1746     xmlGenericError(xmlGenericErrorContext,
1747             "SAX.processingInstruction(%s, %s)\n", target, data);
1748 #endif
1749
1750     ret = xmlNewPI(target, data);
1751     if (ret == NULL) return;
1752     parent = ctxt->node;
1753
1754     if (ctxt->inSubset == 1) {
1755         xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1756         return;
1757     } else if (ctxt->inSubset == 2) {
1758         xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1759         return;
1760     }
1761     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1762 #ifdef DEBUG_SAX_TREE
1763             xmlGenericError(xmlGenericErrorContext,
1764                     "Setting PI %s as root\n", target);
1765 #endif
1766         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1767         return;
1768     }
1769     if (parent->type == XML_ELEMENT_NODE) {
1770 #ifdef DEBUG_SAX_TREE
1771         xmlGenericError(xmlGenericErrorContext,
1772                 "adding PI %s child to %s\n", target, parent->name);
1773 #endif
1774         xmlAddChild(parent, ret);
1775     } else {
1776 #ifdef DEBUG_SAX_TREE
1777         xmlGenericError(xmlGenericErrorContext,
1778                 "adding PI %s sibling to ", target);
1779         xmlDebugDumpOneNode(stderr, parent, 0);
1780 #endif
1781         xmlAddSibling(parent, ret);
1782     }
1783 }
1784
1785 /**
1786  * globalNamespace:
1787  * @ctx: the user data (XML parser context)
1788  * @href:  the namespace associated URN
1789  * @prefix: the namespace prefix
1790  *
1791  * An old global namespace has been parsed.
1792  */
1793 void
1794 globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
1795 {
1796     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1797 #ifdef DEBUG_SAX
1798     xmlGenericError(xmlGenericErrorContext,
1799             "SAX.globalNamespace(%s, %s)\n", href, prefix);
1800 #endif
1801     xmlNewGlobalNs(ctxt->myDoc, href, prefix);
1802 }
1803
1804 /**
1805  * setNamespace:
1806  * @ctx: the user data (XML parser context)
1807  * @name:  the namespace prefix
1808  *
1809  * Set the current element namespace.
1810  */
1811
1812 void
1813 setNamespace(void *ctx, const xmlChar *name)
1814 {
1815     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1816     xmlNsPtr ns;
1817     xmlNodePtr parent;
1818
1819 #ifdef DEBUG_SAX
1820     xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
1821 #endif
1822     ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
1823     if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
1824         if (ctxt->nodeNr >= 2) {
1825             parent = ctxt->nodeTab[ctxt->nodeNr - 2];
1826             if (parent != NULL)
1827                 ns = xmlSearchNs(ctxt->myDoc, parent, name);
1828         }
1829     }
1830     xmlSetNs(ctxt->node, ns);
1831 }
1832
1833 /**
1834  * getNamespace:
1835  * @ctx: the user data (XML parser context)
1836  *
1837  * Get the current element namespace.
1838  *
1839  * Returns the xmlNsPtr or NULL if none
1840  */
1841
1842 xmlNsPtr
1843 getNamespace(void *ctx)
1844 {
1845     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1846     xmlNsPtr ret;
1847
1848 #ifdef DEBUG_SAX
1849     xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
1850 #endif
1851     ret = ctxt->node->ns;
1852     return(ret);
1853 }
1854
1855 /**
1856  * checkNamespace:
1857  * @ctx: the user data (XML parser context)
1858  * @namespace: the namespace to check against
1859  *
1860  * Check that the current element namespace is the same as the
1861  * one read upon parsing.
1862  *
1863  * Returns 1 if true 0 otherwise
1864  */
1865
1866 int
1867 checkNamespace(void *ctx, xmlChar *namespace)
1868 {
1869     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1870     xmlNodePtr cur = ctxt->node;
1871
1872 #ifdef DEBUG_SAX
1873     xmlGenericError(xmlGenericErrorContext,
1874             "SAX.checkNamespace(%s)\n", namespace);
1875 #endif
1876
1877     /*
1878      * Check that the Name in the ETag is the same as in the STag.
1879      */
1880     if (namespace == NULL) {
1881         if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1882             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1883                 ctxt->sax->error(ctxt, 
1884                  "End tags for %s don't hold the namespace %s\n",
1885                                  cur->name, cur->ns->prefix);
1886             ctxt->wellFormed = 0;
1887         }
1888     } else {
1889         if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
1890             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1891                 ctxt->sax->error(ctxt, 
1892                  "End tags %s holds a prefix %s not used by the open tag\n",
1893                                  cur->name, namespace);
1894             ctxt->wellFormed = 0;
1895         } else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
1896             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1897                 ctxt->sax->error(ctxt, 
1898     "Start and End tags for %s don't use the same namespaces: %s and %s\n",
1899                                  cur->name, cur->ns->prefix, namespace);
1900             ctxt->wellFormed = 0;
1901         } else
1902             return(1);
1903     }
1904     return(0);
1905 }
1906
1907 /**
1908  * namespaceDecl:
1909  * @ctx: the user data (XML parser context)
1910  * @href:  the namespace associated URN
1911  * @prefix: the namespace prefix
1912  *
1913  * A namespace has been parsed.
1914  */
1915 void
1916 namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
1917 {
1918     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1919 #ifdef DEBUG_SAX
1920     if (prefix == NULL)
1921         xmlGenericError(xmlGenericErrorContext,
1922                 "SAX.namespaceDecl(%s, NULL)\n", href);
1923     else
1924         xmlGenericError(xmlGenericErrorContext,
1925                 "SAX.namespaceDecl(%s, %s)\n", href, prefix);
1926 #endif
1927     xmlNewNs(ctxt->node, href, prefix);
1928 }
1929
1930 /**
1931  * comment:
1932  * @ctx: the user data (XML parser context)
1933  * @value:  the comment content
1934  *
1935  * A comment has been parsed.
1936  */
1937 void
1938 comment(void *ctx, const xmlChar *value)
1939 {
1940     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1941     xmlNodePtr ret;
1942     xmlNodePtr parent = ctxt->node;
1943
1944 #ifdef DEBUG_SAX
1945     xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
1946 #endif
1947     ret = xmlNewDocComment(ctxt->myDoc, value);
1948     if (ret == NULL) return;
1949
1950     if (ctxt->inSubset == 1) {
1951         xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
1952         return;
1953     } else if (ctxt->inSubset == 2) {
1954         xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
1955         return;
1956     }
1957     if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
1958 #ifdef DEBUG_SAX_TREE
1959             xmlGenericError(xmlGenericErrorContext,
1960                     "Setting comment as root\n");
1961 #endif
1962         xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1963         return;
1964     }
1965     if (parent->type == XML_ELEMENT_NODE) {
1966 #ifdef DEBUG_SAX_TREE
1967         xmlGenericError(xmlGenericErrorContext,
1968                 "adding comment child to %s\n", parent->name);
1969 #endif
1970         xmlAddChild(parent, ret);
1971     } else {
1972 #ifdef DEBUG_SAX_TREE
1973         xmlGenericError(xmlGenericErrorContext,
1974                 "adding comment sibling to ");
1975         xmlDebugDumpOneNode(stderr, parent, 0);
1976 #endif
1977         xmlAddSibling(parent, ret);
1978     }
1979 }
1980
1981 /**
1982  * cdataBlock:
1983  * @ctx: the user data (XML parser context)
1984  * @value:  The pcdata content
1985  * @len:  the block length
1986  *
1987  * called when a pcdata block has been parsed
1988  */
1989 void
1990 cdataBlock(void *ctx, const xmlChar *value, int len)
1991 {
1992     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1993     xmlNodePtr ret, lastChild;
1994
1995 #ifdef DEBUG_SAX
1996     xmlGenericError(xmlGenericErrorContext,
1997             "SAX.pcdata(%.10s, %d)\n", value, len);
1998 #endif
1999     lastChild = xmlGetLastChild(ctxt->node);
2000 #ifdef DEBUG_SAX_TREE
2001     xmlGenericError(xmlGenericErrorContext,
2002             "add chars to %s \n", ctxt->node->name);
2003 #endif
2004     if ((lastChild != NULL) &&
2005         (lastChild->type == XML_CDATA_SECTION_NODE)) {
2006         xmlTextConcat(lastChild, value, len);
2007     } else {
2008         ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2009         xmlAddChild(ctxt->node, ret);
2010     }
2011 }
2012
2013 /**
2014  * initxmlDefaultSAXHandler:
2015  * @hdlr:  the SAX handler
2016  * @warning:  flag if non-zero sets the handler warning procedure
2017  *
2018  * Initialize the default XML SAX handler
2019  */
2020 void
2021 initxmlDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2022 {
2023     if(hdlr->initialized == 1)
2024         return;
2025
2026     hdlr->internalSubset = internalSubset;
2027     hdlr->externalSubset = externalSubset;
2028     hdlr->isStandalone = isStandalone;
2029     hdlr->hasInternalSubset = hasInternalSubset;
2030     hdlr->hasExternalSubset = hasExternalSubset;
2031     hdlr->resolveEntity = resolveEntity;
2032     hdlr->getEntity = getEntity;
2033     hdlr->getParameterEntity = getParameterEntity;
2034     hdlr->entityDecl = entityDecl;
2035     hdlr->attributeDecl = attributeDecl;
2036     hdlr->elementDecl = elementDecl;
2037     hdlr->notationDecl = notationDecl;
2038     hdlr->unparsedEntityDecl = unparsedEntityDecl;
2039     hdlr->setDocumentLocator = setDocumentLocator;
2040     hdlr->startDocument = startDocument;
2041     hdlr->endDocument = endDocument;
2042     hdlr->startElement = startElement;
2043     hdlr->endElement = endElement;
2044     hdlr->reference = reference;
2045     hdlr->characters = characters;
2046     hdlr->cdataBlock = cdataBlock;
2047     hdlr->ignorableWhitespace = characters;
2048     hdlr->processingInstruction = processingInstruction;
2049     hdlr->comment = comment;
2050     /* if (xmlGetWarningsDefaultValue == 0) */
2051     if (warning == 0)
2052         hdlr->warning = NULL;
2053     else
2054         hdlr->warning = xmlParserWarning;
2055     hdlr->error = xmlParserError;
2056     hdlr->fatalError = xmlParserError;
2057
2058     hdlr->initialized = 1;
2059 }
2060
2061 /**
2062  * xmlDefaultSAXHandlerInit:
2063  *
2064  * Initialize the default SAX handler
2065  */
2066 void
2067 xmlDefaultSAXHandlerInit(void)
2068 {
2069     initxmlDefaultSAXHandler(&xmlDefaultSAXHandler, xmlGetWarningsDefaultValue);
2070 }
2071
2072 #ifdef LIBXML_HTML_ENABLED
2073
2074 /**
2075  * inithtmlDefaultSAXHandler:
2076  * @hdlr:  the SAX handler
2077  *
2078  * Initialize the default HTML SAX handler
2079  */
2080 void
2081 inithtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2082 {
2083     if(hdlr->initialized == 1)
2084         return;
2085
2086     hdlr->internalSubset = internalSubset;
2087     hdlr->externalSubset = NULL;
2088     hdlr->isStandalone = NULL;
2089     hdlr->hasInternalSubset = NULL;
2090     hdlr->hasExternalSubset = NULL;
2091     hdlr->resolveEntity = NULL;
2092     hdlr->getEntity = getEntity;
2093     hdlr->getParameterEntity = NULL;
2094     hdlr->entityDecl = NULL;
2095     hdlr->attributeDecl = NULL;
2096     hdlr->elementDecl = NULL;
2097     hdlr->notationDecl = NULL;
2098     hdlr->unparsedEntityDecl = NULL;
2099     hdlr->setDocumentLocator = setDocumentLocator;
2100     hdlr->startDocument = startDocument;
2101     hdlr->endDocument = endDocument;
2102     hdlr->startElement = startElement;
2103     hdlr->endElement = endElement;
2104     hdlr->reference = NULL;
2105     hdlr->characters = characters;
2106     hdlr->cdataBlock = cdataBlock;
2107     hdlr->ignorableWhitespace = ignorableWhitespace;
2108     hdlr->processingInstruction = NULL;
2109     hdlr->comment = comment;
2110     hdlr->warning = xmlParserWarning;
2111     hdlr->error = xmlParserError;
2112     hdlr->fatalError = xmlParserError;
2113
2114     hdlr->initialized = 1;
2115 }
2116
2117 /**
2118  * htmlDefaultSAXHandlerInit:
2119  *
2120  * Initialize the default SAX handler
2121  */
2122 void
2123 htmlDefaultSAXHandlerInit(void)
2124 {
2125         inithtmlDefaultSAXHandler(&htmlDefaultSAXHandler);
2126 }
2127
2128 #endif /* LIBXML_HTML_ENABLED */
2129
2130 #ifdef LIBXML_DOCB_ENABLED
2131
2132 /**
2133  * initdocbDefaultSAXHandler:
2134  * @hdlr:  the SAX handler
2135  *
2136  * Initialize the default DocBook SAX handler
2137  */
2138 void
2139 initdocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2140 {
2141     if(hdlr->initialized == 1)
2142         return;
2143
2144     hdlr->internalSubset = internalSubset;
2145     hdlr->externalSubset = NULL;
2146     hdlr->isStandalone = isStandalone;
2147     hdlr->hasInternalSubset = hasInternalSubset;
2148     hdlr->hasExternalSubset = hasExternalSubset;
2149     hdlr->resolveEntity = resolveEntity;
2150     hdlr->getEntity = getEntity;
2151     hdlr->getParameterEntity = NULL;
2152     hdlr->entityDecl = entityDecl;
2153     hdlr->attributeDecl = NULL;
2154     hdlr->elementDecl = NULL;
2155     hdlr->notationDecl = NULL;
2156     hdlr->unparsedEntityDecl = NULL;
2157     hdlr->setDocumentLocator = setDocumentLocator;
2158     hdlr->startDocument = startDocument;
2159     hdlr->endDocument = endDocument;
2160     hdlr->startElement = startElement;
2161     hdlr->endElement = endElement;
2162     hdlr->reference = reference;
2163     hdlr->characters = characters;
2164     hdlr->cdataBlock = NULL;
2165     hdlr->ignorableWhitespace = ignorableWhitespace;
2166     hdlr->processingInstruction = NULL;
2167     hdlr->comment = comment;
2168     hdlr->warning = xmlParserWarning;
2169     hdlr->error = xmlParserError;
2170     hdlr->fatalError = xmlParserError;
2171
2172     hdlr->initialized = 1;
2173 }
2174
2175 /**
2176  * docbDefaultSAXHandlerInit:
2177  *
2178  * Initialize the default SAX handler
2179  */
2180 void
2181 docbDefaultSAXHandlerInit(void)
2182 {
2183     initdocbDefaultSAXHandler(&docbDefaultSAXHandler);
2184 }
2185
2186 #endif /* LIBXML_DOCB_ENABLED */