source: trunk/third/libxml2/SAX2.c @ 21532

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