SAX2.c revision 06c93b75095ddca6ba80e45dd381bb69cd04b9f6
198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor/*
298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * SAX2.c : Default SAX2 handler to build a tree.
398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor *
498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * See Copyright for the status of this software.
598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor *
698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * Daniel Veillard <daniel@veillard.com>
798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor */
898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor
998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor
1098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#define IN_LIBXML
1198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include "libxml.h"
1298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <stdlib.h>
1398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <string.h>
14a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar#include <limits.h>
156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include <libxml/xmlmemory.h>
16677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor#include <libxml/tree.h>
17188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor#include <libxml/parser.h>
18ae0cdff0b83e59c7fe769baf171d1ba194ad8b88Benjamin Kramer#include <libxml/parserInternals.h>
1998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <libxml/valid.h>
208229d22e6449851b89361bf2f41804557328be63Rafael Espindola#include <libxml/entities.h>
2198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <libxml/xmlerror.h>
22c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines#include <libxml/debugXML.h>
2398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <libxml/xmlIO.h>
242492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#include <libxml/SAX.h>
252492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#include <libxml/uri.h>
262492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#include <libxml/valid.h>
272492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor#include <libxml/HTMLtree.h>
2898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#include <libxml/globals.h>
2998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor
3098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor/* Define SIZE_T_MAX unless defined through <limits.h>. */
311a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor#ifndef SIZE_T_MAX
32ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor# define SIZE_T_MAX     ((size_t)-1)
33ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor#endif /* !SIZE_T_MAX */
34c544ba09695e300f31355af342258bd57619e737Douglas Gregor
35c544ba09695e300f31355af342258bd57619e737Douglas Gregor/* #define DEBUG_SAX2 */
36c544ba09695e300f31355af342258bd57619e737Douglas Gregor/* #define DEBUG_SAX2_TREE */
376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
38c544ba09695e300f31355af342258bd57619e737Douglas Gregor/**
39c544ba09695e300f31355af342258bd57619e737Douglas Gregor * TODO:
40c544ba09695e300f31355af342258bd57619e737Douglas Gregor *
41c544ba09695e300f31355af342258bd57619e737Douglas Gregor * macro to flag unimplemented blocks
42c544ba09695e300f31355af342258bd57619e737Douglas Gregor * XML_CATALOG_PREFER user env to select between system/public prefered
43c544ba09695e300f31355af342258bd57619e737Douglas Gregor * option. C.f. Richard Tobin <richard@cogsci.ed.ac.uk>
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines *> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
45c544ba09695e300f31355af342258bd57619e737Douglas Gregor *> values "system" and "public".  I have made the default be "system" to
46c544ba09695e300f31355af342258bd57619e737Douglas Gregor *> match yours.
4798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor */
4898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor#define TODO 								\
49176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    xmlGenericError(xmlGenericErrorContext,				\
50176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	    "Unimplemented block at %s:%d\n",				\
51ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor            __FILE__, __LINE__);
52ea14a8799f2a6d139491483151cee4341ef1a73eDouglas Gregor
53176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines/*
5498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * xmlSAX2ErrMemory:
5598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * @ctxt:  an XML validation parser context
56677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * @msg:   a string to accompany the error message
5787e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor */
5887e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregorstatic void
59677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas GregorxmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
60677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    if (ctxt != NULL) {
61176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar	    ctxt->sax->error(ctxt->userData, "%s: out of memory\n", msg);
63677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->errNo = XML_ERR_NO_MEMORY;
64677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->instate = XML_PARSER_EOF;
656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	ctxt->disableSAX = 1;
66677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    }
67677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor}
68677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
69677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor/**
700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * xmlValidError:
710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * @ctxt:  an XML validation parser context
720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * @error:  the error number
730e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * @msg:  the error message
740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * @str1:  extra data
750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines * @str2:  extra data
760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines *
77edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman * Handle a validation error
78edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman */
79677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregorstatic void
80edadb9a879e14b3732461316a83ffc4c3482ad19Eli FriedmanxmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
81677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor            const char *msg, const char *str1, const char *str2)
8298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor{
83edadb9a879e14b3732461316a83ffc4c3482ad19Eli Friedman    xmlStructuredErrorFunc schannel = NULL;
84677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
8598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
86677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor        (ctxt->instate == XML_PARSER_EOF))
87677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	return;
881a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor    if (ctxt != NULL) {
8998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	ctxt->errNo = error;
9098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
9198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	    schannel = ctxt->sax->serror;
92057df20b3107cef764052d271c89b8591b98b3ceDouglas Gregor	__xmlRaiseError(schannel,
93cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor			ctxt->vctxt.error, ctxt->vctxt.userData,
9498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor			ctxt, NULL, XML_FROM_DTD, error,
95d64c26f6676eef69d1713f353ca8a3c2fe963f17Argyrios Kyrtzidis			XML_ERR_ERROR, NULL, 0, (const char *) str1,
9687e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor			(const char *) str2, NULL, 0, 0,
9798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor			msg, (const char *) str1, (const char *) str2);
98a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar	ctxt->valid = 0;
99a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    } else {
100b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar	__xmlRaiseError(schannel,
101b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar			NULL, NULL,
10298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor			ctxt, NULL, XML_FROM_DTD, error,
10398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor			XML_ERR_ERROR, NULL, 0, (const char *) str1,
10487e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor			(const char *) str2, NULL, 0, 0,
105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines			msg, (const char *) str1, (const char *) str2);
106176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    }
107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/**
110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines * xmlFatalErrMsg:
111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines * @ctxt:  an XML parser context
112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines * @error:  the error number
113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines * @msg:  the error message
114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines * @str1:  an error string
11598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * @str2:  an error string
116176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *
11798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * Handle a fatal parser error, i.e. violating Well-Formedness constraints
118176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines */
11998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorstatic void
12098339b96a8089a6da715487e432c5abfca0ca0dfDouglas GregorxmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
121176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               const char *msg, const xmlChar *str1, const xmlChar *str2)
122176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines{
12398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
124176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        (ctxt->instate == XML_PARSER_EOF))
125c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines	return;
126c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (ctxt != NULL)
127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines	ctxt->errNo = error;
128c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
129c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                    XML_ERR_FATAL, NULL, 0,
130176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines		    (const char *) str1, (const char *) str2,
131176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines		    NULL, 0, 0, msg, str1, str2);
132176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (ctxt != NULL) {
133c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines	ctxt->wellFormed = 0;
134176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	ctxt->valid = 0;
135176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	if (ctxt->recovery == 0)
136176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	    ctxt->disableSAX = 1;
137677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    }
138176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
139176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
140176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines/**
14198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor * xmlWarnMsg:
142a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * @ctxt:  an XML parser context
143a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * @error:  the error number
144a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * @msg:  the error message
145677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * @str1:  an error string
146176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * @str2:  an error string
147176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *
148176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * Handle a parser warning
149176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines */
150176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic void
151176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesxmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
152176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines               const char *msg, const xmlChar *str1)
153176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines{
154176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
155176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        (ctxt->instate == XML_PARSER_EOF))
156176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	return;
157176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    if (ctxt != NULL)
158176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines	ctxt->errNo = error;
159176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
160176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines                    XML_ERR_WARNING, NULL, 0,
161176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines		    (const char *) str1, NULL,
162b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar		    NULL, 0, 0, msg, str1);
163176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
164a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
165a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar/**
166b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar * xmlNsErrMsg:
167b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar * @ctxt:  an XML parser context
168b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar * @error:  the error number
169b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar * @msg:  the error message
170176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * @str1:  an error string
171176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * @str2:  an error string
172176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *
173176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * Handle a namespace error
174176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines */
17598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorstatic void
17698339b96a8089a6da715487e432c5abfca0ca0dfDouglas GregorxmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
17798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor            const char *msg, const xmlChar *str1, const xmlChar *str2)
17898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor{
17998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
18087e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor        (ctxt->instate == XML_PARSER_EOF))
18187e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor	return;
18287e2cfcec7231daaa3f367dc32df74b411251e46Douglas Gregor    if (ctxt != NULL)
18398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	ctxt->errNo = error;
18498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
185677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor                    XML_ERR_ERROR, NULL, 0,
186677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor		    (const char *) str1, (const char *) str2,
187677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor		    NULL, 0, 0, msg, str1, str2);
18898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor}
18998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor
190c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines/**
191c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * xmlNsWarnMsg:
192c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * @ctxt:  an XML parser context
193c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * @error:  the error number
1947cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor * @msg:  the error message
1957cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor * @str1:  an error string
1967cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor *
197a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Handle a namespace warning
198a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar */
199a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainarstatic void
2007cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas GregorxmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
2017cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor             const char *msg, const xmlChar *str1, const xmlChar *str2)
2027cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor{
203b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
204b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar        (ctxt->instate == XML_PARSER_EOF))
205b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar	return;
2067cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor    if (ctxt != NULL)
2077cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor	ctxt->errNo = error;
208b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
2097cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor                    XML_ERR_WARNING, NULL, 0,
210b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar		    (const char *) str1, (const char *) str2,
211b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar		    NULL, 0, 0, msg, str1, str2);
2127cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor}
213a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
214a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar/**
215a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * xmlSAX2GetPublicId:
216a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * @ctx: the user data (XML parser context)
217a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar *
218a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
219a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar *
220a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Returns a xmlChar *
221a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar */
2227cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregorconst xmlChar *
2237cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas GregorxmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
2247cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor{
225677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
226677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor    return(NULL);
2276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
228677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor
2296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/**
230677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * xmlSAX2GetSystemId:
231677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * @ctx: the user data (XML parser context)
232c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines *
233c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * Provides the system ID, basically URL or filename e.g.
234c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * http://www.sgmlsource.com/dtds/memo.dtd
235c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines *
236c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines * Returns a xmlChar *
237c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines */
238c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hinesconst xmlChar *
2397cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas GregorxmlSAX2GetSystemId(void *ctx)
2407cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor{
2417cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2427cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor    if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
2437cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor    return((const xmlChar *) ctxt->input->filename);
2447cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor}
2457cdd28162dc7ade4b14bf237e87b4bbc17b2f023Douglas Gregor
246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines/**
247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * xmlSAX2GetLineNumber:
248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * @ctx: the user data (XML parser context)
249176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *
250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * Provide the line number of the current parsing point.
251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines *
252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines * Returns an int
25398339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor */
25498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorint
255d3cf5fba332fc77f7e72ef58077822606718671dDouglas GregorxmlSAX2GetLineNumber(void *ctx)
256d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor{
257d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
258d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
259d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    return(ctxt->input->line);
2606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
261d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor
262d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor/**
263d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor * xmlSAX2GetColumnNumber:
264d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor * @ctx: the user data (XML parser context)
265d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor *
266d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor * Provide the column number of the current parsing point.
267d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor *
268d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor * Returns an int
2696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines */
270d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregorint
271d3cf5fba332fc77f7e72ef58077822606718671dDouglas GregorxmlSAX2GetColumnNumber(void *ctx)
272d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor{
273d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
274188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor    if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
275188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor    return(ctxt->input->col);
276fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor}
277fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor
278fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor/**
279677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * xmlSAX2IsStandalone:
280fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor * @ctx: the user data (XML parser context)
281fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor *
282fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor * Is this document tagged standalone ?
283fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor *
284fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor * Returns 1 if true
285fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor */
286fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregorint
287fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas GregorxmlSAX2IsStandalone(void *ctx)
288fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor{
289fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
290fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor    if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
291fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor    return(ctxt->myDoc->standalone == 1);
292fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor}
293fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor
294fa69fc19121da3fc5673ccc00d4e8afa5b540a4fDouglas Gregor/**
295188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * xmlSAX2HasInternalSubset:
296188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * @ctx: the user data (XML parser context)
297a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar *
298a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Does this document has an internal subset
299a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar *
300a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Returns 1 if true
30198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor */
30298339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregorint
30398339b96a8089a6da715487e432c5abfca0ca0dfDouglas GregorxmlSAX2HasInternalSubset(void *ctx)
30498339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor{
305d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
30698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
30798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor    return(ctxt->myDoc->intSubset != NULL);
308a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
309a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
310188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor/**
311d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * xmlSAX2HasExternalSubset:
312d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * @ctx: the user data (XML parser context)
313d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor *
314d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * Does this document has an external subset
315d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor *
316d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * Returns 1 if true
317d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor */
318d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregorint
319d07865b42dcb32154c75134fded51b38cc55a0c4Douglas GregorxmlSAX2HasExternalSubset(void *ctx)
320d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor{
321d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
322a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
323a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    return(ctxt->myDoc->extSubset != NULL);
324a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar}
325a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar
326a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar/**
327d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * xmlSAX2InternalSubset:
328cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor * @ctx:  the user data (XML parser context)
329d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * @name:  the root element name
330d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * @ExternalID:  the external ID
331d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor * @SystemID:  the SYSTEM ID (e.g. filename or URL)
332a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar *
333a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar * Callback on internal subset declaration.
334d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor */
335d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregorvoid
336d07865b42dcb32154c75134fded51b38cc55a0c4Douglas GregorxmlSAX2InternalSubset(void *ctx, const xmlChar *name,
337d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	       const xmlChar *ExternalID, const xmlChar *SystemID)
338a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar{
339a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
340d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    xmlDtdPtr dtd;
341d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    if (ctx == NULL) return;
342d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor#ifdef DEBUG_SAX
343d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    xmlGenericError(xmlGenericErrorContext,
344d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
345d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor            name, ExternalID, SystemID);
346d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor#endif
347d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor
348d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    if (ctxt->myDoc == NULL)
349d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	return;
350d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    dtd = xmlGetIntSubset(ctxt->myDoc);
351d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    if (dtd != NULL) {
352188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor	if (ctxt->html)
353d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	    return;
3546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	xmlUnlinkNode((xmlNodePtr) dtd);
35598339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	xmlFreeDtd(dtd);
356cc71dbee441e97285e86bff48eecfbeab82de7ceDouglas Gregor	ctxt->myDoc->intSubset = NULL;
357d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    }
358d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    ctxt->myDoc->intSubset =
359d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
360188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor    if (ctxt->myDoc->intSubset == NULL)
361188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor        xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
362188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor}
363188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor
364188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor/**
365188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * xmlSAX2ExternalSubset:
366188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * @ctx: the user data (XML parser context)
367677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor * @name:  the root element name
368d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor * @ExternalID:  the external ID
369188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * @SystemID:  the SYSTEM ID (e.g. filename or URL)
370188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor *
371188bdcd1aaf5e9f457cec6851707d7dc3e7bbb15Douglas Gregor * Callback on external subset declaration.
372d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor */
373d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregorvoid
374d07865b42dcb32154c75134fded51b38cc55a0c4Douglas GregorxmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
375d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	       const xmlChar *ExternalID, const xmlChar *SystemID)
37698339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor{
377d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
378d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    if (ctx == NULL) return;
379d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor#ifdef DEBUG_SAX
380d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor    xmlGenericError(xmlGenericErrorContext,
381a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
382d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor            name, ExternalID, SystemID);
383d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor#endif
384d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor    if (((ExternalID != NULL) || (SystemID != NULL)) &&
385d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor        (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
386d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	 (ctxt->wellFormed && ctxt->myDoc))) {
387d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	/*
388d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	 * Try to fetch and parse the external subset.
389d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	 */
390d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	xmlParserInputPtr oldinput;
391d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	int oldinputNr;
392d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	int oldinputMax;
393d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	xmlParserInputPtr *oldinputTab;
394d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	xmlParserInputPtr input = NULL;
395d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	xmlCharEncoding enc;
396d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	int oldcharset;
397d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor
39898339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	/*
39998339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	 * Ask the Entity resolver to load the damn thing
400d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	 */
401d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
402d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	    input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
403d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	                                        SystemID);
404d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	if (input == NULL) {
405344472ebeded2fca2ed5013b9e87f81d09bfa908Robert Wilhelm	    return;
406d07865b42dcb32154c75134fded51b38cc55a0c4Douglas Gregor	}
40798339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor
408d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
409d3cf5fba332fc77f7e72ef58077822606718671dDouglas Gregor
41098339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	/*
41198339b96a8089a6da715487e432c5abfca0ca0dfDouglas Gregor	 * make sure we won't destroy the main document context
412677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	 */
413677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	oldinput = ctxt->input;
414677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	oldinputNr = ctxt->inputNr;
415677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	oldinputMax = ctxt->inputMax;
4166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	oldinputTab = ctxt->inputTab;
4176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	oldcharset = ctxt->charset;
4186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
419677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->inputTab = (xmlParserInputPtr *)
420677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
421677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	if (ctxt->inputTab == NULL) {
422677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	    xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
423677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	    ctxt->input = oldinput;
424677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	    ctxt->inputNr = oldinputNr;
4256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	    ctxt->inputMax = oldinputMax;
4266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	    ctxt->inputTab = oldinputTab;
4276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	    ctxt->charset = oldcharset;
428677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	    return;
429677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	}
430677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->inputNr = 0;
431677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->inputMax = 5;
432677e15ffee2ecc9c1c8f46fd77cab4b5afb59640Douglas Gregor	ctxt->input = NULL;
4332492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	xmlPushInput(ctxt, input);
4342492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4352492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	/*
4362492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 * On the fly encoding conversion if needed
4371a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor	 */
4381a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor	if (ctxt->input->length >= 4) {
4392492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
4402492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	    xmlSwitchEncoding(ctxt, enc);
4412492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	}
4422492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4432492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	if (input->filename == NULL)
4442492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	    input->filename = (char *) xmlCanonicPath(SystemID);
4452492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	input->line = 1;
4462492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	input->col = 1;
4472492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	input->base = ctxt->input->cur;
4482492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	input->cur = ctxt->input->cur;
4492492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	input->free = NULL;
4502492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4512492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	/*
4522492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 * let's parse that entity knowing it's an external subset.
4532492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 */
4542492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	xmlParseExternalSubset(ctxt, ExternalID, SystemID);
4552492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4562492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor        /*
4572492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 * Free up the external entities
4582492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 */
4592492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4602492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	while (ctxt->inputNr > 1)
4612492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	    xmlPopInput(ctxt);
4622492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	xmlFreeInputStream(ctxt->input);
4632492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor        xmlFree(ctxt->inputTab);
4642492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
4652492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	/*
4662492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	 * Restore the parsing context of the main entity
4671a4761edca58c6b559de825b9abfb66f7f1ba94aDouglas Gregor	 */
4686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines	ctxt->input = oldinput;
4692492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	ctxt->inputNr = oldinputNr;
4702492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	ctxt->inputMax = oldinputMax;
4712492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	ctxt->inputTab = oldinputTab;
4722492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	ctxt->charset = oldcharset;
4732492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor	/* ctxt->wellFormed = oldwellFormed; */
4742492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor    }
4752492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor}
4762492c89882b5c5ce03afb4704fee67b7eff8f5eeDouglas Gregor
477/**
478 * xmlSAX2ResolveEntity:
479 * @ctx: the user data (XML parser context)
480 * @publicId: The public ID of the entity
481 * @systemId: The system ID of the entity
482 *
483 * The entity loader, to control the loading of external entities,
484 * the application can either:
485 *    - override this xmlSAX2ResolveEntity() callback in the SAX block
486 *    - or better use the xmlSetExternalEntityLoader() function to
487 *      set up it's own entity resolution routine
488 *
489 * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
490 */
491xmlParserInputPtr
492xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
493{
494    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
495    xmlParserInputPtr ret;
496    xmlChar *URI;
497    const char *base = NULL;
498
499    if (ctx == NULL) return(NULL);
500    if (ctxt->input != NULL)
501	base = ctxt->input->filename;
502    if (base == NULL)
503	base = ctxt->directory;
504
505    URI = xmlBuildURI(systemId, (const xmlChar *) base);
506
507#ifdef DEBUG_SAX
508    xmlGenericError(xmlGenericErrorContext,
509	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
510#endif
511
512    ret = xmlLoadExternalEntity((const char *) URI,
513				(const char *) publicId, ctxt);
514    if (URI != NULL)
515	xmlFree(URI);
516    return(ret);
517}
518
519/**
520 * xmlSAX2GetEntity:
521 * @ctx: the user data (XML parser context)
522 * @name: The entity name
523 *
524 * Get an entity by name
525 *
526 * Returns the xmlEntityPtr if found.
527 */
528xmlEntityPtr
529xmlSAX2GetEntity(void *ctx, const xmlChar *name)
530{
531    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
532    xmlEntityPtr ret = NULL;
533
534    if (ctx == NULL) return(NULL);
535#ifdef DEBUG_SAX
536    xmlGenericError(xmlGenericErrorContext,
537	    "SAX.xmlSAX2GetEntity(%s)\n", name);
538#endif
539
540    if (ctxt->inSubset == 0) {
541	ret = xmlGetPredefinedEntity(name);
542	if (ret != NULL)
543	    return(ret);
544    }
545    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
546	if (ctxt->inSubset == 2) {
547	    ctxt->myDoc->standalone = 0;
548	    ret = xmlGetDocEntity(ctxt->myDoc, name);
549	    ctxt->myDoc->standalone = 1;
550	} else {
551	    ret = xmlGetDocEntity(ctxt->myDoc, name);
552	    if (ret == NULL) {
553		ctxt->myDoc->standalone = 0;
554		ret = xmlGetDocEntity(ctxt->myDoc, name);
555		if (ret != NULL) {
556		    xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
557	 "Entity(%s) document marked standalone but requires external subset\n",
558				   name, NULL);
559		}
560		ctxt->myDoc->standalone = 1;
561	    }
562	}
563    } else {
564	ret = xmlGetDocEntity(ctxt->myDoc, name);
565    }
566    if ((ret != NULL) &&
567	((ctxt->validate) || (ctxt->replaceEntities)) &&
568	(ret->children == NULL) &&
569	(ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
570	int val;
571
572	/*
573	 * for validation purposes we really need to fetch and
574	 * parse the external entity
575	 */
576	xmlNodePtr children;
577
578        val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
579		                         ret->ExternalID, &children);
580	if (val == 0) {
581	    xmlAddChildList((xmlNodePtr) ret, children);
582	} else {
583	    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
584		           "Failure to process entity %s\n", name, NULL);
585	    ctxt->validate = 0;
586	    return(NULL);
587	}
588	ret->owner = 1;
589	if (ret->checked == 0)
590	    ret->checked = 1;
591    }
592    return(ret);
593}
594
595/**
596 * xmlSAX2GetParameterEntity:
597 * @ctx: the user data (XML parser context)
598 * @name: The entity name
599 *
600 * Get a parameter entity by name
601 *
602 * Returns the xmlEntityPtr if found.
603 */
604xmlEntityPtr
605xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
606{
607    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
608    xmlEntityPtr ret;
609
610    if (ctx == NULL) return(NULL);
611#ifdef DEBUG_SAX
612    xmlGenericError(xmlGenericErrorContext,
613	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
614#endif
615
616    ret = xmlGetParameterEntity(ctxt->myDoc, name);
617    return(ret);
618}
619
620
621/**
622 * xmlSAX2EntityDecl:
623 * @ctx: the user data (XML parser context)
624 * @name:  the entity name
625 * @type:  the entity type
626 * @publicId: The public ID of the entity
627 * @systemId: The system ID of the entity
628 * @content: the entity value (without processing).
629 *
630 * An entity definition has been parsed
631 */
632void
633xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
634          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
635{
636    xmlEntityPtr ent;
637    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
638
639    if (ctx == NULL) return;
640#ifdef DEBUG_SAX
641    xmlGenericError(xmlGenericErrorContext,
642	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
643            name, type, publicId, systemId, content);
644#endif
645    if (ctxt->inSubset == 1) {
646	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
647		              systemId, content);
648	if ((ent == NULL) && (ctxt->pedantic))
649	    xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
650	     "Entity(%s) already defined in the internal subset\n",
651	               name);
652	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
653	    xmlChar *URI;
654	    const char *base = NULL;
655
656	    if (ctxt->input != NULL)
657		base = ctxt->input->filename;
658	    if (base == NULL)
659		base = ctxt->directory;
660
661	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
662	    ent->URI = URI;
663	}
664    } else if (ctxt->inSubset == 2) {
665	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
666		              systemId, content);
667	if ((ent == NULL) && (ctxt->pedantic) &&
668	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
669	    ctxt->sax->warning(ctxt->userData,
670	     "Entity(%s) already defined in the external subset\n", name);
671	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
672	    xmlChar *URI;
673	    const char *base = NULL;
674
675	    if (ctxt->input != NULL)
676		base = ctxt->input->filename;
677	    if (base == NULL)
678		base = ctxt->directory;
679
680	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
681	    ent->URI = URI;
682	}
683    } else {
684	xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
685	               "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
686		       name, NULL);
687    }
688}
689
690/**
691 * xmlSAX2AttributeDecl:
692 * @ctx: the user data (XML parser context)
693 * @elem:  the name of the element
694 * @fullname:  the attribute name
695 * @type:  the attribute type
696 * @def:  the type of default value
697 * @defaultValue: the attribute default value
698 * @tree:  the tree of enumerated value set
699 *
700 * An attribute definition has been parsed
701 */
702void
703xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
704              int type, int def, const xmlChar *defaultValue,
705	      xmlEnumerationPtr tree)
706{
707    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
708    xmlAttributePtr attr;
709    xmlChar *name = NULL, *prefix = NULL;
710
711    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
712        return;
713
714#ifdef DEBUG_SAX
715    xmlGenericError(xmlGenericErrorContext,
716	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
717            elem, fullname, type, def, defaultValue);
718#endif
719    if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
720        (type != XML_ATTRIBUTE_ID)) {
721	/*
722	 * Raise the error but keep the validity flag
723	 */
724	int tmp = ctxt->valid;
725	xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
726	      "xml:id : attribute type should be ID\n", NULL, NULL);
727	ctxt->valid = tmp;
728    }
729    /* TODO: optimize name/prefix allocation */
730    name = xmlSplitQName(ctxt, fullname, &prefix);
731    ctxt->vctxt.valid = 1;
732    if (ctxt->inSubset == 1)
733	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
734	       name, prefix, (xmlAttributeType) type,
735	       (xmlAttributeDefault) def, defaultValue, tree);
736    else if (ctxt->inSubset == 2)
737	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
738	   name, prefix, (xmlAttributeType) type,
739	   (xmlAttributeDefault) def, defaultValue, tree);
740    else {
741        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
742	     "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
743	               name, NULL);
744	xmlFreeEnumeration(tree);
745	return;
746    }
747#ifdef LIBXML_VALID_ENABLED
748    if (ctxt->vctxt.valid == 0)
749	ctxt->valid = 0;
750    if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
751        (ctxt->myDoc->intSubset != NULL))
752	ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
753	                                        attr);
754#endif /* LIBXML_VALID_ENABLED */
755    if (prefix != NULL)
756	xmlFree(prefix);
757    if (name != NULL)
758	xmlFree(name);
759}
760
761/**
762 * xmlSAX2ElementDecl:
763 * @ctx: the user data (XML parser context)
764 * @name:  the element name
765 * @type:  the element type
766 * @content: the element value tree
767 *
768 * An element definition has been parsed
769 */
770void
771xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
772            xmlElementContentPtr content)
773{
774    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
775    xmlElementPtr elem = NULL;
776
777    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
778        return;
779
780#ifdef DEBUG_SAX
781    xmlGenericError(xmlGenericErrorContext,
782                    "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
783#endif
784
785    if (ctxt->inSubset == 1)
786        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
787                                 name, (xmlElementTypeVal) type, content);
788    else if (ctxt->inSubset == 2)
789        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
790                                 name, (xmlElementTypeVal) type, content);
791    else {
792        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
793	     "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
794	               name, NULL);
795        return;
796    }
797#ifdef LIBXML_VALID_ENABLED
798    if (elem == NULL)
799        ctxt->valid = 0;
800    if (ctxt->validate && ctxt->wellFormed &&
801        ctxt->myDoc && ctxt->myDoc->intSubset)
802        ctxt->valid &=
803            xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
804#endif /* LIBXML_VALID_ENABLED */
805}
806
807/**
808 * xmlSAX2NotationDecl:
809 * @ctx: the user data (XML parser context)
810 * @name: The name of the notation
811 * @publicId: The public ID of the entity
812 * @systemId: The system ID of the entity
813 *
814 * What to do when a notation declaration has been parsed.
815 */
816void
817xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
818	     const xmlChar *publicId, const xmlChar *systemId)
819{
820    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
821    xmlNotationPtr nota = NULL;
822
823    if ((ctxt == NULL) || (ctxt->myDoc == NULL))
824        return;
825
826#ifdef DEBUG_SAX
827    xmlGenericError(xmlGenericErrorContext,
828	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
829#endif
830
831    if ((publicId == NULL) && (systemId == NULL)) {
832	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
833	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
834	               name, NULL);
835	return;
836    } else if (ctxt->inSubset == 1)
837	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
838                              publicId, systemId);
839    else if (ctxt->inSubset == 2)
840	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
841                              publicId, systemId);
842    else {
843	xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
844	     "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
845	               name, NULL);
846	return;
847    }
848#ifdef LIBXML_VALID_ENABLED
849    if (nota == NULL) ctxt->valid = 0;
850    if ((ctxt->validate) && (ctxt->wellFormed) &&
851        (ctxt->myDoc->intSubset != NULL))
852	ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
853	                                       nota);
854#endif /* LIBXML_VALID_ENABLED */
855}
856
857/**
858 * xmlSAX2UnparsedEntityDecl:
859 * @ctx: the user data (XML parser context)
860 * @name: The name of the entity
861 * @publicId: The public ID of the entity
862 * @systemId: The system ID of the entity
863 * @notationName: the name of the notation
864 *
865 * What to do when an unparsed entity declaration is parsed
866 */
867void
868xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
869		   const xmlChar *publicId, const xmlChar *systemId,
870		   const xmlChar *notationName)
871{
872    xmlEntityPtr ent;
873    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
874    if (ctx == NULL) return;
875#ifdef DEBUG_SAX
876    xmlGenericError(xmlGenericErrorContext,
877	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
878            name, publicId, systemId, notationName);
879#endif
880    if (ctxt->inSubset == 1) {
881	ent = xmlAddDocEntity(ctxt->myDoc, name,
882			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
883			publicId, systemId, notationName);
884	if ((ent == NULL) && (ctxt->pedantic) &&
885	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
886	    ctxt->sax->warning(ctxt->userData,
887	     "Entity(%s) already defined in the internal subset\n", name);
888	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
889	    xmlChar *URI;
890	    const char *base = NULL;
891
892	    if (ctxt->input != NULL)
893		base = ctxt->input->filename;
894	    if (base == NULL)
895		base = ctxt->directory;
896
897	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
898	    ent->URI = URI;
899	}
900    } else if (ctxt->inSubset == 2) {
901	ent = xmlAddDtdEntity(ctxt->myDoc, name,
902			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
903			publicId, systemId, notationName);
904	if ((ent == NULL) && (ctxt->pedantic) &&
905	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
906	    ctxt->sax->warning(ctxt->userData,
907	     "Entity(%s) already defined in the external subset\n", name);
908	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
909	    xmlChar *URI;
910	    const char *base = NULL;
911
912	    if (ctxt->input != NULL)
913		base = ctxt->input->filename;
914	    if (base == NULL)
915		base = ctxt->directory;
916
917	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
918	    ent->URI = URI;
919	}
920    } else {
921        xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
922	     "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
923	               name, NULL);
924    }
925}
926
927/**
928 * xmlSAX2SetDocumentLocator:
929 * @ctx: the user data (XML parser context)
930 * @loc: A SAX Locator
931 *
932 * Receive the document locator at startup, actually xmlDefaultSAXLocator
933 * Everything is available on the context, so this is useless in our case.
934 */
935void
936xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
937{
938    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
939#ifdef DEBUG_SAX
940    xmlGenericError(xmlGenericErrorContext,
941	    "SAX.xmlSAX2SetDocumentLocator()\n");
942#endif
943}
944
945/**
946 * xmlSAX2StartDocument:
947 * @ctx: the user data (XML parser context)
948 *
949 * called when the document start being processed.
950 */
951void
952xmlSAX2StartDocument(void *ctx)
953{
954    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
955    xmlDocPtr doc;
956
957    if (ctx == NULL) return;
958
959#ifdef DEBUG_SAX
960    xmlGenericError(xmlGenericErrorContext,
961	    "SAX.xmlSAX2StartDocument()\n");
962#endif
963    if (ctxt->html) {
964#ifdef LIBXML_HTML_ENABLED
965	if (ctxt->myDoc == NULL)
966	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
967	ctxt->myDoc->properties = XML_DOC_HTML;
968	ctxt->myDoc->parseFlags = ctxt->options;
969	if (ctxt->myDoc == NULL) {
970	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
971	    return;
972	}
973#else
974        xmlGenericError(xmlGenericErrorContext,
975		"libxml2 built without HTML support\n");
976	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
977	ctxt->instate = XML_PARSER_EOF;
978	ctxt->disableSAX = 1;
979	return;
980#endif
981    } else {
982	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
983	if (doc != NULL) {
984	    doc->properties = 0;
985	    if (ctxt->options & XML_PARSE_OLD10)
986	        doc->properties |= XML_DOC_OLD10;
987	    doc->parseFlags = ctxt->options;
988	    if (ctxt->encoding != NULL)
989		doc->encoding = xmlStrdup(ctxt->encoding);
990	    else
991		doc->encoding = NULL;
992	    doc->standalone = ctxt->standalone;
993	} else {
994	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
995	    return;
996	}
997	if ((ctxt->dictNames) && (doc != NULL)) {
998	    doc->dict = ctxt->dict;
999	    xmlDictReference(doc->dict);
1000	}
1001    }
1002    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
1003	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
1004	ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
1005	if (ctxt->myDoc->URL == NULL)
1006	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
1007    }
1008}
1009
1010/**
1011 * xmlSAX2EndDocument:
1012 * @ctx: the user data (XML parser context)
1013 *
1014 * called when the document end has been detected.
1015 */
1016void
1017xmlSAX2EndDocument(void *ctx)
1018{
1019    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1020#ifdef DEBUG_SAX
1021    xmlGenericError(xmlGenericErrorContext,
1022	    "SAX.xmlSAX2EndDocument()\n");
1023#endif
1024    if (ctx == NULL) return;
1025#ifdef LIBXML_VALID_ENABLED
1026    if (ctxt->validate && ctxt->wellFormed &&
1027        ctxt->myDoc && ctxt->myDoc->intSubset)
1028	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
1029#endif /* LIBXML_VALID_ENABLED */
1030
1031    /*
1032     * Grab the encoding if it was added on-the-fly
1033     */
1034    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
1035	(ctxt->myDoc->encoding == NULL)) {
1036	ctxt->myDoc->encoding = ctxt->encoding;
1037	ctxt->encoding = NULL;
1038    }
1039    if ((ctxt->inputTab != NULL) &&
1040        (ctxt->inputNr > 0) && (ctxt->inputTab[0] != NULL) &&
1041        (ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
1042	(ctxt->myDoc->encoding == NULL)) {
1043	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
1044    }
1045    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
1046	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
1047	ctxt->myDoc->charset = ctxt->charset;
1048    }
1049}
1050
1051#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
1052/**
1053 * xmlSAX2AttributeInternal:
1054 * @ctx: the user data (XML parser context)
1055 * @fullname:  The attribute name, including namespace prefix
1056 * @value:  The attribute value
1057 * @prefix: the prefix on the element node
1058 *
1059 * Handle an attribute that has been read by the parser.
1060 * The default handling is to convert the attribute into an
1061 * DOM subtree and past it in a new xmlAttr element added to
1062 * the element.
1063 */
1064static void
1065xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
1066             const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
1067{
1068    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1069    xmlAttrPtr ret;
1070    xmlChar *name;
1071    xmlChar *ns;
1072    xmlChar *nval;
1073    xmlNsPtr namespace;
1074
1075    if (ctxt->html) {
1076	name = xmlStrdup(fullname);
1077	ns = NULL;
1078	namespace = NULL;
1079    } else {
1080	/*
1081	 * Split the full name into a namespace prefix and the tag name
1082	 */
1083	name = xmlSplitQName(ctxt, fullname, &ns);
1084	if ((name != NULL) && (name[0] == 0)) {
1085	    if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1086		xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1087			    "invalid namespace declaration '%s'\n",
1088			    fullname, NULL);
1089	    } else {
1090		xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1091			     "Avoid attribute ending with ':' like '%s'\n",
1092			     fullname, NULL);
1093	    }
1094	    if (ns != NULL)
1095		xmlFree(ns);
1096	    ns = NULL;
1097	    xmlFree(name);
1098	    name = xmlStrdup(fullname);
1099	}
1100    }
1101    if (name == NULL) {
1102        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1103	if (ns != NULL)
1104	    xmlFree(ns);
1105	return;
1106    }
1107
1108#ifdef LIBXML_HTML_ENABLED
1109    if ((ctxt->html) &&
1110        (value == NULL) && (htmlIsBooleanAttr(fullname))) {
1111            nval = xmlStrdup(fullname);
1112            value = (const xmlChar *) nval;
1113    } else
1114#endif
1115    {
1116#ifdef LIBXML_VALID_ENABLED
1117        /*
1118         * Do the last stage of the attribute normalization
1119         * Needed for HTML too:
1120         *   http://www.w3.org/TR/html4/types.html#h-6.2
1121         */
1122        ctxt->vctxt.valid = 1;
1123        nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1124                                               ctxt->myDoc, ctxt->node,
1125                                               fullname, value);
1126        if (ctxt->vctxt.valid != 1) {
1127            ctxt->valid = 0;
1128        }
1129        if (nval != NULL)
1130            value = nval;
1131#else
1132        nval = NULL;
1133#endif /* LIBXML_VALID_ENABLED */
1134    }
1135
1136    /*
1137     * Check whether it's a namespace definition
1138     */
1139    if ((!ctxt->html) && (ns == NULL) &&
1140        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1141        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1142	xmlNsPtr nsret;
1143	xmlChar *val;
1144
1145        if (!ctxt->replaceEntities) {
1146	    ctxt->depth++;
1147	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1148		                          0,0,0);
1149	    ctxt->depth--;
1150	} else {
1151	    val = (xmlChar *) value;
1152	}
1153
1154	if (val[0] != 0) {
1155	    xmlURIPtr uri;
1156
1157	    uri = xmlParseURI((const char *)val);
1158	    if (uri == NULL) {
1159		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1160		    ctxt->sax->warning(ctxt->userData,
1161			 "xmlns: %s not a valid URI\n", val);
1162	    } else {
1163		if (uri->scheme == NULL) {
1164		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1165			ctxt->sax->warning(ctxt->userData,
1166			     "xmlns: URI %s is not absolute\n", val);
1167		}
1168		xmlFreeURI(uri);
1169	    }
1170	}
1171
1172	/* a default namespace definition */
1173	nsret = xmlNewNs(ctxt->node, val, NULL);
1174
1175#ifdef LIBXML_VALID_ENABLED
1176	/*
1177	 * Validate also for namespace decls, they are attributes from
1178	 * an XML-1.0 perspective
1179	 */
1180        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1181	    ctxt->myDoc && ctxt->myDoc->intSubset)
1182	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1183					   ctxt->node, prefix, nsret, val);
1184#endif /* LIBXML_VALID_ENABLED */
1185	if (name != NULL)
1186	    xmlFree(name);
1187	if (nval != NULL)
1188	    xmlFree(nval);
1189	if (val != value)
1190	    xmlFree(val);
1191	return;
1192    }
1193    if ((!ctxt->html) &&
1194	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1195        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1196	xmlNsPtr nsret;
1197	xmlChar *val;
1198
1199        if (!ctxt->replaceEntities) {
1200	    ctxt->depth++;
1201	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1202		                          0,0,0);
1203	    ctxt->depth--;
1204	    if (val == NULL) {
1205	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1206	        xmlFree(ns);
1207		if (name != NULL)
1208		    xmlFree(name);
1209		return;
1210	    }
1211	} else {
1212	    val = (xmlChar *) value;
1213	}
1214
1215	if (val[0] == 0) {
1216	    xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1217		        "Empty namespace name for prefix %s\n", name, NULL);
1218	}
1219	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1220	    xmlURIPtr uri;
1221
1222	    uri = xmlParseURI((const char *)val);
1223	    if (uri == NULL) {
1224	        xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
1225			 "xmlns:%s: %s not a valid URI\n", name, value);
1226	    } else {
1227		if (uri->scheme == NULL) {
1228		    xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1229			   "xmlns:%s: URI %s is not absolute\n", name, value);
1230		}
1231		xmlFreeURI(uri);
1232	    }
1233	}
1234
1235	/* a standard namespace definition */
1236	nsret = xmlNewNs(ctxt->node, val, name);
1237	xmlFree(ns);
1238#ifdef LIBXML_VALID_ENABLED
1239	/*
1240	 * Validate also for namespace decls, they are attributes from
1241	 * an XML-1.0 perspective
1242	 */
1243        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1244	    ctxt->myDoc && ctxt->myDoc->intSubset)
1245	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1246					   ctxt->node, prefix, nsret, value);
1247#endif /* LIBXML_VALID_ENABLED */
1248	if (name != NULL)
1249	    xmlFree(name);
1250	if (nval != NULL)
1251	    xmlFree(nval);
1252	if (val != value)
1253	    xmlFree(val);
1254	return;
1255    }
1256
1257    if (ns != NULL) {
1258	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1259
1260	if (namespace == NULL) {
1261	    xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1262		    "Namespace prefix %s of attribute %s is not defined\n",
1263		             ns, name);
1264	} else {
1265            xmlAttrPtr prop;
1266
1267            prop = ctxt->node->properties;
1268            while (prop != NULL) {
1269                if (prop->ns != NULL) {
1270                    if ((xmlStrEqual(name, prop->name)) &&
1271                        ((namespace == prop->ns) ||
1272                         (xmlStrEqual(namespace->href, prop->ns->href)))) {
1273                            xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1274                                    "Attribute %s in %s redefined\n",
1275                                             name, namespace->href);
1276                        ctxt->wellFormed = 0;
1277                        if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1278                        goto error;
1279                    }
1280                }
1281                prop = prop->next;
1282            }
1283        }
1284    } else {
1285	namespace = NULL;
1286    }
1287
1288    /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1289    ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1290
1291    if (ret != NULL) {
1292        if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1293	    xmlNodePtr tmp;
1294
1295	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1296	    tmp = ret->children;
1297	    while (tmp != NULL) {
1298		tmp->parent = (xmlNodePtr) ret;
1299		if (tmp->next == NULL)
1300		    ret->last = tmp;
1301		tmp = tmp->next;
1302	    }
1303	} else if (value != NULL) {
1304	    ret->children = xmlNewDocText(ctxt->myDoc, value);
1305	    ret->last = ret->children;
1306	    if (ret->children != NULL)
1307		ret->children->parent = (xmlNodePtr) ret;
1308	}
1309    }
1310
1311#ifdef LIBXML_VALID_ENABLED
1312    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1313        ctxt->myDoc && ctxt->myDoc->intSubset) {
1314
1315	/*
1316	 * If we don't substitute entities, the validation should be
1317	 * done on a value with replaced entities anyway.
1318	 */
1319        if (!ctxt->replaceEntities) {
1320	    xmlChar *val;
1321
1322	    ctxt->depth++;
1323	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1324		                          0,0,0);
1325	    ctxt->depth--;
1326
1327	    if (val == NULL)
1328		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1329				ctxt->myDoc, ctxt->node, ret, value);
1330	    else {
1331		xmlChar *nvalnorm;
1332
1333		/*
1334		 * Do the last stage of the attribute normalization
1335		 * It need to be done twice ... it's an extra burden related
1336		 * to the ability to keep xmlSAX2References in attributes
1337		 */
1338		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1339					    ctxt->node, fullname, val);
1340		if (nvalnorm != NULL) {
1341		    xmlFree(val);
1342		    val = nvalnorm;
1343		}
1344
1345		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1346			        ctxt->myDoc, ctxt->node, ret, val);
1347                xmlFree(val);
1348	    }
1349	} else {
1350	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1351					       ctxt->node, ret, value);
1352	}
1353    } else
1354#endif /* LIBXML_VALID_ENABLED */
1355           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1356	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1357	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
1358        /*
1359	 * when validating, the ID registration is done at the attribute
1360	 * validation level. Otherwise we have to do specific handling here.
1361	 */
1362	if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1363	    /*
1364	     * Add the xml:id value
1365	     *
1366	     * Open issue: normalization of the value.
1367	     */
1368	    if (xmlValidateNCName(value, 1) != 0) {
1369	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1370		      "xml:id : attribute value %s is not an NCName\n",
1371			    (const char *) value, NULL);
1372	    }
1373	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1374	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1375	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
1376	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1377	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
1378    }
1379
1380error:
1381    if (nval != NULL)
1382	xmlFree(nval);
1383    if (ns != NULL)
1384	xmlFree(ns);
1385}
1386
1387/*
1388 * xmlCheckDefaultedAttributes:
1389 *
1390 * Check defaulted attributes from the DTD
1391 */
1392static void
1393xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1394	const xmlChar *prefix, const xmlChar **atts) {
1395    xmlElementPtr elemDecl;
1396    const xmlChar *att;
1397    int internal = 1;
1398    int i;
1399
1400    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1401    if (elemDecl == NULL) {
1402	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1403	internal = 0;
1404    }
1405
1406process_external_subset:
1407
1408    if (elemDecl != NULL) {
1409	xmlAttributePtr attr = elemDecl->attributes;
1410	/*
1411	 * Check against defaulted attributes from the external subset
1412	 * if the document is stamped as standalone
1413	 */
1414	if ((ctxt->myDoc->standalone == 1) &&
1415	    (ctxt->myDoc->extSubset != NULL) &&
1416	    (ctxt->validate)) {
1417	    while (attr != NULL) {
1418		if ((attr->defaultValue != NULL) &&
1419		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1420					attr->elem, attr->name,
1421					attr->prefix) == attr) &&
1422		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1423					attr->elem, attr->name,
1424					attr->prefix) == NULL)) {
1425		    xmlChar *fulln;
1426
1427		    if (attr->prefix != NULL) {
1428			fulln = xmlStrdup(attr->prefix);
1429			fulln = xmlStrcat(fulln, BAD_CAST ":");
1430			fulln = xmlStrcat(fulln, attr->name);
1431		    } else {
1432			fulln = xmlStrdup(attr->name);
1433		    }
1434                    if (fulln == NULL) {
1435                        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1436                        break;
1437                    }
1438
1439		    /*
1440		     * Check that the attribute is not declared in the
1441		     * serialization
1442		     */
1443		    att = NULL;
1444		    if (atts != NULL) {
1445			i = 0;
1446			att = atts[i];
1447			while (att != NULL) {
1448			    if (xmlStrEqual(att, fulln))
1449				break;
1450			    i += 2;
1451			    att = atts[i];
1452			}
1453		    }
1454		    if (att == NULL) {
1455		        xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1456      "standalone: attribute %s on %s defaulted from external subset\n",
1457				    (const char *)fulln,
1458				    (const char *)attr->elem);
1459		    }
1460                    xmlFree(fulln);
1461		}
1462		attr = attr->nexth;
1463	    }
1464	}
1465
1466	/*
1467	 * Actually insert defaulted values when needed
1468	 */
1469	attr = elemDecl->attributes;
1470	while (attr != NULL) {
1471	    /*
1472	     * Make sure that attributes redefinition occuring in the
1473	     * internal subset are not overriden by definitions in the
1474	     * external subset.
1475	     */
1476	    if (attr->defaultValue != NULL) {
1477		/*
1478		 * the element should be instantiated in the tree if:
1479		 *  - this is a namespace prefix
1480		 *  - the user required for completion in the tree
1481		 *    like XSLT
1482		 *  - there isn't already an attribute definition
1483		 *    in the internal subset overriding it.
1484		 */
1485		if (((attr->prefix != NULL) &&
1486		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1487		    ((attr->prefix == NULL) &&
1488		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1489		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1490		    xmlAttributePtr tst;
1491
1492		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1493					     attr->elem, attr->name,
1494					     attr->prefix);
1495		    if ((tst == attr) || (tst == NULL)) {
1496		        xmlChar fn[50];
1497			xmlChar *fulln;
1498
1499                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1500			if (fulln == NULL) {
1501			    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1502			    return;
1503			}
1504
1505			/*
1506			 * Check that the attribute is not declared in the
1507			 * serialization
1508			 */
1509			att = NULL;
1510			if (atts != NULL) {
1511			    i = 0;
1512			    att = atts[i];
1513			    while (att != NULL) {
1514				if (xmlStrEqual(att, fulln))
1515				    break;
1516				i += 2;
1517				att = atts[i];
1518			    }
1519			}
1520			if (att == NULL) {
1521			    xmlSAX2AttributeInternal(ctxt, fulln,
1522						 attr->defaultValue, prefix);
1523			}
1524			if ((fulln != fn) && (fulln != attr->name))
1525			    xmlFree(fulln);
1526		    }
1527		}
1528	    }
1529	    attr = attr->nexth;
1530	}
1531	if (internal == 1) {
1532	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1533		                             name, prefix);
1534	    internal = 0;
1535	    goto process_external_subset;
1536	}
1537    }
1538}
1539
1540/**
1541 * xmlSAX2StartElement:
1542 * @ctx: the user data (XML parser context)
1543 * @fullname:  The element name, including namespace prefix
1544 * @atts:  An array of name/value attributes pairs, NULL terminated
1545 *
1546 * called when an opening tag has been processed.
1547 */
1548void
1549xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1550{
1551    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1552    xmlNodePtr ret;
1553    xmlNodePtr parent;
1554    xmlNsPtr ns;
1555    xmlChar *name;
1556    xmlChar *prefix;
1557    const xmlChar *att;
1558    const xmlChar *value;
1559    int i;
1560
1561    if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
1562    parent = ctxt->node;
1563#ifdef DEBUG_SAX
1564    xmlGenericError(xmlGenericErrorContext,
1565	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
1566#endif
1567
1568    /*
1569     * First check on validity:
1570     */
1571    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1572        ((ctxt->myDoc->intSubset == NULL) ||
1573	 ((ctxt->myDoc->intSubset->notations == NULL) &&
1574	  (ctxt->myDoc->intSubset->elements == NULL) &&
1575	  (ctxt->myDoc->intSubset->attributes == NULL) &&
1576	  (ctxt->myDoc->intSubset->entities == NULL)))) {
1577	xmlErrValid(ctxt, XML_ERR_NO_DTD,
1578	  "Validation failed: no DTD found !", NULL, NULL);
1579	ctxt->validate = 0;
1580    }
1581
1582
1583    /*
1584     * Split the full name into a namespace prefix and the tag name
1585     */
1586    name = xmlSplitQName(ctxt, fullname, &prefix);
1587
1588
1589    /*
1590     * Note : the namespace resolution is deferred until the end of the
1591     *        attributes parsing, since local namespace can be defined as
1592     *        an attribute at this level.
1593     */
1594    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1595    if (ret == NULL) {
1596        if (prefix != NULL)
1597	    xmlFree(prefix);
1598	xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1599        return;
1600    }
1601    if (ctxt->myDoc->children == NULL) {
1602#ifdef DEBUG_SAX_TREE
1603	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
1604#endif
1605        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
1606    } else if (parent == NULL) {
1607        parent = ctxt->myDoc->children;
1608    }
1609    ctxt->nodemem = -1;
1610    if (ctxt->linenumbers) {
1611	if (ctxt->input != NULL) {
1612	    if (ctxt->input->line < 65535)
1613		ret->line = (short) ctxt->input->line;
1614	    else
1615	        ret->line = 65535;
1616	}
1617    }
1618
1619    /*
1620     * We are parsing a new node.
1621     */
1622#ifdef DEBUG_SAX_TREE
1623    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
1624#endif
1625    nodePush(ctxt, ret);
1626
1627    /*
1628     * Link the child element
1629     */
1630    if (parent != NULL) {
1631        if (parent->type == XML_ELEMENT_NODE) {
1632#ifdef DEBUG_SAX_TREE
1633	    xmlGenericError(xmlGenericErrorContext,
1634		    "adding child %s to %s\n", name, parent->name);
1635#endif
1636	    xmlAddChild(parent, ret);
1637	} else {
1638#ifdef DEBUG_SAX_TREE
1639	    xmlGenericError(xmlGenericErrorContext,
1640		    "adding sibling %s to ", name);
1641	    xmlDebugDumpOneNode(stderr, parent, 0);
1642#endif
1643	    xmlAddSibling(parent, ret);
1644	}
1645    }
1646
1647    /*
1648     * Insert all the defaulted attributes from the DTD especially namespaces
1649     */
1650    if ((!ctxt->html) &&
1651	((ctxt->myDoc->intSubset != NULL) ||
1652	 (ctxt->myDoc->extSubset != NULL))) {
1653	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1654    }
1655
1656    /*
1657     * process all the attributes whose name start with "xmlns"
1658     */
1659    if (atts != NULL) {
1660        i = 0;
1661	att = atts[i++];
1662	value = atts[i++];
1663	if (!ctxt->html) {
1664	    while ((att != NULL) && (value != NULL)) {
1665		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1666		    (att[3] == 'n') && (att[4] == 's'))
1667		    xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1668
1669		att = atts[i++];
1670		value = atts[i++];
1671	    }
1672	}
1673    }
1674
1675    /*
1676     * Search the namespace, note that since the attributes have been
1677     * processed, the local namespaces are available.
1678     */
1679    ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1680    if ((ns == NULL) && (parent != NULL))
1681	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1682    if ((prefix != NULL) && (ns == NULL)) {
1683	ns = xmlNewNs(ret, NULL, prefix);
1684	xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1685		     "Namespace prefix %s is not defined\n",
1686		     prefix, NULL);
1687    }
1688
1689    /*
1690     * set the namespace node, making sure that if the default namspace
1691     * is unbound on a parent we simply kee it NULL
1692     */
1693    if ((ns != NULL) && (ns->href != NULL) &&
1694	((ns->href[0] != 0) || (ns->prefix != NULL)))
1695	xmlSetNs(ret, ns);
1696
1697    /*
1698     * process all the other attributes
1699     */
1700    if (atts != NULL) {
1701        i = 0;
1702	att = atts[i++];
1703	value = atts[i++];
1704	if (ctxt->html) {
1705	    while (att != NULL) {
1706		xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1707		att = atts[i++];
1708		value = atts[i++];
1709	    }
1710	} else {
1711	    while ((att != NULL) && (value != NULL)) {
1712		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1713		    (att[3] != 'n') || (att[4] != 's'))
1714		    xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1715
1716		/*
1717		 * Next ones
1718		 */
1719		att = atts[i++];
1720		value = atts[i++];
1721	    }
1722	}
1723    }
1724
1725#ifdef LIBXML_VALID_ENABLED
1726    /*
1727     * If it's the Document root, finish the DTD validation and
1728     * check the document root element for validity
1729     */
1730    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
1731	int chk;
1732
1733	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1734	if (chk <= 0)
1735	    ctxt->valid = 0;
1736	if (chk < 0)
1737	    ctxt->wellFormed = 0;
1738	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1739	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
1740    }
1741#endif /* LIBXML_VALID_ENABLED */
1742
1743    if (prefix != NULL)
1744	xmlFree(prefix);
1745
1746}
1747
1748/**
1749 * xmlSAX2EndElement:
1750 * @ctx: the user data (XML parser context)
1751 * @name:  The element name
1752 *
1753 * called when the end of an element has been detected.
1754 */
1755void
1756xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1757{
1758    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1759    xmlParserNodeInfo node_info;
1760    xmlNodePtr cur;
1761
1762    if (ctx == NULL) return;
1763    cur = ctxt->node;
1764#ifdef DEBUG_SAX
1765    if (name == NULL)
1766        xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
1767    else
1768	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
1769#endif
1770
1771    /* Capture end position and add node */
1772    if (cur != NULL && ctxt->record_info) {
1773      node_info.end_pos = ctxt->input->cur - ctxt->input->base;
1774      node_info.end_line = ctxt->input->line;
1775      node_info.node = cur;
1776      xmlParserAddNodeInfo(ctxt, &node_info);
1777    }
1778    ctxt->nodemem = -1;
1779
1780#ifdef LIBXML_VALID_ENABLED
1781    if (ctxt->validate && ctxt->wellFormed &&
1782        ctxt->myDoc && ctxt->myDoc->intSubset)
1783        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1784					     cur);
1785#endif /* LIBXML_VALID_ENABLED */
1786
1787
1788    /*
1789     * end of parsing of this node.
1790     */
1791#ifdef DEBUG_SAX_TREE
1792    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
1793#endif
1794    nodePop(ctxt);
1795}
1796#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLE */
1797
1798/*
1799 * xmlSAX2TextNode:
1800 * @ctxt:  the parser context
1801 * @str:  the input string
1802 * @len: the string length
1803 *
1804 * Remove the entities from an attribute value
1805 *
1806 * Returns the newly allocated string or NULL if not needed or error
1807 */
1808static xmlNodePtr
1809xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1810    xmlNodePtr ret;
1811    const xmlChar *intern = NULL;
1812
1813    /*
1814     * Allocate
1815     */
1816    if (ctxt->freeElems != NULL) {
1817	ret = ctxt->freeElems;
1818	ctxt->freeElems = ret->next;
1819	ctxt->freeElemsNr--;
1820    } else {
1821	ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1822    }
1823    if (ret == NULL) {
1824        xmlErrMemory(ctxt, "xmlSAX2Characters");
1825	return(NULL);
1826    }
1827    memset(ret, 0, sizeof(xmlNode));
1828    /*
1829     * intern the formatting blanks found between tags, or the
1830     * very short strings
1831     */
1832    if (ctxt->dictNames) {
1833        xmlChar cur = str[len];
1834
1835	if ((len < (int) (2 * sizeof(void *))) &&
1836	    (ctxt->options & XML_PARSE_COMPACT)) {
1837	    /* store the string in the node overrithing properties and nsDef */
1838	    xmlChar *tmp = (xmlChar *) &(ret->properties);
1839	    memcpy(tmp, str, len);
1840	    tmp[len] = 0;
1841	    intern = tmp;
1842	} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1843	    ((cur == '<') && (str[len + 1] != '!')))) {
1844	    intern = xmlDictLookup(ctxt->dict, str, len);
1845	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1846	           (str[len + 1] != '!')) {
1847	    int i;
1848
1849	    for (i = 1;i < len;i++) {
1850		if (!IS_BLANK_CH(str[i])) goto skip;
1851	    }
1852	    intern = xmlDictLookup(ctxt->dict, str, len);
1853	}
1854    }
1855skip:
1856    ret->type = XML_TEXT_NODE;
1857
1858    ret->name = xmlStringText;
1859    if (intern == NULL) {
1860	ret->content = xmlStrndup(str, len);
1861	if (ret->content == NULL) {
1862	    xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1863	    xmlFree(ret);
1864	    return(NULL);
1865	}
1866    } else
1867	ret->content = (xmlChar *) intern;
1868
1869    if (ctxt->input != NULL)
1870        ret->line = ctxt->input->line;
1871
1872    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1873	xmlRegisterNodeDefaultValue(ret);
1874    return(ret);
1875}
1876
1877#ifdef LIBXML_VALID_ENABLED
1878/*
1879 * xmlSAX2DecodeAttrEntities:
1880 * @ctxt:  the parser context
1881 * @str:  the input string
1882 * @len: the string length
1883 *
1884 * Remove the entities from an attribute value
1885 *
1886 * Returns the newly allocated string or NULL if not needed or error
1887 */
1888static xmlChar *
1889xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1890                          const xmlChar *end) {
1891    const xmlChar *in;
1892    xmlChar *ret;
1893
1894    in = str;
1895    while (in < end)
1896        if (*in++ == '&')
1897	    goto decode;
1898    return(NULL);
1899decode:
1900    ctxt->depth++;
1901    ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1902				     XML_SUBSTITUTE_REF, 0,0,0);
1903    ctxt->depth--;
1904    return(ret);
1905}
1906#endif /* LIBXML_VALID_ENABLED */
1907
1908/**
1909 * xmlSAX2AttributeNs:
1910 * @ctx: the user data (XML parser context)
1911 * @localname:  the local name of the attribute
1912 * @prefix:  the attribute namespace prefix if available
1913 * @URI:  the attribute namespace name if available
1914 * @value:  Start of the attribute value
1915 * @valueend: end of the attribute value
1916 *
1917 * Handle an attribute that has been read by the parser.
1918 * The default handling is to convert the attribute into an
1919 * DOM subtree and past it in a new xmlAttr element added to
1920 * the element.
1921 */
1922static void
1923xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1924                   const xmlChar * localname,
1925                   const xmlChar * prefix,
1926		   const xmlChar * value,
1927		   const xmlChar * valueend)
1928{
1929    xmlAttrPtr ret;
1930    xmlNsPtr namespace = NULL;
1931    xmlChar *dup = NULL;
1932
1933    /*
1934     * Note: if prefix == NULL, the attribute is not in the default namespace
1935     */
1936    if (prefix != NULL)
1937	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1938
1939    /*
1940     * allocate the node
1941     */
1942    if (ctxt->freeAttrs != NULL) {
1943        ret = ctxt->freeAttrs;
1944	ctxt->freeAttrs = ret->next;
1945	ctxt->freeAttrsNr--;
1946	memset(ret, 0, sizeof(xmlAttr));
1947	ret->type = XML_ATTRIBUTE_NODE;
1948
1949	ret->parent = ctxt->node;
1950	ret->doc = ctxt->myDoc;
1951	ret->ns = namespace;
1952
1953	if (ctxt->dictNames)
1954	    ret->name = localname;
1955	else
1956	    ret->name = xmlStrdup(localname);
1957
1958        /* link at the end to preserv order, TODO speed up with a last */
1959	if (ctxt->node->properties == NULL) {
1960	    ctxt->node->properties = ret;
1961	} else {
1962	    xmlAttrPtr prev = ctxt->node->properties;
1963
1964	    while (prev->next != NULL) prev = prev->next;
1965	    prev->next = ret;
1966	    ret->prev = prev;
1967	}
1968
1969	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1970	    xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1971    } else {
1972	if (ctxt->dictNames)
1973	    ret = xmlNewNsPropEatName(ctxt->node, namespace,
1974	                              (xmlChar *) localname, NULL);
1975	else
1976	    ret = xmlNewNsProp(ctxt->node, namespace, localname, NULL);
1977	if (ret == NULL) {
1978	    xmlErrMemory(ctxt, "xmlSAX2AttributeNs");
1979	    return;
1980	}
1981    }
1982
1983    if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1984	xmlNodePtr tmp;
1985
1986	/*
1987	 * We know that if there is an entity reference, then
1988	 * the string has been dup'ed and terminates with 0
1989	 * otherwise with ' or "
1990	 */
1991	if (*valueend != 0) {
1992	    tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1993	    ret->children = tmp;
1994	    ret->last = tmp;
1995	    if (tmp != NULL) {
1996		tmp->doc = ret->doc;
1997		tmp->parent = (xmlNodePtr) ret;
1998	    }
1999	} else {
2000	    ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
2001						    valueend - value);
2002	    tmp = ret->children;
2003	    while (tmp != NULL) {
2004	        tmp->doc = ret->doc;
2005		tmp->parent = (xmlNodePtr) ret;
2006		if (tmp->next == NULL)
2007		    ret->last = tmp;
2008		tmp = tmp->next;
2009	    }
2010	}
2011    } else if (value != NULL) {
2012	xmlNodePtr tmp;
2013
2014	tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
2015	ret->children = tmp;
2016	ret->last = tmp;
2017	if (tmp != NULL) {
2018	    tmp->doc = ret->doc;
2019	    tmp->parent = (xmlNodePtr) ret;
2020	}
2021    }
2022
2023#ifdef LIBXML_VALID_ENABLED
2024    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2025        ctxt->myDoc && ctxt->myDoc->intSubset) {
2026	/*
2027	 * If we don't substitute entities, the validation should be
2028	 * done on a value with replaced entities anyway.
2029	 */
2030        if (!ctxt->replaceEntities) {
2031	    dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
2032	    if (dup == NULL) {
2033	        if (*valueend == 0) {
2034		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2035				    ctxt->myDoc, ctxt->node, ret, value);
2036		} else {
2037		    /*
2038		     * That should already be normalized.
2039		     * cheaper to finally allocate here than duplicate
2040		     * entry points in the full validation code
2041		     */
2042		    dup = xmlStrndup(value, valueend - value);
2043
2044		    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2045				    ctxt->myDoc, ctxt->node, ret, dup);
2046		}
2047	    } else {
2048	        /*
2049		 * dup now contains a string of the flattened attribute
2050		 * content with entities substitued. Check if we need to
2051		 * apply an extra layer of normalization.
2052		 * It need to be done twice ... it's an extra burden related
2053		 * to the ability to keep references in attributes
2054		 */
2055		if (ctxt->attsSpecial != NULL) {
2056		    xmlChar *nvalnorm;
2057		    xmlChar fn[50];
2058		    xmlChar *fullname;
2059
2060		    fullname = xmlBuildQName(localname, prefix, fn, 50);
2061		    if (fullname != NULL) {
2062			ctxt->vctxt.valid = 1;
2063		        nvalnorm = xmlValidCtxtNormalizeAttributeValue(
2064			                 &ctxt->vctxt, ctxt->myDoc,
2065					 ctxt->node, fullname, dup);
2066			if (ctxt->vctxt.valid != 1)
2067			    ctxt->valid = 0;
2068
2069			if ((fullname != fn) && (fullname != localname))
2070			    xmlFree(fullname);
2071			if (nvalnorm != NULL) {
2072			    xmlFree(dup);
2073			    dup = nvalnorm;
2074			}
2075		    }
2076		}
2077
2078		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2079			        ctxt->myDoc, ctxt->node, ret, dup);
2080	    }
2081	} else {
2082	    /*
2083	     * if entities already have been substitued, then
2084	     * the attribute as passed is already normalized
2085	     */
2086	    dup = xmlStrndup(value, valueend - value);
2087
2088	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2089	                             ctxt->myDoc, ctxt->node, ret, dup);
2090	}
2091    } else
2092#endif /* LIBXML_VALID_ENABLED */
2093           if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2094	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2095	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
2096        /*
2097	 * when validating, the ID registration is done at the attribute
2098	 * validation level. Otherwise we have to do specific handling here.
2099	 */
2100        if ((prefix == ctxt->str_xml) &&
2101	           (localname[0] == 'i') && (localname[1] == 'd') &&
2102		   (localname[2] == 0)) {
2103	    /*
2104	     * Add the xml:id value
2105	     *
2106	     * Open issue: normalization of the value.
2107	     */
2108	    if (dup == NULL)
2109	        dup = xmlStrndup(value, valueend - value);
2110#ifdef LIBXML_VALID_ENABLED
2111	    if (xmlValidateNCName(dup, 1) != 0) {
2112	        xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2113		      "xml:id : attribute value %s is not an NCName\n",
2114			    (const char *) dup, NULL);
2115	    }
2116#endif
2117	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2118	} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2119	    /* might be worth duplicate entry points and not copy */
2120	    if (dup == NULL)
2121	        dup = xmlStrndup(value, valueend - value);
2122	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2123	} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2124	    if (dup == NULL)
2125	        dup = xmlStrndup(value, valueend - value);
2126	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, dup, ret);
2127	}
2128    }
2129    if (dup != NULL)
2130	xmlFree(dup);
2131}
2132
2133/**
2134 * xmlSAX2StartElementNs:
2135 * @ctx:  the user data (XML parser context)
2136 * @localname:  the local name of the element
2137 * @prefix:  the element namespace prefix if available
2138 * @URI:  the element namespace name if available
2139 * @nb_namespaces:  number of namespace definitions on that node
2140 * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
2141 * @nb_attributes:  the number of attributes on that node
2142 * @nb_defaulted:  the number of defaulted attributes.
2143 * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
2144 *               attribute values.
2145 *
2146 * SAX2 callback when an element start has been detected by the parser.
2147 * It provides the namespace informations for the element, as well as
2148 * the new namespace declarations on the element.
2149 */
2150void
2151xmlSAX2StartElementNs(void *ctx,
2152                      const xmlChar *localname,
2153		      const xmlChar *prefix,
2154		      const xmlChar *URI,
2155		      int nb_namespaces,
2156		      const xmlChar **namespaces,
2157		      int nb_attributes,
2158		      int nb_defaulted,
2159		      const xmlChar **attributes)
2160{
2161    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2162    xmlNodePtr ret;
2163    xmlNodePtr parent;
2164    xmlNsPtr last = NULL, ns;
2165    const xmlChar *uri, *pref;
2166    int i, j;
2167
2168    if (ctx == NULL) return;
2169    parent = ctxt->node;
2170    /*
2171     * First check on validity:
2172     */
2173    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2174        ((ctxt->myDoc->intSubset == NULL) ||
2175	 ((ctxt->myDoc->intSubset->notations == NULL) &&
2176	  (ctxt->myDoc->intSubset->elements == NULL) &&
2177	  (ctxt->myDoc->intSubset->attributes == NULL) &&
2178	  (ctxt->myDoc->intSubset->entities == NULL)))) {
2179	xmlErrValid(ctxt, XML_ERR_NO_DTD,
2180	  "Validation failed: no DTD found !", NULL, NULL);
2181	ctxt->validate = 0;
2182    }
2183
2184    /*
2185     * allocate the node
2186     */
2187    if (ctxt->freeElems != NULL) {
2188        ret = ctxt->freeElems;
2189	ctxt->freeElems = ret->next;
2190	ctxt->freeElemsNr--;
2191	memset(ret, 0, sizeof(xmlNode));
2192	ret->type = XML_ELEMENT_NODE;
2193
2194	if (ctxt->dictNames)
2195	    ret->name = localname;
2196	else {
2197	    ret->name = xmlStrdup(localname);
2198	    if (ret->name == NULL) {
2199	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2200		return;
2201	    }
2202	}
2203	if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2204	    xmlRegisterNodeDefaultValue(ret);
2205    } else {
2206	if (ctxt->dictNames)
2207	    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2208	                               (xmlChar *) localname, NULL);
2209	else
2210	    ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2211	if (ret == NULL) {
2212	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2213	    return;
2214	}
2215    }
2216    if (ctxt->linenumbers) {
2217	if (ctxt->input != NULL) {
2218	    if (ctxt->input->line < 65535)
2219		ret->line = (short) ctxt->input->line;
2220	    else
2221	        ret->line = 65535;
2222	}
2223    }
2224
2225    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2226        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2227    }
2228    /*
2229     * Build the namespace list
2230     */
2231    for (i = 0,j = 0;j < nb_namespaces;j++) {
2232        pref = namespaces[i++];
2233	uri = namespaces[i++];
2234	ns = xmlNewNs(NULL, uri, pref);
2235	if (ns != NULL) {
2236	    if (last == NULL) {
2237	        ret->nsDef = last = ns;
2238	    } else {
2239	        last->next = ns;
2240		last = ns;
2241	    }
2242	    if ((URI != NULL) && (prefix == pref))
2243		ret->ns = ns;
2244	} else {
2245	    xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2246	    return;
2247	}
2248#ifdef LIBXML_VALID_ENABLED
2249	if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2250	    ctxt->myDoc && ctxt->myDoc->intSubset) {
2251	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2252	                                           ret, prefix, ns, uri);
2253	}
2254#endif /* LIBXML_VALID_ENABLED */
2255    }
2256    ctxt->nodemem = -1;
2257
2258    /*
2259     * We are parsing a new node.
2260     */
2261    nodePush(ctxt, ret);
2262
2263    /*
2264     * Link the child element
2265     */
2266    if (parent != NULL) {
2267        if (parent->type == XML_ELEMENT_NODE) {
2268	    xmlAddChild(parent, ret);
2269	} else {
2270	    xmlAddSibling(parent, ret);
2271	}
2272    }
2273
2274    /*
2275     * Insert the defaulted attributes from the DTD only if requested:
2276     */
2277    if ((nb_defaulted != 0) &&
2278        ((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2279	nb_attributes -= nb_defaulted;
2280
2281    /*
2282     * Search the namespace if it wasn't already found
2283     * Note that, if prefix is NULL, this searches for the default Ns
2284     */
2285    if ((URI != NULL) && (ret->ns == NULL)) {
2286        ret->ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
2287	if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2288	    ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2289	}
2290	if (ret->ns == NULL) {
2291	    ns = xmlNewNs(ret, NULL, prefix);
2292	    if (ns == NULL) {
2293
2294	        xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2295		return;
2296	    }
2297            if (prefix != NULL)
2298                xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2299                             "Namespace prefix %s was not found\n",
2300                             prefix, NULL);
2301            else
2302                xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2303                             "Namespace default prefix was not found\n",
2304                             NULL, NULL);
2305	}
2306    }
2307
2308    /*
2309     * process all the other attributes
2310     */
2311    if (nb_attributes > 0) {
2312        for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2313	    xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2314	                       attributes[j+3], attributes[j+4]);
2315	}
2316    }
2317
2318#ifdef LIBXML_VALID_ENABLED
2319    /*
2320     * If it's the Document root, finish the DTD validation and
2321     * check the document root element for validity
2322     */
2323    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == XML_CTXT_FINISH_DTD_0)) {
2324	int chk;
2325
2326	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2327	if (chk <= 0)
2328	    ctxt->valid = 0;
2329	if (chk < 0)
2330	    ctxt->wellFormed = 0;
2331	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2332	ctxt->vctxt.finishDtd = XML_CTXT_FINISH_DTD_1;
2333    }
2334#endif /* LIBXML_VALID_ENABLED */
2335}
2336
2337/**
2338 * xmlSAX2EndElementNs:
2339 * @ctx:  the user data (XML parser context)
2340 * @localname:  the local name of the element
2341 * @prefix:  the element namespace prefix if available
2342 * @URI:  the element namespace name if available
2343 *
2344 * SAX2 callback when an element end has been detected by the parser.
2345 * It provides the namespace informations for the element.
2346 */
2347void
2348xmlSAX2EndElementNs(void *ctx,
2349                    const xmlChar * localname ATTRIBUTE_UNUSED,
2350                    const xmlChar * prefix ATTRIBUTE_UNUSED,
2351		    const xmlChar * URI ATTRIBUTE_UNUSED)
2352{
2353    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2354    xmlParserNodeInfo node_info;
2355    xmlNodePtr cur;
2356
2357    if (ctx == NULL) return;
2358    cur = ctxt->node;
2359    /* Capture end position and add node */
2360    if ((ctxt->record_info) && (cur != NULL)) {
2361        node_info.end_pos = ctxt->input->cur - ctxt->input->base;
2362        node_info.end_line = ctxt->input->line;
2363        node_info.node = cur;
2364        xmlParserAddNodeInfo(ctxt, &node_info);
2365    }
2366    ctxt->nodemem = -1;
2367
2368#ifdef LIBXML_VALID_ENABLED
2369    if (ctxt->validate && ctxt->wellFormed &&
2370        ctxt->myDoc && ctxt->myDoc->intSubset)
2371        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc, cur);
2372#endif /* LIBXML_VALID_ENABLED */
2373
2374    /*
2375     * end of parsing of this node.
2376     */
2377    nodePop(ctxt);
2378}
2379
2380/**
2381 * xmlSAX2Reference:
2382 * @ctx: the user data (XML parser context)
2383 * @name:  The entity name
2384 *
2385 * called when an entity xmlSAX2Reference is detected.
2386 */
2387void
2388xmlSAX2Reference(void *ctx, const xmlChar *name)
2389{
2390    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2391    xmlNodePtr ret;
2392
2393    if (ctx == NULL) return;
2394#ifdef DEBUG_SAX
2395    xmlGenericError(xmlGenericErrorContext,
2396	    "SAX.xmlSAX2Reference(%s)\n", name);
2397#endif
2398    if (name[0] == '#')
2399	ret = xmlNewCharRef(ctxt->myDoc, name);
2400    else
2401	ret = xmlNewReference(ctxt->myDoc, name);
2402#ifdef DEBUG_SAX_TREE
2403    xmlGenericError(xmlGenericErrorContext,
2404	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
2405#endif
2406    if (xmlAddChild(ctxt->node, ret) == NULL) {
2407        xmlFreeNode(ret);
2408    }
2409}
2410
2411/**
2412 * xmlSAX2Characters:
2413 * @ctx: the user data (XML parser context)
2414 * @ch:  a xmlChar string
2415 * @len: the number of xmlChar
2416 *
2417 * receiving some chars from the parser.
2418 */
2419void
2420xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2421{
2422    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2423    xmlNodePtr lastChild;
2424
2425    if (ctx == NULL) return;
2426#ifdef DEBUG_SAX
2427    xmlGenericError(xmlGenericErrorContext,
2428	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
2429#endif
2430    /*
2431     * Handle the data if any. If there is no child
2432     * add it as content, otherwise if the last child is text,
2433     * concatenate it, else create a new node of type text.
2434     */
2435
2436    if (ctxt->node == NULL) {
2437#ifdef DEBUG_SAX_TREE
2438	xmlGenericError(xmlGenericErrorContext,
2439		"add chars: ctxt->node == NULL !\n");
2440#endif
2441        return;
2442    }
2443    lastChild = ctxt->node->last;
2444#ifdef DEBUG_SAX_TREE
2445    xmlGenericError(xmlGenericErrorContext,
2446	    "add chars to %s \n", ctxt->node->name);
2447#endif
2448
2449    /*
2450     * Here we needed an accelerator mechanism in case of very large
2451     * elements. Use an attribute in the structure !!!
2452     */
2453    if (lastChild == NULL) {
2454        lastChild = xmlSAX2TextNode(ctxt, ch, len);
2455	if (lastChild != NULL) {
2456	    ctxt->node->children = lastChild;
2457	    ctxt->node->last = lastChild;
2458	    lastChild->parent = ctxt->node;
2459	    lastChild->doc = ctxt->node->doc;
2460	    ctxt->nodelen = len;
2461	    ctxt->nodemem = len + 1;
2462	} else {
2463	    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2464	    return;
2465	}
2466    } else {
2467	int coalesceText = (lastChild != NULL) &&
2468	    (lastChild->type == XML_TEXT_NODE) &&
2469	    (lastChild->name == xmlStringText);
2470	if ((coalesceText) && (ctxt->nodemem != 0)) {
2471	    /*
2472	     * The whole point of maintaining nodelen and nodemem,
2473	     * xmlTextConcat is too costly, i.e. compute length,
2474	     * reallocate a new buffer, move data, append ch. Here
2475	     * We try to minimaze realloc() uses and avoid copying
2476	     * and recomputing length over and over.
2477	     */
2478	    if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2479		lastChild->content = xmlStrdup(lastChild->content);
2480		lastChild->properties = NULL;
2481	    } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2482	               (xmlDictOwns(ctxt->dict, lastChild->content))) {
2483		lastChild->content = xmlStrdup(lastChild->content);
2484	    }
2485            if (((size_t)ctxt->nodelen + (size_t)len > XML_MAX_TEXT_LENGTH) &&
2486                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2487                xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2488                return;
2489            }
2490	    if ((size_t)ctxt->nodelen > SIZE_T_MAX - (size_t)len ||
2491	        (size_t)ctxt->nodemem + (size_t)len > SIZE_T_MAX / 2) {
2492                xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2493                return;
2494	    }
2495	    if (ctxt->nodelen + len >= ctxt->nodemem) {
2496		xmlChar *newbuf;
2497		size_t size;
2498
2499		size = ctxt->nodemem + len;
2500		size *= 2;
2501                newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2502		if (newbuf == NULL) {
2503		    xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2504		    return;
2505		}
2506		ctxt->nodemem = size;
2507		lastChild->content = newbuf;
2508	    }
2509	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2510	    ctxt->nodelen += len;
2511	    lastChild->content[ctxt->nodelen] = 0;
2512	} else if (coalesceText) {
2513	    if (xmlTextConcat(lastChild, ch, len)) {
2514		xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2515	    }
2516	    if (ctxt->node->children != NULL) {
2517		ctxt->nodelen = xmlStrlen(lastChild->content);
2518		ctxt->nodemem = ctxt->nodelen + 1;
2519	    }
2520	} else {
2521	    /* Mixed content, first time */
2522	    lastChild = xmlSAX2TextNode(ctxt, ch, len);
2523	    if (lastChild != NULL) {
2524		xmlAddChild(ctxt->node, lastChild);
2525		if (ctxt->node->children != NULL) {
2526		    ctxt->nodelen = len;
2527		    ctxt->nodemem = len + 1;
2528		}
2529	    }
2530	}
2531    }
2532}
2533
2534/**
2535 * xmlSAX2IgnorableWhitespace:
2536 * @ctx: the user data (XML parser context)
2537 * @ch:  a xmlChar string
2538 * @len: the number of xmlChar
2539 *
2540 * receiving some ignorable whitespaces from the parser.
2541 * UNUSED: by default the DOM building will use xmlSAX2Characters
2542 */
2543void
2544xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2545{
2546    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2547#ifdef DEBUG_SAX
2548    xmlGenericError(xmlGenericErrorContext,
2549	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
2550#endif
2551}
2552
2553/**
2554 * xmlSAX2ProcessingInstruction:
2555 * @ctx: the user data (XML parser context)
2556 * @target:  the target name
2557 * @data: the PI data's
2558 *
2559 * A processing instruction has been parsed.
2560 */
2561void
2562xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2563                      const xmlChar *data)
2564{
2565    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2566    xmlNodePtr ret;
2567    xmlNodePtr parent;
2568
2569    if (ctx == NULL) return;
2570    parent = ctxt->node;
2571#ifdef DEBUG_SAX
2572    xmlGenericError(xmlGenericErrorContext,
2573	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
2574#endif
2575
2576    ret = xmlNewDocPI(ctxt->myDoc, target, data);
2577    if (ret == NULL) return;
2578
2579    if (ctxt->linenumbers) {
2580	if (ctxt->input != NULL) {
2581	    if (ctxt->input->line < 65535)
2582		ret->line = (short) ctxt->input->line;
2583	    else
2584	        ret->line = 65535;
2585	}
2586    }
2587    if (ctxt->inSubset == 1) {
2588	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2589	return;
2590    } else if (ctxt->inSubset == 2) {
2591	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2592	return;
2593    }
2594    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2595#ifdef DEBUG_SAX_TREE
2596	    xmlGenericError(xmlGenericErrorContext,
2597		    "Setting PI %s as root\n", target);
2598#endif
2599        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2600	return;
2601    }
2602    if (parent->type == XML_ELEMENT_NODE) {
2603#ifdef DEBUG_SAX_TREE
2604	xmlGenericError(xmlGenericErrorContext,
2605		"adding PI %s child to %s\n", target, parent->name);
2606#endif
2607	xmlAddChild(parent, ret);
2608    } else {
2609#ifdef DEBUG_SAX_TREE
2610	xmlGenericError(xmlGenericErrorContext,
2611		"adding PI %s sibling to ", target);
2612	xmlDebugDumpOneNode(stderr, parent, 0);
2613#endif
2614	xmlAddSibling(parent, ret);
2615    }
2616}
2617
2618/**
2619 * xmlSAX2Comment:
2620 * @ctx: the user data (XML parser context)
2621 * @value:  the xmlSAX2Comment content
2622 *
2623 * A xmlSAX2Comment has been parsed.
2624 */
2625void
2626xmlSAX2Comment(void *ctx, const xmlChar *value)
2627{
2628    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2629    xmlNodePtr ret;
2630    xmlNodePtr parent;
2631
2632    if (ctx == NULL) return;
2633    parent = ctxt->node;
2634#ifdef DEBUG_SAX
2635    xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
2636#endif
2637    ret = xmlNewDocComment(ctxt->myDoc, value);
2638    if (ret == NULL) return;
2639    if (ctxt->linenumbers) {
2640	if (ctxt->input != NULL) {
2641	    if (ctxt->input->line < 65535)
2642		ret->line = (short) ctxt->input->line;
2643	    else
2644	        ret->line = 65535;
2645	}
2646    }
2647
2648    if (ctxt->inSubset == 1) {
2649	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2650	return;
2651    } else if (ctxt->inSubset == 2) {
2652	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2653	return;
2654    }
2655    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
2656#ifdef DEBUG_SAX_TREE
2657	    xmlGenericError(xmlGenericErrorContext,
2658		    "Setting xmlSAX2Comment as root\n");
2659#endif
2660        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2661	return;
2662    }
2663    if (parent->type == XML_ELEMENT_NODE) {
2664#ifdef DEBUG_SAX_TREE
2665	xmlGenericError(xmlGenericErrorContext,
2666		"adding xmlSAX2Comment child to %s\n", parent->name);
2667#endif
2668	xmlAddChild(parent, ret);
2669    } else {
2670#ifdef DEBUG_SAX_TREE
2671	xmlGenericError(xmlGenericErrorContext,
2672		"adding xmlSAX2Comment sibling to ");
2673	xmlDebugDumpOneNode(stderr, parent, 0);
2674#endif
2675	xmlAddSibling(parent, ret);
2676    }
2677}
2678
2679/**
2680 * xmlSAX2CDataBlock:
2681 * @ctx: the user data (XML parser context)
2682 * @value:  The pcdata content
2683 * @len:  the block length
2684 *
2685 * called when a pcdata block has been parsed
2686 */
2687void
2688xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2689{
2690    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2691    xmlNodePtr ret, lastChild;
2692
2693    if (ctx == NULL) return;
2694#ifdef DEBUG_SAX
2695    xmlGenericError(xmlGenericErrorContext,
2696	    "SAX.pcdata(%.10s, %d)\n", value, len);
2697#endif
2698    lastChild = xmlGetLastChild(ctxt->node);
2699#ifdef DEBUG_SAX_TREE
2700    xmlGenericError(xmlGenericErrorContext,
2701	    "add chars to %s \n", ctxt->node->name);
2702#endif
2703    if ((lastChild != NULL) &&
2704        (lastChild->type == XML_CDATA_SECTION_NODE)) {
2705	xmlTextConcat(lastChild, value, len);
2706    } else {
2707	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
2708	xmlAddChild(ctxt->node, ret);
2709    }
2710}
2711
2712static int xmlSAX2DefaultVersionValue = 2;
2713
2714#ifdef LIBXML_SAX1_ENABLED
2715/**
2716 * xmlSAXDefaultVersion:
2717 * @version:  the version, 1 or 2
2718 *
2719 * Set the default version of SAX used globally by the library.
2720 * By default, during initialization the default is set to 2.
2721 * Note that it is generally a better coding style to use
2722 * xmlSAXVersion() to set up the version explicitly for a given
2723 * parsing context.
2724 *
2725 * Returns the previous value in case of success and -1 in case of error.
2726 */
2727int
2728xmlSAXDefaultVersion(int version)
2729{
2730    int ret = xmlSAX2DefaultVersionValue;
2731
2732    if ((version != 1) && (version != 2))
2733        return(-1);
2734    xmlSAX2DefaultVersionValue = version;
2735    return(ret);
2736}
2737#endif /* LIBXML_SAX1_ENABLED */
2738
2739/**
2740 * xmlSAXVersion:
2741 * @hdlr:  the SAX handler
2742 * @version:  the version, 1 or 2
2743 *
2744 * Initialize the default XML SAX handler according to the version
2745 *
2746 * Returns 0 in case of success and -1 in case of error.
2747 */
2748int
2749xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2750{
2751    if (hdlr == NULL) return(-1);
2752    if (version == 2) {
2753	hdlr->startElement = NULL;
2754	hdlr->endElement = NULL;
2755	hdlr->startElementNs = xmlSAX2StartElementNs;
2756	hdlr->endElementNs = xmlSAX2EndElementNs;
2757	hdlr->serror = NULL;
2758	hdlr->initialized = XML_SAX2_MAGIC;
2759#ifdef LIBXML_SAX1_ENABLED
2760    } else if (version == 1) {
2761	hdlr->startElement = xmlSAX2StartElement;
2762	hdlr->endElement = xmlSAX2EndElement;
2763	hdlr->initialized = 1;
2764#endif /* LIBXML_SAX1_ENABLED */
2765    } else
2766        return(-1);
2767    hdlr->internalSubset = xmlSAX2InternalSubset;
2768    hdlr->externalSubset = xmlSAX2ExternalSubset;
2769    hdlr->isStandalone = xmlSAX2IsStandalone;
2770    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2771    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2772    hdlr->resolveEntity = xmlSAX2ResolveEntity;
2773    hdlr->getEntity = xmlSAX2GetEntity;
2774    hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2775    hdlr->entityDecl = xmlSAX2EntityDecl;
2776    hdlr->attributeDecl = xmlSAX2AttributeDecl;
2777    hdlr->elementDecl = xmlSAX2ElementDecl;
2778    hdlr->notationDecl = xmlSAX2NotationDecl;
2779    hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2780    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2781    hdlr->startDocument = xmlSAX2StartDocument;
2782    hdlr->endDocument = xmlSAX2EndDocument;
2783    hdlr->reference = xmlSAX2Reference;
2784    hdlr->characters = xmlSAX2Characters;
2785    hdlr->cdataBlock = xmlSAX2CDataBlock;
2786    hdlr->ignorableWhitespace = xmlSAX2Characters;
2787    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2788    hdlr->comment = xmlSAX2Comment;
2789    hdlr->warning = xmlParserWarning;
2790    hdlr->error = xmlParserError;
2791    hdlr->fatalError = xmlParserError;
2792
2793    return(0);
2794}
2795
2796/**
2797 * xmlSAX2InitDefaultSAXHandler:
2798 * @hdlr:  the SAX handler
2799 * @warning:  flag if non-zero sets the handler warning procedure
2800 *
2801 * Initialize the default XML SAX2 handler
2802 */
2803void
2804xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2805{
2806    if ((hdlr == NULL) || (hdlr->initialized != 0))
2807	return;
2808
2809    xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2810    if (warning == 0)
2811	hdlr->warning = NULL;
2812    else
2813	hdlr->warning = xmlParserWarning;
2814}
2815
2816/**
2817 * xmlDefaultSAXHandlerInit:
2818 *
2819 * Initialize the default SAX2 handler
2820 */
2821void
2822xmlDefaultSAXHandlerInit(void)
2823{
2824#ifdef LIBXML_SAX1_ENABLED
2825    xmlSAXVersion((xmlSAXHandlerPtr) &xmlDefaultSAXHandler, 1);
2826#endif /* LIBXML_SAX1_ENABLED */
2827}
2828
2829#ifdef LIBXML_HTML_ENABLED
2830
2831/**
2832 * xmlSAX2InitHtmlDefaultSAXHandler:
2833 * @hdlr:  the SAX handler
2834 *
2835 * Initialize the default HTML SAX2 handler
2836 */
2837void
2838xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2839{
2840    if ((hdlr == NULL) || (hdlr->initialized != 0))
2841	return;
2842
2843    hdlr->internalSubset = xmlSAX2InternalSubset;
2844    hdlr->externalSubset = NULL;
2845    hdlr->isStandalone = NULL;
2846    hdlr->hasInternalSubset = NULL;
2847    hdlr->hasExternalSubset = NULL;
2848    hdlr->resolveEntity = NULL;
2849    hdlr->getEntity = xmlSAX2GetEntity;
2850    hdlr->getParameterEntity = NULL;
2851    hdlr->entityDecl = NULL;
2852    hdlr->attributeDecl = NULL;
2853    hdlr->elementDecl = NULL;
2854    hdlr->notationDecl = NULL;
2855    hdlr->unparsedEntityDecl = NULL;
2856    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2857    hdlr->startDocument = xmlSAX2StartDocument;
2858    hdlr->endDocument = xmlSAX2EndDocument;
2859    hdlr->startElement = xmlSAX2StartElement;
2860    hdlr->endElement = xmlSAX2EndElement;
2861    hdlr->reference = NULL;
2862    hdlr->characters = xmlSAX2Characters;
2863    hdlr->cdataBlock = xmlSAX2CDataBlock;
2864    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2865    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2866    hdlr->comment = xmlSAX2Comment;
2867    hdlr->warning = xmlParserWarning;
2868    hdlr->error = xmlParserError;
2869    hdlr->fatalError = xmlParserError;
2870
2871    hdlr->initialized = 1;
2872}
2873
2874/**
2875 * htmlDefaultSAXHandlerInit:
2876 *
2877 * Initialize the default SAX handler
2878 */
2879void
2880htmlDefaultSAXHandlerInit(void)
2881{
2882    xmlSAX2InitHtmlDefaultSAXHandler((xmlSAXHandlerPtr) &htmlDefaultSAXHandler);
2883}
2884
2885#endif /* LIBXML_HTML_ENABLED */
2886
2887#ifdef LIBXML_DOCB_ENABLED
2888
2889/**
2890 * xmlSAX2InitDocbDefaultSAXHandler:
2891 * @hdlr:  the SAX handler
2892 *
2893 * Initialize the default DocBook SAX2 handler
2894 */
2895void
2896xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
2897{
2898    if ((hdlr == NULL) || (hdlr->initialized != 0))
2899	return;
2900
2901    hdlr->internalSubset = xmlSAX2InternalSubset;
2902    hdlr->externalSubset = NULL;
2903    hdlr->isStandalone = xmlSAX2IsStandalone;
2904    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2905    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2906    hdlr->resolveEntity = xmlSAX2ResolveEntity;
2907    hdlr->getEntity = xmlSAX2GetEntity;
2908    hdlr->getParameterEntity = NULL;
2909    hdlr->entityDecl = xmlSAX2EntityDecl;
2910    hdlr->attributeDecl = NULL;
2911    hdlr->elementDecl = NULL;
2912    hdlr->notationDecl = NULL;
2913    hdlr->unparsedEntityDecl = NULL;
2914    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2915    hdlr->startDocument = xmlSAX2StartDocument;
2916    hdlr->endDocument = xmlSAX2EndDocument;
2917    hdlr->startElement = xmlSAX2StartElement;
2918    hdlr->endElement = xmlSAX2EndElement;
2919    hdlr->reference = xmlSAX2Reference;
2920    hdlr->characters = xmlSAX2Characters;
2921    hdlr->cdataBlock = NULL;
2922    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2923    hdlr->processingInstruction = NULL;
2924    hdlr->comment = xmlSAX2Comment;
2925    hdlr->warning = xmlParserWarning;
2926    hdlr->error = xmlParserError;
2927    hdlr->fatalError = xmlParserError;
2928
2929    hdlr->initialized = 1;
2930}
2931
2932/**
2933 * docbDefaultSAXHandlerInit:
2934 *
2935 * Initialize the default SAX handler
2936 */
2937void
2938docbDefaultSAXHandlerInit(void)
2939{
2940    xmlSAX2InitDocbDefaultSAXHandler((xmlSAXHandlerPtr) &docbDefaultSAXHandler);
2941}
2942
2943#endif /* LIBXML_DOCB_ENABLED */
2944#define bottom_SAX2
2945#include "elfgcchack.h"
2946