source: trunk/third/libxml2/SAX.c @ 18536

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