Adding new version of the SAX interface, it's not there yet, currently

* Makefile.am SAX2.c include/libxml/Makefile.am include/libxml/SAX2.h:
  Adding new version of the SAX interface, it's not there yet,
  currently just preparing the work
* globals.c parser.c SAX.c include/libxml/SAX.h
  include/libxml/globals.h include/libxml/parser.h: doing some
  refactoring of the SAXv1 interfaces, obsoleting a bunch of them
  while keeping functionalities, preparing SAX2 integration.
* dict.c: small cleanup.
Daniel
diff --git a/ChangeLog b/ChangeLog
index 25cf243..7a2e1c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Thu Aug 21 00:50:32 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+	* Makefile.am SAX2.c include/libxml/Makefile.am include/libxml/SAX2.h:
+	  Adding new version of the SAX interface, it's not there yet,
+	  currently just preparing the work
+	* globals.c parser.c SAX.c include/libxml/SAX.h 
+	  include/libxml/globals.h include/libxml/parser.h: doing some
+	  refactoring of the SAXv1 interfaces, obsoleting a bunch of them
+	  while keeping functionalities, preparing SAX2 integration.
+	* dict.c: small cleanup.
+
 Wed Aug 20 00:20:01 CEST 2003 Daniel Veillard <daniel@veillard.com>
 
 	* tree.c: fixes a small bug introduced in last commit and detected
diff --git a/Makefile.am b/Makefile.am
index cbd8ddd..434735d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,7 +26,7 @@
 		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
 		catalog.c globals.c threads.c c14n.c \
 		xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \
-		triostr.c trio.c xmlreader.c relaxng.c dict.c
+		triostr.c trio.c xmlreader.c relaxng.c dict.c SAX2.c
 else
 libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c  \
 		parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c  \
@@ -34,7 +34,7 @@
 		xpointer.c xinclude.c nanohttp.c nanoftp.c DOCBparser.c \
 		catalog.c globals.c threads.c c14n.c \
 		xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \
-		xmlreader.c relaxng.c dict.c
+		xmlreader.c relaxng.c dict.c SAX2.c
 endif
 
 DEPS = $(top_builddir)/libxml2.la
diff --git a/SAX.c b/SAX.c
index 3f62894..4d2cdd5 100644
--- a/SAX.c
+++ b/SAX.c
@@ -1,5 +1,6 @@
 /*
- * SAX.c : Default SAX handler to build a tree.
+ * SAX.c : Old SAX v1 handlers to build a tree.
+ *         Deprecated except for compatibility
  *
  * See Copyright for the status of this software.
  *
@@ -25,6 +26,7 @@
 #include <libxml/valid.h>
 #include <libxml/HTMLtree.h>
 #include <libxml/globals.h>
+#include <libxml/SAX2.h>
 
 /* #define DEBUG_SAX */
 /* #define DEBUG_SAX_TREE */
@@ -34,14 +36,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
+ * DEPRECATED: use xmlSAX2GetPublicId()
  *
  * Returns a xmlChar *
  */
 const xmlChar *
-getPublicId(void *ctx ATTRIBUTE_UNUSED)
+getPublicId(void *ctx)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-    return(NULL);
+    return(xmlSAX2GetPublicId(ctx));
 }
 
 /**
@@ -50,14 +52,14 @@
  *
  * Provides the system ID, basically URL or filename e.g.
  * http://www.sgmlsource.com/dtds/memo.dtd
+ * DEPRECATED: use xmlSAX2GetSystemId()
  *
  * Returns a xmlChar *
  */
 const xmlChar *
 getSystemId(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return((const xmlChar *) ctxt->input->filename); 
+    return(xmlSAX2GetSystemId(ctx)); 
 }
 
 /**
@@ -65,14 +67,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Provide the line number of the current parsing point.
+ * DEPRECATED: use xmlSAX2GetLineNumber()
  *
  * Returns an int
  */
 int
 getLineNumber(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return(ctxt->input->line);
+    return(xmlSAX2GetLineNumber(ctx));
 }
 
 /**
@@ -80,14 +82,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Provide the column number of the current parsing point.
+ * DEPRECATED: use xmlSAX2GetColumnNumber()
  *
  * Returns an int
  */
 int
 getColumnNumber(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return(ctxt->input->col);
+    return(xmlSAX2GetColumnNumber(ctx));
 }
 
 /**
@@ -95,14 +97,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Is this document tagged standalone ?
+ * DEPRECATED: use xmlSAX2IsStandalone()
  *
  * Returns 1 if true
  */
 int
 isStandalone(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return(ctxt->myDoc->standalone == 1);
+    return(xmlSAX2IsStandalone(ctx));
 }
 
 /**
@@ -110,14 +112,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Does this document has an internal subset
+ * DEPRECATED: use xmlSAX2HasInternalSubset()
  *
  * Returns 1 if true
  */
 int
 hasInternalSubset(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return(ctxt->myDoc->intSubset != NULL);
+    return(xmlSAX2HasInternalSubset(ctx));
 }
 
 /**
@@ -125,14 +127,14 @@
  * @ctx: the user data (XML parser context)
  *
  * Does this document has an external subset
+ * DEPRECATED: use xmlSAX2HasExternalSubset()
  *
  * Returns 1 if true
  */
 int
 hasExternalSubset(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    return(ctxt->myDoc->extSubset != NULL);
+    return(xmlSAX2HasExternalSubset(ctx));
 }
 
 /**
@@ -143,31 +145,13 @@
  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
  *
  * Callback on internal subset declaration.
+ * DEPRECATED: use xmlSAX2InternalSubset()
  */
 void
 internalSubset(void *ctx, const xmlChar *name,
 	       const xmlChar *ExternalID, const xmlChar *SystemID)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlDtdPtr dtd;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.internalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
-
-    if (ctxt->myDoc == NULL)
-	return;
-    dtd = xmlGetIntSubset(ctxt->myDoc);
-    if (dtd != NULL) {
-	if (ctxt->html)
-	    return;
-	xmlUnlinkNode((xmlNodePtr) dtd);
-	xmlFreeDtd(dtd);
-	ctxt->myDoc->intSubset = NULL;
-    }
-    ctxt->myDoc->intSubset = 
-	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
+    xmlSAX2InternalSubset(ctx, name, ExternalID, SystemID);
 }
 
 /**
@@ -178,114 +162,13 @@
  * @SystemID:  the SYSTEM ID (e.g. filename or URL)
  *
  * Callback on external subset declaration.
+ * DEPRECATED: use xmlSAX2ExternalSubset()
  */
 void
 externalSubset(void *ctx, const xmlChar *name,
 	       const xmlChar *ExternalID, const xmlChar *SystemID)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.externalSubset(%s, %s, %s)\n",
-            name, ExternalID, SystemID);
-#endif
-    if (((ExternalID != NULL) || (SystemID != NULL)) &&
-        (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
-	 (ctxt->wellFormed && ctxt->myDoc))) {
-	/*
-	 * Try to fetch and parse the external subset.
-	 */
-	xmlParserInputPtr oldinput;
-	int oldinputNr;
-	int oldinputMax;
-	xmlParserInputPtr *oldinputTab;
-	xmlParserInputPtr input = NULL;
-	xmlCharEncoding enc;
-	int oldcharset;
-
-	/*
-	 * Ask the Entity resolver to load the damn thing
-	 */
-	if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
-	    input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
-	                                        SystemID);
-	if (input == NULL) {
-	    return;
-	}
-
-	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
-
-	/*
-	 * make sure we won't destroy the main document context
-	 */
-	oldinput = ctxt->input;
-	oldinputNr = ctxt->inputNr;
-	oldinputMax = ctxt->inputMax;
-	oldinputTab = ctxt->inputTab;
-	oldcharset = ctxt->charset;
-
-	ctxt->inputTab = (xmlParserInputPtr *)
-	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
-	if (ctxt->inputTab == NULL) {
-	    ctxt->errNo = XML_ERR_NO_MEMORY;
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData, 
-		     "externalSubset: out of memory\n");
-	    ctxt->errNo = XML_ERR_NO_MEMORY;
-	    ctxt->instate = XML_PARSER_EOF;
-	    ctxt->disableSAX = 1;
-	    ctxt->input = oldinput;
-	    ctxt->inputNr = oldinputNr;
-	    ctxt->inputMax = oldinputMax;
-	    ctxt->inputTab = oldinputTab;
-	    ctxt->charset = oldcharset;
-	    return;
-	}
-	ctxt->inputNr = 0;
-	ctxt->inputMax = 5;
-	ctxt->input = NULL;
-	xmlPushInput(ctxt, input);
-
-	/*
-	 * On the fly encoding conversion if needed
-	 */
-	if (ctxt->input->length >= 4) {
-	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
-	    xmlSwitchEncoding(ctxt, enc);
-	}
-
-	if (input->filename == NULL)
-	    input->filename = (char *) xmlCanonicPath(SystemID);
-	input->line = 1;
-	input->col = 1;
-	input->base = ctxt->input->cur;
-	input->cur = ctxt->input->cur;
-	input->free = NULL;
-
-	/*
-	 * let's parse that entity knowing it's an external subset.
-	 */
-	xmlParseExternalSubset(ctxt, ExternalID, SystemID);
-
-        /*
-	 * Free up the external entities
-	 */
-
-	while (ctxt->inputNr > 1)
-	    xmlPopInput(ctxt);
-	xmlFreeInputStream(ctxt->input);
-        xmlFree(ctxt->inputTab);
-
-	/*
-	 * Restore the parsing context of the main entity
-	 */
-	ctxt->input = oldinput;
-	ctxt->inputNr = oldinputNr;
-	ctxt->inputMax = oldinputMax;
-	ctxt->inputTab = oldinputTab;
-	ctxt->charset = oldcharset;
-	/* ctxt->wellFormed = oldwellFormed; */
-    }
+    xmlSAX2ExternalSubset(ctx, name, ExternalID, SystemID);
 }
 
 /**
@@ -299,34 +182,14 @@
  *    - override this resolveEntity() callback in the SAX block
  *    - or better use the xmlSetExternalEntityLoader() function to
  *      set up it's own entity resolution routine
+ * DEPRECATED: use xmlSAX2ResolveEntity()
  *
  * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
  */
 xmlParserInputPtr
 resolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserInputPtr ret;
-    xmlChar *URI;
-    const char *base = NULL;
-
-    if (ctxt->input != NULL)
-	base = ctxt->input->filename;
-    if (base == NULL)
-	base = ctxt->directory;
-
-    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
-#endif
-
-    ret = xmlLoadExternalEntity((const char *) URI,
-				(const char *) publicId, ctxt);
-    if (URI != NULL)
-	xmlFree(URI);
-    return(ret);
+    return(xmlSAX2ResolveEntity(ctx, publicId, systemId));
 }
 
 /**
@@ -335,76 +198,14 @@
  * @name: The entity name
  *
  * Get an entity by name
+ * DEPRECATED: use xmlSAX2GetEntity()
  *
  * Returns the xmlEntityPtr if found.
  */
 xmlEntityPtr
 getEntity(void *ctx, const xmlChar *name)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlEntityPtr ret = NULL;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.getEntity(%s)\n", name);
-#endif
-
-    if (ctxt->inSubset == 0) {
-	ret = xmlGetPredefinedEntity(name);
-	if (ret != NULL)
-	    return(ret);
-    }
-    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
-	if (ctxt->inSubset == 2) {
-	    ctxt->myDoc->standalone = 0;
-	    ret = xmlGetDocEntity(ctxt->myDoc, name);
-	    ctxt->myDoc->standalone = 1;
-	} else {
-	    ret = xmlGetDocEntity(ctxt->myDoc, name);
-	    if (ret == NULL) {
-		ctxt->myDoc->standalone = 0;
-		ret = xmlGetDocEntity(ctxt->myDoc, name);
-		if (ret != NULL) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-			ctxt->sax->error(ctxt, 
-		 "Entity(%s) document marked standalone but require external subset\n",
-					 name);
-		    ctxt->valid = 0;
-		    ctxt->wellFormed = 0;
-		}
-		ctxt->myDoc->standalone = 1;
-	    }
-	}
-    } else {
-	ret = xmlGetDocEntity(ctxt->myDoc, name);
-    }
-    if ((ret != NULL) &&
-	((ctxt->validate) || (ctxt->replaceEntities)) &&
-	(ret->children == NULL) &&
-	(ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
-	int val;
-
-	/*
-	 * for validation purposes we really need to fetch and
-	 * parse the external entity
-	 */
-	xmlNodePtr children;
-
-        val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
-		                         ret->ExternalID, &children);
-	if (val == 0) {
-	    xmlAddChildList((xmlNodePtr) ret, children);
-	} else {
-	    ctxt->sax->error(ctxt, 
-	     "Failure to process entity %s\n", name);
-	    ctxt->wellFormed = 0;
-	    ctxt->valid = 0;
-	    ctxt->validate = 0;
-	    return(NULL);
-	}
-	ret->owner = 1;
-    }
-    return(ret);
+    return(xmlSAX2GetEntity(ctx, name));
 }
 
 /**
@@ -413,22 +214,14 @@
  * @name: The entity name
  *
  * Get a parameter entity by name
+ * DEPRECATED: use xmlSAX2GetParameterEntity()
  *
  * Returns the xmlEntityPtr if found.
  */
 xmlEntityPtr
 getParameterEntity(void *ctx, const xmlChar *name)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlEntityPtr ret;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.getParameterEntity(%s)\n", name);
-#endif
-
-    ret = xmlGetParameterEntity(ctxt->myDoc, name);
-    return(ret);
+    return(xmlSAX2GetParameterEntity(ctx, name));
 }
 
 
@@ -442,62 +235,13 @@
  * @content: the entity value (without processing).
  *
  * An entity definition has been parsed
+ * DEPRECATED: use xmlSAX2EntityDecl()
  */
 void
 entityDecl(void *ctx, const xmlChar *name, int type,
           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
 {
-    xmlEntityPtr ent;
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
-            name, type, publicId, systemId, content);
-#endif
-    if (ctxt->inSubset == 1) {
-	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
-		              systemId, content);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt, 
-	     "Entity(%s) already defined in the internal subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-	
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else if (ctxt->inSubset == 2) {
-	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
-		              systemId, content);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt, 
-	     "Entity(%s) already defined in the external subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-	
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	     "SAX.entityDecl(%s) called while not in subset\n", name);
-    }
+    xmlSAX2EntityDecl(ctx, name, type, publicId, systemId, content);
 }
 
 /**
@@ -511,47 +255,14 @@
  * @tree:  the tree of enumerated value set
  *
  * An attribute definition has been parsed
+ * DEPRECATED: use xmlSAX2AttributeDecl()
  */
 void
 attributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
               int type, int def, const xmlChar *defaultValue,
 	      xmlEnumerationPtr tree)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlAttributePtr attr;
-    xmlChar *name = NULL, *prefix = NULL;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
-            elem, fullname, type, def, defaultValue);
-#endif
-    name = xmlSplitQName(ctxt, fullname, &prefix);
-    ctxt->vctxt.valid = 1;
-    if (ctxt->inSubset == 1)
-	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
-	       name, prefix, (xmlAttributeType) type,
-	       (xmlAttributeDefault) def, defaultValue, tree);
-    else if (ctxt->inSubset == 2)
-	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
-	   name, prefix, (xmlAttributeType) type, 
-	   (xmlAttributeDefault) def, defaultValue, tree);
-    else {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	     "SAX.attributeDecl(%s) called while not in subset\n", name);
-	return;
-    }
-    if (ctxt->vctxt.valid == 0)
-	ctxt->valid = 0;
-    if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
-        (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
-	ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
-	                                        attr);
-    if (prefix != NULL)
-	xmlFree(prefix);
-    if (name != NULL)
-	xmlFree(name);
+    xmlSAX2AttributeDecl(ctx, elem, fullname, type, def, defaultValue, tree);
 }
 
 /**
@@ -562,38 +273,13 @@
  * @content: the element value tree
  *
  * An element definition has been parsed
+ * DEPRECATED: use xmlSAX2ElementDecl()
  */
 void
 elementDecl(void *ctx, const xmlChar * name, int type,
             xmlElementContentPtr content)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlElementPtr elem = NULL;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-                    "SAX.elementDecl(%s, %d, ...)\n", name, type);
-#endif
-
-    if (ctxt->inSubset == 1)
-        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
-                                 name, (xmlElementTypeVal) type, content);
-    else if (ctxt->inSubset == 2)
-        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
-                                 name, (xmlElementTypeVal) type, content);
-    else {
-        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-            ctxt->sax->error(ctxt,
-                             "SAX.elementDecl(%s) called while not in subset\n",
-                             name);
-        return;
-    }
-    if (elem == NULL)
-        ctxt->valid = 0;
-    if (ctxt->validate && ctxt->wellFormed &&
-        ctxt->myDoc && ctxt->myDoc->intSubset)
-        ctxt->valid &=
-            xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
+    xmlSAX2ElementDecl(ctx, name, type, content);
 }
 
 /**
@@ -604,43 +290,13 @@
  * @systemId: The system ID of the entity
  *
  * What to do when a notation declaration has been parsed.
+ * DEPRECATED: use xmlSAX2NotationDecl()
  */
 void
 notationDecl(void *ctx, const xmlChar *name,
 	     const xmlChar *publicId, const xmlChar *systemId)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNotationPtr nota = NULL;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
-#endif
-
-    if ((publicId == NULL) && (systemId == NULL)) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	     "SAX.notationDecl(%s) externalID or PublicID missing\n", name);
-	ctxt->valid = 0;
-	ctxt->wellFormed = 0;
-	return;
-    } else if (ctxt->inSubset == 1)
-	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
-                              publicId, systemId);
-    else if (ctxt->inSubset == 2)
-	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
-                              publicId, systemId);
-    else {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	     "SAX.notationDecl(%s) called while not in subset\n", name);
-	return;
-    }
-    if (nota == NULL) ctxt->valid = 0;
-    if (ctxt->validate && ctxt->wellFormed &&
-        ctxt->myDoc && ctxt->myDoc->intSubset)
-	ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
-	                                       nota);
+    xmlSAX2NotationDecl(ctx, name, publicId, systemId);
 }
 
 /**
@@ -652,64 +308,14 @@
  * @notationName: the name of the notation
  *
  * What to do when an unparsed entity declaration is parsed
+ * DEPRECATED: use xmlSAX2UnparsedEntityDecl()
  */
 void
 unparsedEntityDecl(void *ctx, const xmlChar *name,
 		   const xmlChar *publicId, const xmlChar *systemId,
 		   const xmlChar *notationName)
 {
-    xmlEntityPtr ent;
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
-            name, publicId, systemId, notationName);
-#endif
-    if (ctxt->inSubset == 1) {
-	ent = xmlAddDocEntity(ctxt->myDoc, name,
-			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
-			publicId, systemId, notationName);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt, 
-	     "Entity(%s) already defined in the internal subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-	
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else if (ctxt->inSubset == 2) {
-	ent = xmlAddDtdEntity(ctxt->myDoc, name,
-			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
-			publicId, systemId, notationName);
-	if ((ent == NULL) && (ctxt->pedantic) &&
-	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt, 
-	     "Entity(%s) already defined in the external subset\n", name);
-	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
-	    xmlChar *URI;
-	    const char *base = NULL;
-
-	    if (ctxt->input != NULL)
-		base = ctxt->input->filename;
-	    if (base == NULL)
-		base = ctxt->directory;
-	
-	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
-	    ent->URI = URI;
-	}
-    } else {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	     "SAX.unparsedEntityDecl(%s) called while not in subset\n", name);
-    }
+    xmlSAX2UnparsedEntityDecl(ctx, name, publicId, systemId, notationName);
 }
 
 /**
@@ -719,15 +325,11 @@
  *
  * Receive the document locator at startup, actually xmlDefaultSAXLocator
  * Everything is available on the context, so this is useless in our case.
+ * DEPRECATED
  */
 void
 setDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.setDocumentLocator()\n");
-#endif
 }
 
 /**
@@ -735,62 +337,12 @@
  * @ctx: the user data (XML parser context)
  *
  * called when the document start being processed.
+ * DEPRECATED: use xmlSAX2StartDocument()
  */
 void
 startDocument(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlDocPtr doc;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.startDocument()\n");
-#endif
-    if (ctxt->html) {
-#ifdef LIBXML_HTML_ENABLED
-	if (ctxt->myDoc == NULL)
-	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
-	if (ctxt->myDoc == NULL) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData, 
-		     "SAX.startDocument(): out of memory\n");
-	    ctxt->errNo = XML_ERR_NO_MEMORY;
-	    ctxt->instate = XML_PARSER_EOF;
-	    ctxt->disableSAX = 1;
-	    return;
-	}
-#else
-        xmlGenericError(xmlGenericErrorContext,
-		"libxml2 built without HTML support\n");
-	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
-	ctxt->instate = XML_PARSER_EOF;
-	ctxt->disableSAX = 1;
-	return;
-#endif
-    } else {
-	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
-	if (doc != NULL) {
-	    if (ctxt->encoding != NULL)
-		doc->encoding = xmlStrdup(ctxt->encoding);
-	    else
-		doc->encoding = NULL;
-	    doc->standalone = ctxt->standalone;
-	} else {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData, 
-		     "SAX.startDocument(): out of memory\n");
-	    ctxt->errNo = XML_ERR_NO_MEMORY;
-	    ctxt->instate = XML_PARSER_EOF;
-	    ctxt->disableSAX = 1;
-	    return;
-	}
-    }
-    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
-	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
-	ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
-	if (ctxt->myDoc->URL == NULL)
-	    ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
-    }
+    xmlSAX2StartDocument(ctx);
 }
 
 /**
@@ -798,346 +350,12 @@
  * @ctx: the user data (XML parser context)
  *
  * called when the document end has been detected.
+ * DEPRECATED: use xmlSAX2EndDocument()
  */
 void
 endDocument(void *ctx)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.endDocument()\n");
-#endif
-    if (ctxt->validate && ctxt->wellFormed &&
-        ctxt->myDoc && ctxt->myDoc->intSubset)
-	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
-
-    /*
-     * Grab the encoding if it was added on-the-fly
-     */
-    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = ctxt->encoding;
-	ctxt->encoding = NULL;
-    }
-    if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->encoding == NULL)) {
-	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
-    }
-    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
-	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
-	ctxt->myDoc->charset = ctxt->charset;
-    }
-}
-
-/**
- * my_attribute:
- * @ctx: the user data (XML parser context)
- * @fullname:  The attribute name, including namespace prefix
- * @value:  The attribute value
- * @prefix: the prefix on the element node
- *
- * Handle an attribute that has been read by the parser.
- * The default handling is to convert the attribute into an
- * DOM subtree and past it in a new xmlAttr element added to
- * the element.
- */
-static void
-my_attribute(void *ctx, const xmlChar *fullname, const xmlChar *value,
-	     const xmlChar *prefix)
-{
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlAttrPtr ret;
-    xmlChar *name;
-    xmlChar *ns;
-    xmlChar *nval;
-    xmlNsPtr namespace;
-
-/****************
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-    "SAX.attribute(%s, %s)\n", fullname, value);
-#endif
- ****************/
-    /*
-     * Split the full name into a namespace prefix and the tag name
-     */
-    name = xmlSplitQName(ctxt, fullname, &ns);
-    if ((name != NULL) && (name[0] == 0)) {
-        if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData, 
-		     "invalid namespace declaration '%s'\n", fullname);
-	} else {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-		ctxt->sax->warning(ctxt->userData, 
-		     "Avoid attribute ending with ':' like '%s'\n", fullname);
-	}
-	if (ns != NULL)
-	    xmlFree(ns);
-	ns = NULL;
-	xmlFree(name);
-	name = xmlStrdup(fullname);
-    }
-    if (name == NULL) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt->userData, 
-		 "SAX.startElement(): out of memory\n");
-	ctxt->errNo = XML_ERR_NO_MEMORY;
-	ctxt->instate = XML_PARSER_EOF;
-	ctxt->disableSAX = 1;
-	if (ns != NULL)
-	    xmlFree(ns);
-	return;
-    }
-
-    /*
-     * Do the last stage of the attribute normalization
-     * Needed for HTML too:
-     *   http://www.w3.org/TR/html4/types.html#h-6.2
-     */
-    ctxt->vctxt.valid = 1;
-    nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
-	                                   ctxt->myDoc, ctxt->node,
-					   fullname, value);
-    if (ctxt->vctxt.valid != 1) {
-	ctxt->valid = 0;
-    }
-    if (nval != NULL)
-	value = nval;
-
-    /*
-     * Check whether it's a namespace definition
-     */
-    if ((!ctxt->html) && (ns == NULL) &&
-        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
-        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
-	xmlNsPtr nsret;
-	xmlChar *val;
-
-        if (!ctxt->replaceEntities) {
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
-	} else {
-	    val = (xmlChar *) value;
-	}
-
-	if (val[0] != 0) {
-	    xmlURIPtr uri;
-
-	    uri = xmlParseURI((const char *)val);
-	    if (uri == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-		    ctxt->sax->warning(ctxt->userData, 
-			 "nmlns: %s not a valid URI\n", val);
-	    } else {
-		if (uri->scheme == NULL) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-			ctxt->sax->warning(ctxt->userData, 
-			     "xmlns: URI %s is not absolute\n", val);
-		}
-		xmlFreeURI(uri);
-	    }
-	}
-
-	/* a default namespace definition */
-	nsret = xmlNewNs(ctxt->node, val, NULL);
-
-	/*
-	 * Validate also for namespace decls, they are attributes from
-	 * an XML-1.0 perspective
-	 */
-        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
-	    ctxt->myDoc && ctxt->myDoc->intSubset)
-	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
-					   ctxt->node, prefix, nsret, val);
-	if (name != NULL) 
-	    xmlFree(name);
-	if (nval != NULL)
-	    xmlFree(nval);
-	if (val != value)
-	    xmlFree(val);
-	return;
-    }
-    if ((!ctxt->html) &&
-	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
-        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
-	xmlNsPtr nsret;
-	xmlChar *val;
-
-        if (!ctxt->replaceEntities) {
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
-	    if (val == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		    ctxt->sax->error(ctxt->userData, 
-			 "SAX.startElement(): out of memory\n");
-		ctxt->errNo = XML_ERR_NO_MEMORY;
-		ctxt->instate = XML_PARSER_EOF;
-		ctxt->disableSAX = 1;
-	        xmlFree(ns);
-		if (name != NULL) 
-		    xmlFree(name);
-		return;
-	    }
-	} else {
-	    val = (xmlChar *) value;
-	}
-
-	if (val[0] == 0) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt->userData, 
-		     "Empty namespace name for prefix %s\n", name);
-	}
-	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
-	    xmlURIPtr uri;
-
-	    uri = xmlParseURI((const char *)val);
-	    if (uri == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-		    ctxt->sax->warning(ctxt->userData, 
-			 "xmlns:%s: %s not a valid URI\n", name, value);
-	    } else {
-		if (uri->scheme == NULL) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-			ctxt->sax->warning(ctxt->userData, 
-			   "xmlns:%s: URI %s is not absolute\n", name, value);
-		}
-		xmlFreeURI(uri);
-	    }
-	}
-
-	/* a standard namespace definition */
-	nsret = xmlNewNs(ctxt->node, val, name);
-	xmlFree(ns);
-	/*
-	 * Validate also for namespace decls, they are attributes from
-	 * an XML-1.0 perspective
-	 */
-        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
-	    ctxt->myDoc && ctxt->myDoc->intSubset)
-	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
-					   ctxt->node, prefix, nsret, value);
-	if (name != NULL) 
-	    xmlFree(name);
-	if (nval != NULL)
-	    xmlFree(nval);
-	if (val != value)
-	    xmlFree(val);
-	return;
-    }
-
-    if (ns != NULL) {
-	xmlAttrPtr prop;
-	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
-
-	prop = ctxt->node->properties;
-	while (prop != NULL) {
-	    if (prop->ns != NULL) {
-		if ((xmlStrEqual(name, prop->name)) &&
-		    ((namespace == prop->ns) ||
-		     (xmlStrEqual(namespace->href, prop->ns->href)))) {
-		    ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
-		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-			ctxt->sax->error(ctxt->userData,
-			        "Attribute %s in %s redefined\n",
-			                 name, namespace->href);
-		    ctxt->wellFormed = 0;
-		    if (ctxt->recovery == 0) ctxt->disableSAX = 1;
-		    goto error;
-		}
-	    }
-	    prop = prop->next;
-	}
-    } else {
-	namespace = NULL;
-    }
-
-    /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
-    ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
-
-    if (ret != NULL) {
-        if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
-	    xmlNodePtr tmp;
-
-	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
-	    tmp = ret->children;
-	    while (tmp != NULL) {
-		tmp->parent = (xmlNodePtr) ret;
-		if (tmp->next == NULL)
-		    ret->last = tmp;
-		tmp = tmp->next;
-	    }
-	} else if (value != NULL) {
-	    ret->children = xmlNewDocText(ctxt->myDoc, value);
-	    ret->last = ret->children;
-	    if (ret->children != NULL)
-		ret->children->parent = (xmlNodePtr) ret;
-	}
-    }
-
-    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
-        ctxt->myDoc && ctxt->myDoc->intSubset) {
-	
-	/*
-	 * If we don't substitute entities, the validation should be
-	 * done on a value with replaced entities anyway.
-	 */
-        if (!ctxt->replaceEntities) {
-	    xmlChar *val;
-
-	    ctxt->depth++;
-	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
-		                          0,0,0);
-	    ctxt->depth--;
-	    
-	    if (val == NULL)
-		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
-				ctxt->myDoc, ctxt->node, ret, value);
-	    else {
-		xmlChar *nvalnorm;
-
-		/*
-		 * Do the last stage of the attribute normalization
-		 * It need to be done twice ... it's an extra burden related
-		 * to the ability to keep references in attributes
-		 */
-		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
-					    ctxt->node, fullname, val);
-		if (nvalnorm != NULL) {
-		    xmlFree(val);
-		    val = nvalnorm;
-		}
-
-		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
-			        ctxt->myDoc, ctxt->node, ret, val);
-                xmlFree(val);
-	    }
-	} else {
-	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
-					       ctxt->node, ret, value);
-	}
-    } else if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
-	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
-	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
-        /*
-	 * when validating, the ID registration is done at the attribute
-	 * validation level. Otherwise we have to do specific handling here.
-	 */
-	if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
-	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
-	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
-    }
-
-error:
-    if (nval != NULL)
-	xmlFree(nval);
-    if (ns != NULL) 
-	xmlFree(ns);
+    xmlSAX2EndDocument(ctx);
 }
 
 /**
@@ -1150,166 +368,11 @@
  * The default handling is to convert the attribute into an
  * DOM subtree and past it in a new xmlAttr element added to
  * the element.
+ * DEPRECATED: use xmlSAX2Attribute()
  */
 void
-attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
+attribute(void *ctx ATTRIBUTE_UNUSED, const xmlChar *fullname ATTRIBUTE_UNUSED, const xmlChar *value ATTRIBUTE_UNUSED)
 {
-    my_attribute(ctx, fullname, value, NULL);
-}
-
-/*
- * xmlCheckDefaultedAttributes:
- *
- * Check defaulted attributes from the DTD
- */
-static void
-xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
-	const xmlChar *prefix, const xmlChar **atts) {
-    xmlElementPtr elemDecl;
-    const xmlChar *att;
-    int internal = 1;
-    int i;
-
-    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
-    if (elemDecl == NULL) {
-	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
-	internal = 0;
-    }
-
-process_external_subset:
-
-    if (elemDecl != NULL) {
-	xmlAttributePtr attr = elemDecl->attributes;
-	/*
-	 * Check against defaulted attributes from the external subset
-	 * if the document is stamped as standalone
-	 */
-	if ((ctxt->myDoc->standalone == 1) &&
-	    (ctxt->myDoc->extSubset != NULL) &&
-	    (ctxt->validate)) {
-	    while (attr != NULL) {
-		if ((attr->defaultValue != NULL) &&
-		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
-					attr->elem, attr->name,
-					attr->prefix) == attr) &&
-		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
-					attr->elem, attr->name,
-					attr->prefix) == NULL)) {
-		    xmlChar *fulln;
-
-		    if (attr->prefix != NULL) {
-			fulln = xmlStrdup(attr->prefix);
-			fulln = xmlStrcat(fulln, BAD_CAST ":");
-			fulln = xmlStrcat(fulln, attr->name);
-		    } else {
-			fulln = xmlStrdup(attr->name);
-		    }
-
-		    /*
-		     * Check that the attribute is not declared in the
-		     * serialization
-		     */
-		    att = NULL;
-		    if (atts != NULL) {
-			i = 0;
-			att = atts[i];
-			while (att != NULL) {
-			    if (xmlStrEqual(att, fulln))
-				break;
-			    i += 2;
-			    att = atts[i];
-			}
-		    }
-		    if (att == NULL) {
-			if (ctxt->vctxt.error != NULL)
-			    ctxt->vctxt.error(ctxt->vctxt.userData,
-      "standalone: attribute %s on %s defaulted from external subset\n",
-					      fulln, attr->elem);
-			ctxt->valid = 0;
-		    }
-		}
-		attr = attr->nexth;
-	    }
-	}
-
-	/*
-	 * Actually insert defaulted values when needed
-	 */
-	attr = elemDecl->attributes;
-	while (attr != NULL) {
-	    /*
-	     * Make sure that attributes redefinition occuring in the
-	     * internal subset are not overriden by definitions in the
-	     * external subset.
-	     */
-	    if (attr->defaultValue != NULL) {
-		/*
-		 * the element should be instantiated in the tree if:
-		 *  - this is a namespace prefix
-		 *  - the user required for completion in the tree
-		 *    like XSLT
-		 *  - there isn't already an attribute definition 
-		 *    in the internal subset overriding it.
-		 */
-		if (((attr->prefix != NULL) &&
-		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
-		    ((attr->prefix == NULL) &&
-		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
-		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
-		    xmlAttributePtr tst;
-
-		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
-					     attr->elem, attr->name,
-					     attr->prefix);
-		    if ((tst == attr) || (tst == NULL)) {
-		        xmlChar fn[50];
-			xmlChar *fulln;
-
-                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
-			if (fulln == NULL) {
-			    if ((ctxt->sax != NULL) &&
-			        (ctxt->sax->error != NULL))
-				ctxt->sax->error(ctxt->userData, 
-				     "SAX.startElement(): out of memory\n");
-			    ctxt->errNo = XML_ERR_NO_MEMORY;
-			    ctxt->instate = XML_PARSER_EOF;
-			    ctxt->disableSAX = 1;
-			    return;
-			}
-
-			/*
-			 * Check that the attribute is not declared in the
-			 * serialization
-			 */
-			att = NULL;
-			if (atts != NULL) {
-			    i = 0;
-			    att = atts[i];
-			    while (att != NULL) {
-				if (xmlStrEqual(att, fulln))
-				    break;
-				i += 2;
-				att = atts[i];
-			    }
-			}
-			if (att == NULL) {
-			    my_attribute(ctxt, fulln, attr->defaultValue,
-			                 prefix);
-			}
-			if ((fulln != fn) && (fulln != attr->name))
-			    xmlFree(fulln);
-		    }
-		}
-	    }
-	    attr = attr->nexth;
-	}
-	if (internal == 1) {
-	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
-		                             name, prefix);
-	    internal = 0;
-	    goto process_external_subset;
-	}
-    }
 }
 
 /**
@@ -1319,203 +382,12 @@
  * @atts:  An array of name/value attributes pairs, NULL terminated
  *
  * called when an opening tag has been processed.
+ * DEPRECATED: use xmlSAX2StartElement()
  */
 void
 startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr ret;
-    xmlNodePtr parent = ctxt->node;
-    xmlNsPtr ns;
-    xmlChar *name;
-    xmlChar *prefix;
-    const xmlChar *att;
-    const xmlChar *value;
-    int i;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.startElement(%s)\n", fullname);
-#endif
-
-    /*
-     * First check on validity:
-     */
-    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 
-        ((ctxt->myDoc->intSubset == NULL) ||
-	 ((ctxt->myDoc->intSubset->notations == NULL) && 
-	  (ctxt->myDoc->intSubset->elements == NULL) &&
-	  (ctxt->myDoc->intSubset->attributes == NULL) && 
-	  (ctxt->myDoc->intSubset->entities == NULL)))) {
-	if (ctxt->vctxt.error != NULL) {
-            ctxt->vctxt.error(ctxt->vctxt.userData,
-	      "Validation failed: no DTD found !\n");
-	}
-	ctxt->validate = 0;
-	ctxt->valid = 0;
-	ctxt->errNo = XML_ERR_NO_DTD;
-    }
-       
-
-    /*
-     * Split the full name into a namespace prefix and the tag name
-     */
-    name = xmlSplitQName(ctxt, fullname, &prefix);
-
-
-    /*
-     * Note : the namespace resolution is deferred until the end of the
-     *        attributes parsing, since local namespace can be defined as
-     *        an attribute at this level.
-     */
-    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
-    if (ret == NULL) {
-        if (prefix != NULL)
-	    xmlFree(prefix);
-	ctxt->errNo = XML_ERR_NO_MEMORY;
-	ctxt->instate = XML_PARSER_EOF;
-	ctxt->disableSAX = 1;
-        return;
-    }
-    if (ctxt->myDoc->children == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-    } else if (parent == NULL) {
-        parent = ctxt->myDoc->children;
-    }
-    ctxt->nodemem = -1;
-    if (ctxt->linenumbers) {
-	if (ctxt->input != NULL)
-	    ret->content = (void *) (long) ctxt->input->line;
-    }
-
-    /*
-     * We are parsing a new node.
-     */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
-#endif
-    nodePush(ctxt, ret);
-
-    /*
-     * Link the child element
-     */
-    if (parent != NULL) {
-        if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding child %s to %s\n", name, parent->name);
-#endif
-	    xmlAddChild(parent, ret);
-	} else {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "adding sibling %s to ", name);
-	    xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	    xmlAddSibling(parent, ret);
-	}
-    }
-
-    /*
-     * Insert all the defaulted attributes from the DTD especially namespaces
-     */
-    if ((!ctxt->html) &&
-	((ctxt->myDoc->intSubset != NULL) ||
-	 (ctxt->myDoc->extSubset != NULL))) {
-	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
-    }
-
-    /*
-     * process all the attributes whose name start with "xmlns"
-     */
-    if (atts != NULL) {
-        i = 0;
-	att = atts[i++];
-	value = atts[i++];
-	if (!ctxt->html) {
-	    while ((att != NULL) && (value != NULL)) {
-		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
-		    (att[3] == 'n') && (att[4] == 's'))
-		    my_attribute(ctxt, att, value, prefix);
-
-		att = atts[i++];
-		value = atts[i++];
-	    }
-	}
-    }
-
-    /*
-     * Search the namespace, note that since the attributes have been
-     * processed, the local namespaces are available.
-     */
-    ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
-    if ((ns == NULL) && (parent != NULL))
-	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
-    if ((prefix != NULL) && (ns == NULL)) {
-	ns = xmlNewNs(ret, NULL, prefix);
-	if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
-	    ctxt->sax->warning(ctxt->userData, 
-		 "Namespace prefix %s is not defined\n", prefix);
-    }
-
-    /*
-     * set the namespace node, making sure that if the default namspace
-     * is unbound on a parent we simply kee it NULL
-     */
-    if ((ns != NULL) && (ns->href != NULL) &&
-	((ns->href[0] != 0) || (ns->prefix != NULL)))
-	xmlSetNs(ret, ns);
-
-    /*
-     * process all the other attributes
-     */
-    if (atts != NULL) {
-        i = 0;
-	att = atts[i++];
-	value = atts[i++];
-	if (ctxt->html) {
-	    while (att != NULL) {
-		attribute(ctxt, att, value);
-		att = atts[i++];
-		value = atts[i++];
-	    }
-	} else {
-	    while ((att != NULL) && (value != NULL)) {
-		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
-		    (att[3] != 'n') || (att[4] != 's'))
-		    attribute(ctxt, att, value);
-
-		/*
-		 * Next ones
-		 */
-		att = atts[i++];
-		value = atts[i++];
-	    }
-	}
-    }
-
-    /*
-     * If it's the Document root, finish the DTD validation and
-     * check the document root element for validity
-     */
-    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
-	int chk;
-
-	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
-	if (chk <= 0)
-	    ctxt->valid = 0;
-	if (chk < 0)
-	    ctxt->wellFormed = 0;
-	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
-	ctxt->vctxt.finishDtd = 1;
-    }
-
-    if (prefix != NULL)
-	xmlFree(prefix);
-
+    xmlSAX2StartElement(ctx, fullname, atts);
 }
 
 /**
@@ -1524,43 +396,12 @@
  * @name:  The element name
  *
  * called when the end of an element has been detected.
+ * DEPRECATED: use xmlSAX2EndElement()
  */
 void
 endElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlParserNodeInfo node_info;
-    xmlNodePtr cur = ctxt->node;
-
-#ifdef DEBUG_SAX
-    if (name == NULL)
-        xmlGenericError(xmlGenericErrorContext, "SAX.endElement(NULL)\n");
-    else
-	xmlGenericError(xmlGenericErrorContext, "SAX.endElement(%s)\n", name);
-#endif
-    
-    /* Capture end position and add node */
-    if (cur != NULL && ctxt->record_info) {
-      node_info.end_pos = ctxt->input->cur - ctxt->input->base;
-      node_info.end_line = ctxt->input->line;
-      node_info.node = cur;
-      xmlParserAddNodeInfo(ctxt, &node_info);
-    }
-    ctxt->nodemem = -1;
-
-    if (ctxt->validate && ctxt->wellFormed &&
-        ctxt->myDoc && ctxt->myDoc->intSubset)
-        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
-					     cur);
-
-    
-    /*
-     * end of parsing of this node.
-     */
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
-#endif
-    nodePop(ctxt);
+    xmlSAX2EndElement(ctx, name);
 }
 
 /**
@@ -1569,26 +410,12 @@
  * @name:  The entity name
  *
  * called when an entity reference is detected. 
+ * DEPRECATED: use xmlSAX2Reference()
  */
 void
 reference(void *ctx, const xmlChar *name)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr ret;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.reference(%s)\n", name);
-#endif
-    if (name[0] == '#')
-	ret = xmlNewCharRef(ctxt->myDoc, name);
-    else
-	ret = xmlNewReference(ctxt->myDoc, name);
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add reference %s to %s \n", name, ctxt->node->name);
-#endif
-    xmlAddChild(ctxt->node, ret);
+    xmlSAX2Reference(ctx, name);
 }
 
 /**
@@ -1598,113 +425,12 @@
  * @len: the number of xmlChar
  *
  * receiving some chars from the parser.
+ * DEPRECATED: use xmlSAX2Characters()
  */
 void
 characters(void *ctx, const xmlChar *ch, int len)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr lastChild;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.characters(%.30s, %d)\n", ch, len);
-#endif
-    /*
-     * Handle the data if any. If there is no child
-     * add it as content, otherwise if the last child is text,
-     * concatenate it, else create a new node of type text.
-     */
-
-    if (ctxt->node == NULL) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"add chars: ctxt->node == NULL !\n");
-#endif
-        return;
-    }
-    lastChild = xmlGetLastChild(ctxt->node);
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add chars to %s \n", ctxt->node->name);
-#endif
-
-    /*
-     * Here we needed an accelerator mechanism in case of very large
-     * elements. Use an attribute in the structure !!!
-     */
-    if (lastChild == NULL) {
-	/* first node, first time */
-	xmlNodeAddContentLen(ctxt->node, ch, len);
-	if (ctxt->node->children != NULL) {
-	    ctxt->nodelen = len;
-	    ctxt->nodemem = len + 1;
-	}
-    } else {
-	int coalesceText = (lastChild != NULL) &&
-	    (lastChild->type == XML_TEXT_NODE) &&
-	    (lastChild->name == xmlStringText);
-	if ((coalesceText) && (ctxt->nodemem != 0)) {
-	    /*
-	     * The whole point of maintaining nodelen and nodemem,
-	     * xmlTextConcat is too costly, i.e. compute length,
-	     * reallocate a new buffer, move data, append ch. Here
-	     * We try to minimaze realloc() uses and avoid copying
-	     * and recomputing length over and over.
-	     */
-	    if (ctxt->nodelen + len >= ctxt->nodemem) {
-		xmlChar *newbuf;
-		int size;
-
-		size = ctxt->nodemem + len;
-		size *= 2;
-                newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
-		if (newbuf == NULL) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-			ctxt->sax->error(ctxt->userData, 
-			     "SAX.characters(): out of memory\n");
-		    ctxt->errNo = XML_ERR_NO_MEMORY;
-		    ctxt->instate = XML_PARSER_EOF;
-		    ctxt->disableSAX = 1;
-		    return;
-		}
-		ctxt->nodemem = size;
-		lastChild->content = newbuf;
-	    }
-	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
-	    ctxt->nodelen += len;
-	    lastChild->content[ctxt->nodelen] = 0;
-	} else if (coalesceText) {
-	    if (xmlTextConcat(lastChild, ch, len)) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		    ctxt->sax->error(ctxt->userData, 
-			 "SAX.characters(): out of memory\n");
-		ctxt->errNo = XML_ERR_NO_MEMORY;
-		ctxt->instate = XML_PARSER_EOF;
-		ctxt->disableSAX = 1;
-	    }
-	    if (ctxt->node->children != NULL) {
-		ctxt->nodelen = xmlStrlen(lastChild->content);
-		ctxt->nodemem = ctxt->nodelen + 1;
-	    }
-	} else {
-	    /* Mixed content, first time */
-	    lastChild = xmlNewTextLen(ch, len);
-	    if (lastChild == NULL) {
-		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		    ctxt->sax->error(ctxt->userData, 
-			 "SAX.characters(): out of memory\n");
-		ctxt->errNo = XML_ERR_NO_MEMORY;
-		ctxt->instate = XML_PARSER_EOF;
-		ctxt->disableSAX = 1;
-	    } else {
-		xmlAddChild(ctxt->node, lastChild);
-		if (ctxt->node->children != NULL) {
-		    ctxt->nodelen = len;
-		    ctxt->nodemem = len + 1;
-		}
-	    }
-	}
-    }
+    xmlSAX2Characters(ctx, ch, len);
 }
 
 /**
@@ -1715,15 +441,11 @@
  *
  * receiving some ignorable whitespaces from the parser.
  * UNUSED: by default the DOM building will use characters
+ * DEPRECATED: use xmlSAX2IgnorableWhitespace()
  */
 void
 ignorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
 {
-    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
-#endif
 }
 
 /**
@@ -1733,53 +455,13 @@
  * @data: the PI data's
  *
  * A processing instruction has been parsed.
+ * DEPRECATED: use xmlSAX2ProcessingInstruction()
  */
 void
 processingInstruction(void *ctx, const xmlChar *target,
                       const xmlChar *data)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr ret;
-    xmlNodePtr parent = ctxt->node;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.processingInstruction(%s, %s)\n", target, data);
-#endif
-
-    ret = xmlNewPI(target, data);
-    if (ret == NULL) return;
-    parent = ctxt->node;
-
-    if (ctxt->inSubset == 1) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
-	return;
-    } else if (ctxt->inSubset == 2) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
-	return;
-    }
-    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting PI %s as root\n", target);
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-	return;
-    }
-    if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s child to %s\n", target, parent->name);
-#endif
-	xmlAddChild(parent, ret);
-    } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding PI %s sibling to ", target);
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	xmlAddSibling(parent, ret);
-    }
+    xmlSAX2ProcessingInstruction(ctx, target, data);
 }
 
 /**
@@ -1789,16 +471,11 @@
  * @prefix: the namespace prefix
  *
  * An old global namespace has been parsed.
+ * DEPRECATED
  */
 void
-globalNamespace(void *ctx, const xmlChar *href, const xmlChar *prefix)
+globalNamespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *href ATTRIBUTE_UNUSED, const xmlChar *prefix ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.globalNamespace(%s, %s)\n", href, prefix);
-#endif
-    xmlNewGlobalNs(ctxt->myDoc, href, prefix);
 }
 
 /**
@@ -1807,27 +484,12 @@
  * @name:  the namespace prefix
  *
  * Set the current element namespace.
+ * DEPRECATED
  */
 
 void
-setNamespace(void *ctx, const xmlChar *name)
+setNamespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNsPtr ns;
-    xmlNodePtr parent;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext, "SAX.setNamespace(%s)\n", name);
-#endif
-    ns = xmlSearchNs(ctxt->myDoc, ctxt->node, name);
-    if (ns == NULL) { /* ctxt->node may not have a parent yet ! */
-        if (ctxt->nodeNr >= 2) {
-	    parent = ctxt->nodeTab[ctxt->nodeNr - 2];
-	    if (parent != NULL)
-		ns = xmlSearchNs(ctxt->myDoc, parent, name);
-	}
-    }
-    xmlSetNs(ctxt->node, ns);
 }
 
 /**
@@ -1835,21 +497,15 @@
  * @ctx: the user data (XML parser context)
  *
  * Get the current element namespace.
+ * DEPRECATED
  *
  * Returns the xmlNsPtr or NULL if none
  */
 
 xmlNsPtr
-getNamespace(void *ctx)
+getNamespace(void *ctx ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNsPtr ret;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext, "SAX.getNamespace()\n");
-#endif
-    ret = ctxt->node->ns;
-    return(ret);
+    return(NULL);
 }
 
 /**
@@ -1859,48 +515,14 @@
  *
  * Check that the current element namespace is the same as the
  * one read upon parsing.
+ * DEPRECATED
  *
  * Returns 1 if true 0 otherwise
  */
 
 int
-checkNamespace(void *ctx, xmlChar *namespace)
+checkNamespace(void *ctx ATTRIBUTE_UNUSED, xmlChar *namespace ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr cur = ctxt->node;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.checkNamespace(%s)\n", namespace);
-#endif
-
-    /*
-     * Check that the Name in the ETag is the same as in the STag.
-     */
-    if (namespace == NULL) {
-        if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt, 
-		 "End tags for %s don't hold the namespace %s\n",
-		                 cur->name, cur->ns->prefix);
-	    ctxt->wellFormed = 0;
-	}
-    } else {
-        if ((cur->ns == NULL) || (cur->ns->prefix == NULL)) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt, 
-		 "End tags %s holds a prefix %s not used by the open tag\n",
-		                 cur->name, namespace);
-	    ctxt->wellFormed = 0;
-	} else if (!xmlStrEqual(namespace, cur->ns->prefix)) {
-	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		ctxt->sax->error(ctxt, 
-    "Start and End tags for %s don't use the same namespaces: %s and %s\n",
-	                         cur->name, cur->ns->prefix, namespace);
-	    ctxt->wellFormed = 0;
-	} else
-	    return(1);
-    }
     return(0);
 }
 
@@ -1911,20 +533,11 @@
  * @prefix: the namespace prefix
  *
  * A namespace has been parsed.
+ * DEPRECATED
  */
 void
-namespaceDecl(void *ctx, const xmlChar *href, const xmlChar *prefix)
+namespaceDecl(void *ctx ATTRIBUTE_UNUSED, const xmlChar *href ATTRIBUTE_UNUSED, const xmlChar *prefix ATTRIBUTE_UNUSED)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-#ifdef DEBUG_SAX
-    if (prefix == NULL)
-	xmlGenericError(xmlGenericErrorContext,
-		"SAX.namespaceDecl(%s, NULL)\n", href);
-    else
-	xmlGenericError(xmlGenericErrorContext,
-		"SAX.namespaceDecl(%s, %s)\n", href, prefix);
-#endif
-    xmlNewNs(ctxt->node, href, prefix);
 }
 
 /**
@@ -1933,49 +546,12 @@
  * @value:  the comment content
  *
  * A comment has been parsed.
+ * DEPRECATED: use xmlSAX2Comment()
  */
 void
 comment(void *ctx, const xmlChar *value)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr ret;
-    xmlNodePtr parent = ctxt->node;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext, "SAX.comment(%s)\n", value);
-#endif
-    ret = xmlNewDocComment(ctxt->myDoc, value);
-    if (ret == NULL) return;
-
-    if (ctxt->inSubset == 1) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
-	return;
-    } else if (ctxt->inSubset == 2) {
-	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
-	return;
-    }
-    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
-#ifdef DEBUG_SAX_TREE
-	    xmlGenericError(xmlGenericErrorContext,
-		    "Setting comment as root\n");
-#endif
-        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
-	return;
-    }
-    if (parent->type == XML_ELEMENT_NODE) {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding comment child to %s\n", parent->name);
-#endif
-	xmlAddChild(parent, ret);
-    } else {
-#ifdef DEBUG_SAX_TREE
-	xmlGenericError(xmlGenericErrorContext,
-		"adding comment sibling to ");
-	xmlDebugDumpOneNode(stderr, parent, 0);
-#endif
-	xmlAddSibling(parent, ret);
-    }
+    xmlSAX2Comment(ctx, value);
 }
 
 /**
@@ -1985,29 +561,12 @@
  * @len:  the block length
  *
  * called when a pcdata block has been parsed
+ * DEPRECATED: use xmlSAX2CDataBlock()
  */
 void
 cdataBlock(void *ctx, const xmlChar *value, int len)
 {
-    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
-    xmlNodePtr ret, lastChild;
-
-#ifdef DEBUG_SAX
-    xmlGenericError(xmlGenericErrorContext,
-	    "SAX.pcdata(%.10s, %d)\n", value, len);
-#endif
-    lastChild = xmlGetLastChild(ctxt->node);
-#ifdef DEBUG_SAX_TREE
-    xmlGenericError(xmlGenericErrorContext,
-	    "add chars to %s \n", ctxt->node->name);
-#endif
-    if ((lastChild != NULL) &&
-        (lastChild->type == XML_CDATA_SECTION_NODE)) {
-	xmlTextConcat(lastChild, value, len);
-    } else {
-	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
-	xmlAddChild(ctxt->node, ret);
-    }
+    xmlSAX2CDataBlock(ctx, value, len);
 }
 
 /**
@@ -2015,39 +574,39 @@
  * @hdlr:  the SAX handler
  * @warning:  flag if non-zero sets the handler warning procedure
  *
- * Initialize the default XML SAX handler
+ * Initialize the default XML SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitDefaultSAXHandler() for the new SAX2 blocks
  */
 void
 initxmlDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
 {
+    
     if(hdlr->initialized == 1)
 	return;
 
-    hdlr->internalSubset = internalSubset;
-    hdlr->externalSubset = externalSubset;
-    hdlr->isStandalone = isStandalone;
-    hdlr->hasInternalSubset = hasInternalSubset;
-    hdlr->hasExternalSubset = hasExternalSubset;
-    hdlr->resolveEntity = resolveEntity;
-    hdlr->getEntity = getEntity;
-    hdlr->getParameterEntity = getParameterEntity;
-    hdlr->entityDecl = entityDecl;
-    hdlr->attributeDecl = attributeDecl;
-    hdlr->elementDecl = elementDecl;
-    hdlr->notationDecl = notationDecl;
-    hdlr->unparsedEntityDecl = unparsedEntityDecl;
-    hdlr->setDocumentLocator = setDocumentLocator;
-    hdlr->startDocument = startDocument;
-    hdlr->endDocument = endDocument;
-    hdlr->startElement = startElement;
-    hdlr->endElement = endElement;
-    hdlr->reference = reference;
-    hdlr->characters = characters;
-    hdlr->cdataBlock = cdataBlock;
-    hdlr->ignorableWhitespace = characters;
-    hdlr->processingInstruction = processingInstruction;
-    hdlr->comment = comment;
-    /* if (xmlGetWarningsDefaultValue == 0) */
+    hdlr->internalSubset = xmlSAX2InternalSubset;
+    hdlr->externalSubset = xmlSAX2ExternalSubset;
+    hdlr->isStandalone = xmlSAX2IsStandalone;
+    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
+    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
+    hdlr->resolveEntity = xmlSAX2ResolveEntity;
+    hdlr->getEntity = xmlSAX2GetEntity;
+    hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
+    hdlr->entityDecl = xmlSAX2EntityDecl;
+    hdlr->attributeDecl = xmlSAX2AttributeDecl;
+    hdlr->elementDecl = xmlSAX2ElementDecl;
+    hdlr->notationDecl = xmlSAX2NotationDecl;
+    hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+    hdlr->reference = xmlSAX2Reference;
+    hdlr->characters = xmlSAX2Characters;
+    hdlr->cdataBlock = xmlSAX2CDataBlock;
+    hdlr->ignorableWhitespace = xmlSAX2Characters;
+    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
     if (warning == 0)
 	hdlr->warning = NULL;
     else
@@ -2058,24 +617,14 @@
     hdlr->initialized = 1;
 }
 
-/**
- * xmlDefaultSAXHandlerInit:
- *
- * Initialize the default SAX handler
- */
-void
-xmlDefaultSAXHandlerInit(void)
-{
-    initxmlDefaultSAXHandler(&xmlDefaultSAXHandler, xmlGetWarningsDefaultValue);
-}
-
 #ifdef LIBXML_HTML_ENABLED
 
 /**
  * inithtmlDefaultSAXHandler:
  * @hdlr:  the SAX handler
  *
- * Initialize the default HTML SAX handler
+ * Initialize the default HTML SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitHtmlDefaultSAXHandler() for the new SAX2 blocks
  */
 void
 inithtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
@@ -2083,30 +632,30 @@
     if(hdlr->initialized == 1)
 	return;
 
-    hdlr->internalSubset = internalSubset;
+    hdlr->internalSubset = xmlSAX2InternalSubset;
     hdlr->externalSubset = NULL;
     hdlr->isStandalone = NULL;
     hdlr->hasInternalSubset = NULL;
     hdlr->hasExternalSubset = NULL;
     hdlr->resolveEntity = NULL;
-    hdlr->getEntity = getEntity;
+    hdlr->getEntity = xmlSAX2GetEntity;
     hdlr->getParameterEntity = NULL;
     hdlr->entityDecl = NULL;
     hdlr->attributeDecl = NULL;
     hdlr->elementDecl = NULL;
     hdlr->notationDecl = NULL;
     hdlr->unparsedEntityDecl = NULL;
-    hdlr->setDocumentLocator = setDocumentLocator;
-    hdlr->startDocument = startDocument;
-    hdlr->endDocument = endDocument;
-    hdlr->startElement = startElement;
-    hdlr->endElement = endElement;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
     hdlr->reference = NULL;
-    hdlr->characters = characters;
-    hdlr->cdataBlock = cdataBlock;
-    hdlr->ignorableWhitespace = ignorableWhitespace;
+    hdlr->characters = xmlSAX2Characters;
+    hdlr->cdataBlock = xmlSAX2CDataBlock;
+    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
     hdlr->processingInstruction = NULL;
-    hdlr->comment = comment;
+    hdlr->comment = xmlSAX2Comment;
     hdlr->warning = xmlParserWarning;
     hdlr->error = xmlParserError;
     hdlr->fatalError = xmlParserError;
@@ -2114,17 +663,6 @@
     hdlr->initialized = 1;
 }
 
-/**
- * htmlDefaultSAXHandlerInit:
- *
- * Initialize the default SAX handler
- */
-void
-htmlDefaultSAXHandlerInit(void)
-{
-	inithtmlDefaultSAXHandler(&htmlDefaultSAXHandler);
-}
-
 #endif /* LIBXML_HTML_ENABLED */
 
 #ifdef LIBXML_DOCB_ENABLED
@@ -2133,7 +671,8 @@
  * initdocbDefaultSAXHandler:
  * @hdlr:  the SAX handler
  *
- * Initialize the default DocBook SAX handler
+ * Initialize the default DocBook SAX version 1 handler
+ * DEPRECATED: use xmlSAX2InitDocbDefaultSAXHandler() for the new SAX2 blocks
  */
 void
 initdocbDefaultSAXHandler(xmlSAXHandler *hdlr)
@@ -2141,30 +680,30 @@
     if(hdlr->initialized == 1)
 	return;
 
-    hdlr->internalSubset = internalSubset;
+    hdlr->internalSubset = xmlSAX2InternalSubset;
     hdlr->externalSubset = NULL;
-    hdlr->isStandalone = isStandalone;
-    hdlr->hasInternalSubset = hasInternalSubset;
-    hdlr->hasExternalSubset = hasExternalSubset;
-    hdlr->resolveEntity = resolveEntity;
-    hdlr->getEntity = getEntity;
+    hdlr->isStandalone = xmlSAX2IsStandalone;
+    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
+    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
+    hdlr->resolveEntity = xmlSAX2ResolveEntity;
+    hdlr->getEntity = xmlSAX2GetEntity;
     hdlr->getParameterEntity = NULL;
-    hdlr->entityDecl = entityDecl;
+    hdlr->entityDecl = xmlSAX2EntityDecl;
     hdlr->attributeDecl = NULL;
     hdlr->elementDecl = NULL;
     hdlr->notationDecl = NULL;
     hdlr->unparsedEntityDecl = NULL;
-    hdlr->setDocumentLocator = setDocumentLocator;
-    hdlr->startDocument = startDocument;
-    hdlr->endDocument = endDocument;
-    hdlr->startElement = startElement;
-    hdlr->endElement = endElement;
-    hdlr->reference = reference;
-    hdlr->characters = characters;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+    hdlr->reference = xmlSAX2Reference;
+    hdlr->characters = xmlSAX2Characters;
     hdlr->cdataBlock = NULL;
-    hdlr->ignorableWhitespace = ignorableWhitespace;
+    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
     hdlr->processingInstruction = NULL;
-    hdlr->comment = comment;
+    hdlr->comment = xmlSAX2Comment;
     hdlr->warning = xmlParserWarning;
     hdlr->error = xmlParserError;
     hdlr->fatalError = xmlParserError;
@@ -2172,15 +711,4 @@
     hdlr->initialized = 1;
 }
 
-/**
- * docbDefaultSAXHandlerInit:
- *
- * Initialize the default SAX handler
- */
-void
-docbDefaultSAXHandlerInit(void)
-{
-    initdocbDefaultSAXHandler(&docbDefaultSAXHandler);
-}
-
 #endif /* LIBXML_DOCB_ENABLED */
diff --git a/SAX2.c b/SAX2.c
new file mode 100644
index 0000000..a55e6a4
--- /dev/null
+++ b/SAX2.c
@@ -0,0 +1,2036 @@
+/*
+ * SAX2.c : Default SAX2 handler to build a tree.
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <daniel@veillard.com>
+ */
+
+
+#define IN_LIBXML
+#include "libxml.h"
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/valid.h>
+#include <libxml/entities.h>
+#include <libxml/xmlerror.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlIO.h>
+#include <libxml/SAX.h>
+#include <libxml/uri.h>
+#include <libxml/valid.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/globals.h>
+
+/* #define DEBUG_SAX2 */
+/* #define DEBUG_SAX2_TREE */
+
+/**
+ * xmlSAX2GetPublicId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
+{
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+    return(NULL);
+}
+
+/**
+ * xmlSAX2GetSystemId:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provides the system ID, basically URL or filename e.g.
+ * http://www.sgmlsource.com/dtds/memo.dtd
+ *
+ * Returns a xmlChar *
+ */
+const xmlChar *
+xmlSAX2GetSystemId(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return((const xmlChar *) ctxt->input->filename); 
+}
+
+/**
+ * xmlSAX2GetLineNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the line number of the current parsing point.
+ *
+ * Returns an int
+ */
+int
+xmlSAX2GetLineNumber(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return(ctxt->input->line);
+}
+
+/**
+ * xmlSAX2GetColumnNumber:
+ * @ctx: the user data (XML parser context)
+ *
+ * Provide the column number of the current parsing point.
+ *
+ * Returns an int
+ */
+int
+xmlSAX2GetColumnNumber(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return(ctxt->input->col);
+}
+
+/**
+ * xmlSAX2IsStandalone:
+ * @ctx: the user data (XML parser context)
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2IsStandalone(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return(ctxt->myDoc->standalone == 1);
+}
+
+/**
+ * xmlSAX2HasInternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2HasInternalSubset(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return(ctxt->myDoc->intSubset != NULL);
+}
+
+/**
+ * xmlSAX2HasExternalSubset:
+ * @ctx: the user data (XML parser context)
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+int
+xmlSAX2HasExternalSubset(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    return(ctxt->myDoc->extSubset != NULL);
+}
+
+/**
+ * xmlSAX2InternalSubset:
+ * @ctx:  the user data (XML parser context)
+ * @name:  the root element name
+ * @ExternalID:  the external ID
+ * @SystemID:  the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on internal subset declaration.
+ */
+void
+xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlDtdPtr dtd;
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2InternalSubset(%s, %s, %s)\n",
+            name, ExternalID, SystemID);
+#endif
+
+    if (ctxt->myDoc == NULL)
+	return;
+    dtd = xmlGetIntSubset(ctxt->myDoc);
+    if (dtd != NULL) {
+	if (ctxt->html)
+	    return;
+	xmlUnlinkNode((xmlNodePtr) dtd);
+	xmlFreeDtd(dtd);
+	ctxt->myDoc->intSubset = NULL;
+    }
+    ctxt->myDoc->intSubset = 
+	xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
+}
+
+/**
+ * xmlSAX2ExternalSubset:
+ * @ctx: the user data (XML parser context)
+ * @name:  the root element name
+ * @ExternalID:  the external ID
+ * @SystemID:  the SYSTEM ID (e.g. filename or URL)
+ *
+ * Callback on external subset declaration.
+ */
+void
+xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
+	       const xmlChar *ExternalID, const xmlChar *SystemID)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2ExternalSubset(%s, %s, %s)\n",
+            name, ExternalID, SystemID);
+#endif
+    if (((ExternalID != NULL) || (SystemID != NULL)) &&
+        (((ctxt->validate) || (ctxt->loadsubset != 0)) &&
+	 (ctxt->wellFormed && ctxt->myDoc))) {
+	/*
+	 * Try to fetch and parse the external subset.
+	 */
+	xmlParserInputPtr oldinput;
+	int oldinputNr;
+	int oldinputMax;
+	xmlParserInputPtr *oldinputTab;
+	xmlParserInputPtr input = NULL;
+	xmlCharEncoding enc;
+	int oldcharset;
+
+	/*
+	 * Ask the Entity resolver to load the damn thing
+	 */
+	if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
+	    input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
+	                                        SystemID);
+	if (input == NULL) {
+	    return;
+	}
+
+	xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
+
+	/*
+	 * make sure we won't destroy the main document context
+	 */
+	oldinput = ctxt->input;
+	oldinputNr = ctxt->inputNr;
+	oldinputMax = ctxt->inputMax;
+	oldinputTab = ctxt->inputTab;
+	oldcharset = ctxt->charset;
+
+	ctxt->inputTab = (xmlParserInputPtr *)
+	                 xmlMalloc(5 * sizeof(xmlParserInputPtr));
+	if (ctxt->inputTab == NULL) {
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "xmlSAX2ExternalSubset: out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
+	    ctxt->input = oldinput;
+	    ctxt->inputNr = oldinputNr;
+	    ctxt->inputMax = oldinputMax;
+	    ctxt->inputTab = oldinputTab;
+	    ctxt->charset = oldcharset;
+	    return;
+	}
+	ctxt->inputNr = 0;
+	ctxt->inputMax = 5;
+	ctxt->input = NULL;
+	xmlPushInput(ctxt, input);
+
+	/*
+	 * On the fly encoding conversion if needed
+	 */
+	if (ctxt->input->length >= 4) {
+	    enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
+	    xmlSwitchEncoding(ctxt, enc);
+	}
+
+	if (input->filename == NULL)
+	    input->filename = (char *) xmlCanonicPath(SystemID);
+	input->line = 1;
+	input->col = 1;
+	input->base = ctxt->input->cur;
+	input->cur = ctxt->input->cur;
+	input->free = NULL;
+
+	/*
+	 * let's parse that entity knowing it's an external subset.
+	 */
+	xmlParseExternalSubset(ctxt, ExternalID, SystemID);
+
+        /*
+	 * Free up the external entities
+	 */
+
+	while (ctxt->inputNr > 1)
+	    xmlPopInput(ctxt);
+	xmlFreeInputStream(ctxt->input);
+        xmlFree(ctxt->inputTab);
+
+	/*
+	 * Restore the parsing context of the main entity
+	 */
+	ctxt->input = oldinput;
+	ctxt->inputNr = oldinputNr;
+	ctxt->inputMax = oldinputMax;
+	ctxt->inputTab = oldinputTab;
+	ctxt->charset = oldcharset;
+	/* ctxt->wellFormed = oldwellFormed; */
+    }
+}
+
+/**
+ * xmlSAX2ResolveEntity:
+ * @ctx: the user data (XML parser context)
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * The entity loader, to control the loading of external entities,
+ * the application can either:
+ *    - override this xmlSAX2ResolveEntity() callback in the SAX block
+ *    - or better use the xmlSetExternalEntityLoader() function to
+ *      set up it's own entity resolution routine
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+xmlParserInputPtr
+xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserInputPtr ret;
+    xmlChar *URI;
+    const char *base = NULL;
+
+    if (ctxt->input != NULL)
+	base = ctxt->input->filename;
+    if (base == NULL)
+	base = ctxt->directory;
+
+    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2ResolveEntity(%s, %s)\n", publicId, systemId);
+#endif
+
+    ret = xmlLoadExternalEntity((const char *) URI,
+				(const char *) publicId, ctxt);
+    if (URI != NULL)
+	xmlFree(URI);
+    return(ret);
+}
+
+/**
+ * xmlSAX2GetEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+xmlSAX2GetEntity(void *ctx, const xmlChar *name)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlEntityPtr ret = NULL;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2GetEntity(%s)\n", name);
+#endif
+
+    if (ctxt->inSubset == 0) {
+	ret = xmlGetPredefinedEntity(name);
+	if (ret != NULL)
+	    return(ret);
+    }
+    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
+	if (ctxt->inSubset == 2) {
+	    ctxt->myDoc->standalone = 0;
+	    ret = xmlGetDocEntity(ctxt->myDoc, name);
+	    ctxt->myDoc->standalone = 1;
+	} else {
+	    ret = xmlGetDocEntity(ctxt->myDoc, name);
+	    if (ret == NULL) {
+		ctxt->myDoc->standalone = 0;
+		ret = xmlGetDocEntity(ctxt->myDoc, name);
+		if (ret != NULL) {
+		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+			ctxt->sax->error(ctxt, 
+		 "Entity(%s) document marked standalone but require external subset\n",
+					 name);
+		    ctxt->valid = 0;
+		    ctxt->wellFormed = 0;
+		}
+		ctxt->myDoc->standalone = 1;
+	    }
+	}
+    } else {
+	ret = xmlGetDocEntity(ctxt->myDoc, name);
+    }
+    if ((ret != NULL) &&
+	((ctxt->validate) || (ctxt->replaceEntities)) &&
+	(ret->children == NULL) &&
+	(ret->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
+	int val;
+
+	/*
+	 * for validation purposes we really need to fetch and
+	 * parse the external entity
+	 */
+	xmlNodePtr children;
+
+        val = xmlParseCtxtExternalEntity(ctxt, ret->URI,
+		                         ret->ExternalID, &children);
+	if (val == 0) {
+	    xmlAddChildList((xmlNodePtr) ret, children);
+	} else {
+	    ctxt->sax->error(ctxt, 
+	     "Failure to process entity %s\n", name);
+	    ctxt->wellFormed = 0;
+	    ctxt->valid = 0;
+	    ctxt->validate = 0;
+	    return(NULL);
+	}
+	ret->owner = 1;
+    }
+    return(ret);
+}
+
+/**
+ * xmlSAX2GetParameterEntity:
+ * @ctx: the user data (XML parser context)
+ * @name: The entity name
+ *
+ * Get a parameter entity by name
+ *
+ * Returns the xmlEntityPtr if found.
+ */
+xmlEntityPtr
+xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlEntityPtr ret;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2GetParameterEntity(%s)\n", name);
+#endif
+
+    ret = xmlGetParameterEntity(ctxt->myDoc, name);
+    return(ret);
+}
+
+
+/**
+ * xmlSAX2EntityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name:  the entity name 
+ * @type:  the entity type 
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @content: the entity value (without processing).
+ *
+ * An entity definition has been parsed
+ */
+void
+xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
+          const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
+{
+    xmlEntityPtr ent;
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2EntityDecl(%s, %d, %s, %s, %s)\n",
+            name, type, publicId, systemId, content);
+#endif
+    if (ctxt->inSubset == 1) {
+	ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
+		              systemId, content);
+	if ((ent == NULL) && (ctxt->pedantic) &&
+	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt, 
+	     "Entity(%s) already defined in the internal subset\n", name);
+	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+	    xmlChar *URI;
+	    const char *base = NULL;
+
+	    if (ctxt->input != NULL)
+		base = ctxt->input->filename;
+	    if (base == NULL)
+		base = ctxt->directory;
+	
+	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+	    ent->URI = URI;
+	}
+    } else if (ctxt->inSubset == 2) {
+	ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
+		              systemId, content);
+	if ((ent == NULL) && (ctxt->pedantic) &&
+	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt, 
+	     "Entity(%s) already defined in the external subset\n", name);
+	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+	    xmlChar *URI;
+	    const char *base = NULL;
+
+	    if (ctxt->input != NULL)
+		base = ctxt->input->filename;
+	    if (base == NULL)
+		base = ctxt->directory;
+	
+	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+	    ent->URI = URI;
+	}
+    } else {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt, 
+	     "SAX.xmlSAX2EntityDecl(%s) called while not in subset\n", name);
+    }
+}
+
+/**
+ * xmlSAX2AttributeDecl:
+ * @ctx: the user data (XML parser context)
+ * @elem:  the name of the element
+ * @fullname:  the attribute name 
+ * @type:  the attribute type 
+ * @def:  the type of default value
+ * @defaultValue: the attribute default value
+ * @tree:  the tree of enumerated value set
+ *
+ * An attribute definition has been parsed
+ */
+void
+xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
+              int type, int def, const xmlChar *defaultValue,
+	      xmlEnumerationPtr tree)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlAttributePtr attr;
+    xmlChar *name = NULL, *prefix = NULL;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2AttributeDecl(%s, %s, %d, %d, %s, ...)\n",
+            elem, fullname, type, def, defaultValue);
+#endif
+    name = xmlSplitQName(ctxt, fullname, &prefix);
+    ctxt->vctxt.valid = 1;
+    if (ctxt->inSubset == 1)
+	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
+	       name, prefix, (xmlAttributeType) type,
+	       (xmlAttributeDefault) def, defaultValue, tree);
+    else if (ctxt->inSubset == 2)
+	attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
+	   name, prefix, (xmlAttributeType) type, 
+	   (xmlAttributeDefault) def, defaultValue, tree);
+    else {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt, 
+	     "SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n", name);
+	return;
+    }
+    if (ctxt->vctxt.valid == 0)
+	ctxt->valid = 0;
+    if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
+        (ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset != NULL))
+	ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
+	                                        attr);
+    if (prefix != NULL)
+	xmlFree(prefix);
+    if (name != NULL)
+	xmlFree(name);
+}
+
+/**
+ * xmlSAX2ElementDecl:
+ * @ctx: the user data (XML parser context)
+ * @name:  the element name 
+ * @type:  the element type 
+ * @content: the element value tree
+ *
+ * An element definition has been parsed
+ */
+void
+xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
+            xmlElementContentPtr content)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlElementPtr elem = NULL;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+                    "SAX.xmlSAX2ElementDecl(%s, %d, ...)\n", name, type);
+#endif
+
+    if (ctxt->inSubset == 1)
+        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
+                                 name, (xmlElementTypeVal) type, content);
+    else if (ctxt->inSubset == 2)
+        elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
+                                 name, (xmlElementTypeVal) type, content);
+    else {
+        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+            ctxt->sax->error(ctxt,
+                             "SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
+                             name);
+        return;
+    }
+    if (elem == NULL)
+        ctxt->valid = 0;
+    if (ctxt->validate && ctxt->wellFormed &&
+        ctxt->myDoc && ctxt->myDoc->intSubset)
+        ctxt->valid &=
+            xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
+}
+
+/**
+ * xmlSAX2NotationDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the notation
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ *
+ * What to do when a notation declaration has been parsed.
+ */
+void
+xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
+	     const xmlChar *publicId, const xmlChar *systemId)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNotationPtr nota = NULL;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2NotationDecl(%s, %s, %s)\n", name, publicId, systemId);
+#endif
+
+    if ((publicId == NULL) && (systemId == NULL)) {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt, 
+	     "SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n", name);
+	ctxt->valid = 0;
+	ctxt->wellFormed = 0;
+	return;
+    } else if (ctxt->inSubset == 1)
+	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
+                              publicId, systemId);
+    else if (ctxt->inSubset == 2)
+	nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
+                              publicId, systemId);
+    else {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt, 
+	     "SAX.xmlSAX2NotationDecl(%s) called while not in subset\n", name);
+	return;
+    }
+    if (nota == NULL) ctxt->valid = 0;
+    if (ctxt->validate && ctxt->wellFormed &&
+        ctxt->myDoc && ctxt->myDoc->intSubset)
+	ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
+	                                       nota);
+}
+
+/**
+ * xmlSAX2UnparsedEntityDecl:
+ * @ctx: the user data (XML parser context)
+ * @name: The name of the entity
+ * @publicId: The public ID of the entity
+ * @systemId: The system ID of the entity
+ * @notationName: the name of the notation
+ *
+ * What to do when an unparsed entity declaration is parsed
+ */
+void
+xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
+		   const xmlChar *publicId, const xmlChar *systemId,
+		   const xmlChar *notationName)
+{
+    xmlEntityPtr ent;
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2UnparsedEntityDecl(%s, %s, %s, %s)\n",
+            name, publicId, systemId, notationName);
+#endif
+    if (ctxt->inSubset == 1) {
+	ent = xmlAddDocEntity(ctxt->myDoc, name,
+			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
+			publicId, systemId, notationName);
+	if ((ent == NULL) && (ctxt->pedantic) &&
+	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt, 
+	     "Entity(%s) already defined in the internal subset\n", name);
+	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+	    xmlChar *URI;
+	    const char *base = NULL;
+
+	    if (ctxt->input != NULL)
+		base = ctxt->input->filename;
+	    if (base == NULL)
+		base = ctxt->directory;
+	
+	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+	    ent->URI = URI;
+	}
+    } else if (ctxt->inSubset == 2) {
+	ent = xmlAddDtdEntity(ctxt->myDoc, name,
+			XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
+			publicId, systemId, notationName);
+	if ((ent == NULL) && (ctxt->pedantic) &&
+	    (ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt, 
+	     "Entity(%s) already defined in the external subset\n", name);
+	if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
+	    xmlChar *URI;
+	    const char *base = NULL;
+
+	    if (ctxt->input != NULL)
+		base = ctxt->input->filename;
+	    if (base == NULL)
+		base = ctxt->directory;
+	
+	    URI = xmlBuildURI(systemId, (const xmlChar *) base);
+	    ent->URI = URI;
+	}
+    } else {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt, 
+	     "SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n", name);
+    }
+}
+
+/**
+ * xmlSAX2SetDocumentLocator:
+ * @ctx: the user data (XML parser context)
+ * @loc: A SAX Locator
+ *
+ * Receive the document locator at startup, actually xmlDefaultSAXLocator
+ * Everything is available on the context, so this is useless in our case.
+ */
+void
+xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
+{
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2SetDocumentLocator()\n");
+#endif
+}
+
+/**
+ * xmlSAX2StartDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document start being processed.
+ */
+void
+xmlSAX2StartDocument(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlDocPtr doc;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2StartDocument()\n");
+#endif
+    if (ctxt->html) {
+#ifdef LIBXML_HTML_ENABLED
+	if (ctxt->myDoc == NULL)
+	    ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
+	if (ctxt->myDoc == NULL) {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "SAX.xmlSAX2StartDocument(): out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
+	    return;
+	}
+#else
+        xmlGenericError(xmlGenericErrorContext,
+		"libxml2 built without HTML support\n");
+	ctxt->errNo = XML_ERR_INTERNAL_ERROR;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+	return;
+#endif
+    } else {
+	doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
+	if (doc != NULL) {
+	    if (ctxt->encoding != NULL)
+		doc->encoding = xmlStrdup(ctxt->encoding);
+	    else
+		doc->encoding = NULL;
+	    doc->standalone = ctxt->standalone;
+	} else {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "SAX.xmlSAX2StartDocument(): out of memory\n");
+	    ctxt->errNo = XML_ERR_NO_MEMORY;
+	    ctxt->instate = XML_PARSER_EOF;
+	    ctxt->disableSAX = 1;
+	    return;
+	}
+    }
+    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
+	(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
+	ctxt->myDoc->URL = xmlCanonicPath((const xmlChar *) ctxt->input->filename);
+	if (ctxt->myDoc->URL == NULL)
+	    ctxt->myDoc->URL = xmlStrdup((const xmlChar *) ctxt->input->filename);
+    }
+}
+
+/**
+ * xmlSAX2EndDocument:
+ * @ctx: the user data (XML parser context)
+ *
+ * called when the document end has been detected.
+ */
+void
+xmlSAX2EndDocument(void *ctx)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2EndDocument()\n");
+#endif
+    if (ctxt->validate && ctxt->wellFormed &&
+        ctxt->myDoc && ctxt->myDoc->intSubset)
+	ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
+
+    /*
+     * Grab the encoding if it was added on-the-fly
+     */
+    if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
+	(ctxt->myDoc->encoding == NULL)) {
+	ctxt->myDoc->encoding = ctxt->encoding;
+	ctxt->encoding = NULL;
+    }
+    if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
+	(ctxt->myDoc->encoding == NULL)) {
+	ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
+    }
+    if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
+	(ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
+	ctxt->myDoc->charset = ctxt->charset;
+    }
+}
+
+/**
+ * xmlSAX2AttributeInternal:
+ * @ctx: the user data (XML parser context)
+ * @fullname:  The attribute name, including namespace prefix
+ * @value:  The attribute value
+ * @prefix: the prefix on the element node
+ *
+ * Handle an attribute that has been read by the parser.
+ * The default handling is to convert the attribute into an
+ * DOM subtree and past it in a new xmlAttr element added to
+ * the element.
+ */
+static void
+xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
+             const xmlChar *value, const xmlChar *prefix)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlAttrPtr ret;
+    xmlChar *name;
+    xmlChar *ns;
+    xmlChar *nval;
+    xmlNsPtr namespace;
+
+    /*
+     * Split the full name into a namespace prefix and the tag name
+     */
+    name = xmlSplitQName(ctxt, fullname, &ns);
+    if ((name != NULL) && (name[0] == 0)) {
+        if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "invalid namespace declaration '%s'\n", fullname);
+	} else {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+		ctxt->sax->warning(ctxt->userData, 
+		     "Avoid attribute ending with ':' like '%s'\n", fullname);
+	}
+	if (ns != NULL)
+	    xmlFree(ns);
+	ns = NULL;
+	xmlFree(name);
+	name = xmlStrdup(fullname);
+    }
+    if (name == NULL) {
+	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+	    ctxt->sax->error(ctxt->userData, 
+		 "SAX.xmlSAX2StartElement(): out of memory\n");
+	ctxt->errNo = XML_ERR_NO_MEMORY;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+	if (ns != NULL)
+	    xmlFree(ns);
+	return;
+    }
+
+    /*
+     * Do the last stage of the attribute normalization
+     * Needed for HTML too:
+     *   http://www.w3.org/TR/html4/types.html#h-6.2
+     */
+    ctxt->vctxt.valid = 1;
+    nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
+	                                   ctxt->myDoc, ctxt->node,
+					   fullname, value);
+    if (ctxt->vctxt.valid != 1) {
+	ctxt->valid = 0;
+    }
+    if (nval != NULL)
+	value = nval;
+
+    /*
+     * Check whether it's a namespace definition
+     */
+    if ((!ctxt->html) && (ns == NULL) &&
+        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
+        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
+	xmlNsPtr nsret;
+	xmlChar *val;
+
+        if (!ctxt->replaceEntities) {
+	    ctxt->depth++;
+	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
+		                          0,0,0);
+	    ctxt->depth--;
+	} else {
+	    val = (xmlChar *) value;
+	}
+
+	if (val[0] != 0) {
+	    xmlURIPtr uri;
+
+	    uri = xmlParseURI((const char *)val);
+	    if (uri == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+		    ctxt->sax->warning(ctxt->userData, 
+			 "nmlns: %s not a valid URI\n", val);
+	    } else {
+		if (uri->scheme == NULL) {
+		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+			ctxt->sax->warning(ctxt->userData, 
+			     "xmlns: URI %s is not absolute\n", val);
+		}
+		xmlFreeURI(uri);
+	    }
+	}
+
+	/* a default namespace definition */
+	nsret = xmlNewNs(ctxt->node, val, NULL);
+
+	/*
+	 * Validate also for namespace decls, they are attributes from
+	 * an XML-1.0 perspective
+	 */
+        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
+	    ctxt->myDoc && ctxt->myDoc->intSubset)
+	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
+					   ctxt->node, prefix, nsret, val);
+	if (name != NULL) 
+	    xmlFree(name);
+	if (nval != NULL)
+	    xmlFree(nval);
+	if (val != value)
+	    xmlFree(val);
+	return;
+    }
+    if ((!ctxt->html) &&
+	(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
+        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
+	xmlNsPtr nsret;
+	xmlChar *val;
+
+        if (!ctxt->replaceEntities) {
+	    ctxt->depth++;
+	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
+		                          0,0,0);
+	    ctxt->depth--;
+	    if (val == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.xmlSAX2StartElement(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	        xmlFree(ns);
+		if (name != NULL) 
+		    xmlFree(name);
+		return;
+	    }
+	} else {
+	    val = (xmlChar *) value;
+	}
+
+	if (val[0] == 0) {
+	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		ctxt->sax->error(ctxt->userData, 
+		     "Empty namespace name for prefix %s\n", name);
+	}
+	if ((ctxt->pedantic != 0) && (val[0] != 0)) {
+	    xmlURIPtr uri;
+
+	    uri = xmlParseURI((const char *)val);
+	    if (uri == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+		    ctxt->sax->warning(ctxt->userData, 
+			 "xmlns:%s: %s not a valid URI\n", name, value);
+	    } else {
+		if (uri->scheme == NULL) {
+		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+			ctxt->sax->warning(ctxt->userData, 
+			   "xmlns:%s: URI %s is not absolute\n", name, value);
+		}
+		xmlFreeURI(uri);
+	    }
+	}
+
+	/* a standard namespace definition */
+	nsret = xmlNewNs(ctxt->node, val, name);
+	xmlFree(ns);
+	/*
+	 * Validate also for namespace decls, they are attributes from
+	 * an XML-1.0 perspective
+	 */
+        if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
+	    ctxt->myDoc && ctxt->myDoc->intSubset)
+	    ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
+					   ctxt->node, prefix, nsret, value);
+	if (name != NULL) 
+	    xmlFree(name);
+	if (nval != NULL)
+	    xmlFree(nval);
+	if (val != value)
+	    xmlFree(val);
+	return;
+    }
+
+    if (ns != NULL) {
+	xmlAttrPtr prop;
+	namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
+
+	prop = ctxt->node->properties;
+	while (prop != NULL) {
+	    if (prop->ns != NULL) {
+		if ((xmlStrEqual(name, prop->name)) &&
+		    ((namespace == prop->ns) ||
+		     (xmlStrEqual(namespace->href, prop->ns->href)))) {
+		    ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
+		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+			ctxt->sax->error(ctxt->userData,
+			        "Attribute %s in %s redefined\n",
+			                 name, namespace->href);
+		    ctxt->wellFormed = 0;
+		    if (ctxt->recovery == 0) ctxt->disableSAX = 1;
+		    goto error;
+		}
+	    }
+	    prop = prop->next;
+	}
+    } else {
+	namespace = NULL;
+    }
+
+    /* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
+    ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
+
+    if (ret != NULL) {
+        if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
+	    xmlNodePtr tmp;
+
+	    ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
+	    tmp = ret->children;
+	    while (tmp != NULL) {
+		tmp->parent = (xmlNodePtr) ret;
+		if (tmp->next == NULL)
+		    ret->last = tmp;
+		tmp = tmp->next;
+	    }
+	} else if (value != NULL) {
+	    ret->children = xmlNewDocText(ctxt->myDoc, value);
+	    ret->last = ret->children;
+	    if (ret->children != NULL)
+		ret->children->parent = (xmlNodePtr) ret;
+	}
+    }
+
+    if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
+        ctxt->myDoc && ctxt->myDoc->intSubset) {
+	
+	/*
+	 * If we don't substitute entities, the validation should be
+	 * done on a value with replaced entities anyway.
+	 */
+        if (!ctxt->replaceEntities) {
+	    xmlChar *val;
+
+	    ctxt->depth++;
+	    val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
+		                          0,0,0);
+	    ctxt->depth--;
+	    
+	    if (val == NULL)
+		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
+				ctxt->myDoc, ctxt->node, ret, value);
+	    else {
+		xmlChar *nvalnorm;
+
+		/*
+		 * Do the last stage of the attribute normalization
+		 * It need to be done twice ... it's an extra burden related
+		 * to the ability to keep xmlSAX2References in attributes
+		 */
+		nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
+					    ctxt->node, fullname, val);
+		if (nvalnorm != NULL) {
+		    xmlFree(val);
+		    val = nvalnorm;
+		}
+
+		ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
+			        ctxt->myDoc, ctxt->node, ret, val);
+                xmlFree(val);
+	    }
+	} else {
+	    ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
+					       ctxt->node, ret, value);
+	}
+    } else if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
+	       (((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
+	        ((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0)))) {
+        /*
+	 * when validating, the ID registration is done at the attribute
+	 * validation level. Otherwise we have to do specific handling here.
+	 */
+	if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
+	    xmlAddID(&ctxt->vctxt, ctxt->myDoc, value, ret);
+	else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
+	    xmlAddRef(&ctxt->vctxt, ctxt->myDoc, value, ret);
+    }
+
+error:
+    if (nval != NULL)
+	xmlFree(nval);
+    if (ns != NULL) 
+	xmlFree(ns);
+}
+
+/**
+ * attribute:
+ * @ctx: the user data (XML parser context)
+ * @fullname:  The attribute name, including namespace prefix
+ * @value:  The attribute value
+ *
+ * Handle an attribute that has been read by the parser.
+ * The default handling is to convert the attribute into an
+ * DOM subtree and past it in a new xmlAttr element added to
+ * the element.
+ */
+static void
+xmlSAX2Attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
+{
+    xmlSAX2AttributeInternal(ctx, fullname, value, NULL);
+}
+
+/*
+ * xmlCheckDefaultedAttributes:
+ *
+ * Check defaulted attributes from the DTD
+ */
+static void
+xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
+	const xmlChar *prefix, const xmlChar **atts) {
+    xmlElementPtr elemDecl;
+    const xmlChar *att;
+    int internal = 1;
+    int i;
+
+    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
+    if (elemDecl == NULL) {
+	elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
+	internal = 0;
+    }
+
+process_external_subset:
+
+    if (elemDecl != NULL) {
+	xmlAttributePtr attr = elemDecl->attributes;
+	/*
+	 * Check against defaulted attributes from the external subset
+	 * if the document is stamped as standalone
+	 */
+	if ((ctxt->myDoc->standalone == 1) &&
+	    (ctxt->myDoc->extSubset != NULL) &&
+	    (ctxt->validate)) {
+	    while (attr != NULL) {
+		if ((attr->defaultValue != NULL) &&
+		    (xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
+					attr->elem, attr->name,
+					attr->prefix) == attr) &&
+		    (xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
+					attr->elem, attr->name,
+					attr->prefix) == NULL)) {
+		    xmlChar *fulln;
+
+		    if (attr->prefix != NULL) {
+			fulln = xmlStrdup(attr->prefix);
+			fulln = xmlStrcat(fulln, BAD_CAST ":");
+			fulln = xmlStrcat(fulln, attr->name);
+		    } else {
+			fulln = xmlStrdup(attr->name);
+		    }
+
+		    /*
+		     * Check that the attribute is not declared in the
+		     * serialization
+		     */
+		    att = NULL;
+		    if (atts != NULL) {
+			i = 0;
+			att = atts[i];
+			while (att != NULL) {
+			    if (xmlStrEqual(att, fulln))
+				break;
+			    i += 2;
+			    att = atts[i];
+			}
+		    }
+		    if (att == NULL) {
+			if (ctxt->vctxt.error != NULL)
+			    ctxt->vctxt.error(ctxt->vctxt.userData,
+      "standalone: attribute %s on %s defaulted from external subset\n",
+					      fulln, attr->elem);
+			ctxt->valid = 0;
+		    }
+		}
+		attr = attr->nexth;
+	    }
+	}
+
+	/*
+	 * Actually insert defaulted values when needed
+	 */
+	attr = elemDecl->attributes;
+	while (attr != NULL) {
+	    /*
+	     * Make sure that attributes redefinition occuring in the
+	     * internal subset are not overriden by definitions in the
+	     * external subset.
+	     */
+	    if (attr->defaultValue != NULL) {
+		/*
+		 * the element should be instantiated in the tree if:
+		 *  - this is a namespace prefix
+		 *  - the user required for completion in the tree
+		 *    like XSLT
+		 *  - there isn't already an attribute definition 
+		 *    in the internal subset overriding it.
+		 */
+		if (((attr->prefix != NULL) &&
+		     (xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
+		    ((attr->prefix == NULL) &&
+		     (xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
+		    (ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
+		    xmlAttributePtr tst;
+
+		    tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
+					     attr->elem, attr->name,
+					     attr->prefix);
+		    if ((tst == attr) || (tst == NULL)) {
+		        xmlChar fn[50];
+			xmlChar *fulln;
+
+                        fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
+			if (fulln == NULL) {
+			    if ((ctxt->sax != NULL) &&
+			        (ctxt->sax->error != NULL))
+				ctxt->sax->error(ctxt->userData, 
+				     "SAX.xmlSAX2StartElement(): out of memory\n");
+			    ctxt->errNo = XML_ERR_NO_MEMORY;
+			    ctxt->instate = XML_PARSER_EOF;
+			    ctxt->disableSAX = 1;
+			    return;
+			}
+
+			/*
+			 * Check that the attribute is not declared in the
+			 * serialization
+			 */
+			att = NULL;
+			if (atts != NULL) {
+			    i = 0;
+			    att = atts[i];
+			    while (att != NULL) {
+				if (xmlStrEqual(att, fulln))
+				    break;
+				i += 2;
+				att = atts[i];
+			    }
+			}
+			if (att == NULL) {
+			    xmlSAX2AttributeInternal(ctxt, fulln,
+						 attr->defaultValue, prefix);
+			}
+			if ((fulln != fn) && (fulln != attr->name))
+			    xmlFree(fulln);
+		    }
+		}
+	    }
+	    attr = attr->nexth;
+	}
+	if (internal == 1) {
+	    elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
+		                             name, prefix);
+	    internal = 0;
+	    goto process_external_subset;
+	}
+    }
+}
+
+/**
+ * xmlSAX2StartElement:
+ * @ctx: the user data (XML parser context)
+ * @fullname:  The element name, including namespace prefix
+ * @atts:  An array of name/value attributes pairs, NULL terminated
+ *
+ * called when an opening tag has been processed.
+ */
+void
+xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr ret;
+    xmlNodePtr parent = ctxt->node;
+    xmlNsPtr ns;
+    xmlChar *name;
+    xmlChar *prefix;
+    const xmlChar *att;
+    const xmlChar *value;
+    int i;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2StartElement(%s)\n", fullname);
+#endif
+
+    /*
+     * First check on validity:
+     */
+    if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) && 
+        ((ctxt->myDoc->intSubset == NULL) ||
+	 ((ctxt->myDoc->intSubset->notations == NULL) && 
+	  (ctxt->myDoc->intSubset->elements == NULL) &&
+	  (ctxt->myDoc->intSubset->attributes == NULL) && 
+	  (ctxt->myDoc->intSubset->entities == NULL)))) {
+	if (ctxt->vctxt.error != NULL) {
+            ctxt->vctxt.error(ctxt->vctxt.userData,
+	      "Validation failed: no DTD found !\n");
+	}
+	ctxt->validate = 0;
+	ctxt->valid = 0;
+	ctxt->errNo = XML_ERR_NO_DTD;
+    }
+       
+
+    /*
+     * Split the full name into a namespace prefix and the tag name
+     */
+    name = xmlSplitQName(ctxt, fullname, &prefix);
+
+
+    /*
+     * Note : the namespace resolution is deferred until the end of the
+     *        attributes parsing, since local namespace can be defined as
+     *        an attribute at this level.
+     */
+    ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
+    if (ret == NULL) {
+        if (prefix != NULL)
+	    xmlFree(prefix);
+	ctxt->errNo = XML_ERR_NO_MEMORY;
+	ctxt->instate = XML_PARSER_EOF;
+	ctxt->disableSAX = 1;
+        return;
+    }
+    if (ctxt->myDoc->children == NULL) {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext, "Setting %s as root\n", name);
+#endif
+        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
+    } else if (parent == NULL) {
+        parent = ctxt->myDoc->children;
+    }
+    ctxt->nodemem = -1;
+    if (ctxt->linenumbers) {
+	if (ctxt->input != NULL)
+	    ret->content = (void *) (long) ctxt->input->line;
+    }
+
+    /*
+     * We are parsing a new node.
+     */
+#ifdef DEBUG_SAX_TREE
+    xmlGenericError(xmlGenericErrorContext, "pushing(%s)\n", name);
+#endif
+    nodePush(ctxt, ret);
+
+    /*
+     * Link the child element
+     */
+    if (parent != NULL) {
+        if (parent->type == XML_ELEMENT_NODE) {
+#ifdef DEBUG_SAX_TREE
+	    xmlGenericError(xmlGenericErrorContext,
+		    "adding child %s to %s\n", name, parent->name);
+#endif
+	    xmlAddChild(parent, ret);
+	} else {
+#ifdef DEBUG_SAX_TREE
+	    xmlGenericError(xmlGenericErrorContext,
+		    "adding sibling %s to ", name);
+	    xmlDebugDumpOneNode(stderr, parent, 0);
+#endif
+	    xmlAddSibling(parent, ret);
+	}
+    }
+
+    /*
+     * Insert all the defaulted attributes from the DTD especially namespaces
+     */
+    if ((!ctxt->html) &&
+	((ctxt->myDoc->intSubset != NULL) ||
+	 (ctxt->myDoc->extSubset != NULL))) {
+	xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
+    }
+
+    /*
+     * process all the attributes whose name start with "xmlns"
+     */
+    if (atts != NULL) {
+        i = 0;
+	att = atts[i++];
+	value = atts[i++];
+	if (!ctxt->html) {
+	    while ((att != NULL) && (value != NULL)) {
+		if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
+		    (att[3] == 'n') && (att[4] == 's'))
+		    xmlSAX2AttributeInternal(ctxt, att, value, prefix);
+
+		att = atts[i++];
+		value = atts[i++];
+	    }
+	}
+    }
+
+    /*
+     * Search the namespace, note that since the attributes have been
+     * processed, the local namespaces are available.
+     */
+    ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
+    if ((ns == NULL) && (parent != NULL))
+	ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
+    if ((prefix != NULL) && (ns == NULL)) {
+	ns = xmlNewNs(ret, NULL, prefix);
+	if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+	    ctxt->sax->warning(ctxt->userData, 
+		 "Namespace prefix %s is not defined\n", prefix);
+    }
+
+    /*
+     * set the namespace node, making sure that if the default namspace
+     * is unbound on a parent we simply kee it NULL
+     */
+    if ((ns != NULL) && (ns->href != NULL) &&
+	((ns->href[0] != 0) || (ns->prefix != NULL)))
+	xmlSetNs(ret, ns);
+
+    /*
+     * process all the other attributes
+     */
+    if (atts != NULL) {
+        i = 0;
+	att = atts[i++];
+	value = atts[i++];
+	if (ctxt->html) {
+	    while (att != NULL) {
+		xmlSAX2AttributeInternal(ctxt, att, value, NULL);
+		att = atts[i++];
+		value = atts[i++];
+	    }
+	} else {
+	    while ((att != NULL) && (value != NULL)) {
+		if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
+		    (att[3] != 'n') || (att[4] != 's'))
+		    xmlSAX2AttributeInternal(ctxt, att, value, NULL);
+
+		/*
+		 * Next ones
+		 */
+		att = atts[i++];
+		value = atts[i++];
+	    }
+	}
+    }
+
+    /*
+     * If it's the Document root, finish the DTD validation and
+     * check the document root element for validity
+     */
+    if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
+	int chk;
+
+	chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
+	if (chk <= 0)
+	    ctxt->valid = 0;
+	if (chk < 0)
+	    ctxt->wellFormed = 0;
+	ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
+	ctxt->vctxt.finishDtd = 1;
+    }
+
+    if (prefix != NULL)
+	xmlFree(prefix);
+
+}
+
+/**
+ * xmlSAX2EndElement:
+ * @ctx: the user data (XML parser context)
+ * @name:  The element name
+ *
+ * called when the end of an element has been detected.
+ */
+void
+xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlParserNodeInfo node_info;
+    xmlNodePtr cur = ctxt->node;
+
+#ifdef DEBUG_SAX
+    if (name == NULL)
+        xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(NULL)\n");
+    else
+	xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2EndElement(%s)\n", name);
+#endif
+    
+    /* Capture end position and add node */
+    if (cur != NULL && ctxt->record_info) {
+      node_info.end_pos = ctxt->input->cur - ctxt->input->base;
+      node_info.end_line = ctxt->input->line;
+      node_info.node = cur;
+      xmlParserAddNodeInfo(ctxt, &node_info);
+    }
+    ctxt->nodemem = -1;
+
+    if (ctxt->validate && ctxt->wellFormed &&
+        ctxt->myDoc && ctxt->myDoc->intSubset)
+        ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
+					     cur);
+
+    
+    /*
+     * end of parsing of this node.
+     */
+#ifdef DEBUG_SAX_TREE
+    xmlGenericError(xmlGenericErrorContext, "popping(%s)\n", cur->name);
+#endif
+    nodePop(ctxt);
+}
+
+/**
+ * xmlSAX2Reference:
+ * @ctx: the user data (XML parser context)
+ * @name:  The entity name
+ *
+ * called when an entity xmlSAX2Reference is detected. 
+ */
+void
+xmlSAX2Reference(void *ctx, const xmlChar *name)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr ret;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2Reference(%s)\n", name);
+#endif
+    if (name[0] == '#')
+	ret = xmlNewCharRef(ctxt->myDoc, name);
+    else
+	ret = xmlNewReference(ctxt->myDoc, name);
+#ifdef DEBUG_SAX_TREE
+    xmlGenericError(xmlGenericErrorContext,
+	    "add xmlSAX2Reference %s to %s \n", name, ctxt->node->name);
+#endif
+    xmlAddChild(ctxt->node, ret);
+}
+
+/**
+ * xmlSAX2Characters:
+ * @ctx: the user data (XML parser context)
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some chars from the parser.
+ */
+void
+xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr lastChild;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2Characters(%.30s, %d)\n", ch, len);
+#endif
+    /*
+     * Handle the data if any. If there is no child
+     * add it as content, otherwise if the last child is text,
+     * concatenate it, else create a new node of type text.
+     */
+
+    if (ctxt->node == NULL) {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext,
+		"add chars: ctxt->node == NULL !\n");
+#endif
+        return;
+    }
+    lastChild = xmlGetLastChild(ctxt->node);
+#ifdef DEBUG_SAX_TREE
+    xmlGenericError(xmlGenericErrorContext,
+	    "add chars to %s \n", ctxt->node->name);
+#endif
+
+    /*
+     * Here we needed an accelerator mechanism in case of very large
+     * elements. Use an attribute in the structure !!!
+     */
+    if (lastChild == NULL) {
+	/* first node, first time */
+	xmlNodeAddContentLen(ctxt->node, ch, len);
+	if (ctxt->node->children != NULL) {
+	    ctxt->nodelen = len;
+	    ctxt->nodemem = len + 1;
+	}
+    } else {
+	int coalesceText = (lastChild != NULL) &&
+	    (lastChild->type == XML_TEXT_NODE) &&
+	    (lastChild->name == xmlStringText);
+	if ((coalesceText) && (ctxt->nodemem != 0)) {
+	    /*
+	     * The whole point of maintaining nodelen and nodemem,
+	     * xmlTextConcat is too costly, i.e. compute length,
+	     * reallocate a new buffer, move data, append ch. Here
+	     * We try to minimaze realloc() uses and avoid copying
+	     * and recomputing length over and over.
+	     */
+	    if (ctxt->nodelen + len >= ctxt->nodemem) {
+		xmlChar *newbuf;
+		int size;
+
+		size = ctxt->nodemem + len;
+		size *= 2;
+                newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
+		if (newbuf == NULL) {
+		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+			ctxt->sax->error(ctxt->userData, 
+			     "SAX.xmlSAX2Characters(): out of memory\n");
+		    ctxt->errNo = XML_ERR_NO_MEMORY;
+		    ctxt->instate = XML_PARSER_EOF;
+		    ctxt->disableSAX = 1;
+		    return;
+		}
+		ctxt->nodemem = size;
+		lastChild->content = newbuf;
+	    }
+	    memcpy(&lastChild->content[ctxt->nodelen], ch, len);
+	    ctxt->nodelen += len;
+	    lastChild->content[ctxt->nodelen] = 0;
+	} else if (coalesceText) {
+	    if (xmlTextConcat(lastChild, ch, len)) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.xmlSAX2Characters(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	    }
+	    if (ctxt->node->children != NULL) {
+		ctxt->nodelen = xmlStrlen(lastChild->content);
+		ctxt->nodemem = ctxt->nodelen + 1;
+	    }
+	} else {
+	    /* Mixed content, first time */
+	    lastChild = xmlNewTextLen(ch, len);
+	    if (lastChild == NULL) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt->userData, 
+			 "SAX.xmlSAX2Characters(): out of memory\n");
+		ctxt->errNo = XML_ERR_NO_MEMORY;
+		ctxt->instate = XML_PARSER_EOF;
+		ctxt->disableSAX = 1;
+	    } else {
+		xmlAddChild(ctxt->node, lastChild);
+		if (ctxt->node->children != NULL) {
+		    ctxt->nodelen = len;
+		    ctxt->nodemem = len + 1;
+		}
+	    }
+	}
+    }
+}
+
+/**
+ * xmlSAX2IgnorableWhitespace:
+ * @ctx: the user data (XML parser context)
+ * @ch:  a xmlChar string
+ * @len: the number of xmlChar
+ *
+ * receiving some ignorable whitespaces from the parser.
+ * UNUSED: by default the DOM building will use xmlSAX2Characters
+ */
+void
+xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
+{
+    /* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2IgnorableWhitespace(%.30s, %d)\n", ch, len);
+#endif
+}
+
+/**
+ * xmlSAX2ProcessingInstruction:
+ * @ctx: the user data (XML parser context)
+ * @target:  the target name
+ * @data: the PI data's
+ *
+ * A processing instruction has been parsed.
+ */
+void
+xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
+                      const xmlChar *data)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr ret;
+    xmlNodePtr parent = ctxt->node;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
+#endif
+
+    ret = xmlNewPI(target, data);
+    if (ret == NULL) return;
+    parent = ctxt->node;
+
+    if (ctxt->inSubset == 1) {
+	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
+	return;
+    } else if (ctxt->inSubset == 2) {
+	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
+	return;
+    }
+    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
+#ifdef DEBUG_SAX_TREE
+	    xmlGenericError(xmlGenericErrorContext,
+		    "Setting PI %s as root\n", target);
+#endif
+        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
+	return;
+    }
+    if (parent->type == XML_ELEMENT_NODE) {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext,
+		"adding PI %s child to %s\n", target, parent->name);
+#endif
+	xmlAddChild(parent, ret);
+    } else {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext,
+		"adding PI %s sibling to ", target);
+	xmlDebugDumpOneNode(stderr, parent, 0);
+#endif
+	xmlAddSibling(parent, ret);
+    }
+}
+
+/**
+ * xmlSAX2Comment:
+ * @ctx: the user data (XML parser context)
+ * @value:  the xmlSAX2Comment content
+ *
+ * A xmlSAX2Comment has been parsed.
+ */
+void
+xmlSAX2Comment(void *ctx, const xmlChar *value)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr ret;
+    xmlNodePtr parent = ctxt->node;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext, "SAX.xmlSAX2Comment(%s)\n", value);
+#endif
+    ret = xmlNewDocComment(ctxt->myDoc, value);
+    if (ret == NULL) return;
+
+    if (ctxt->inSubset == 1) {
+	xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
+	return;
+    } else if (ctxt->inSubset == 2) {
+	xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
+	return;
+    }
+    if ((ctxt->myDoc->children == NULL) || (parent == NULL)) {
+#ifdef DEBUG_SAX_TREE
+	    xmlGenericError(xmlGenericErrorContext,
+		    "Setting xmlSAX2Comment as root\n");
+#endif
+        xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
+	return;
+    }
+    if (parent->type == XML_ELEMENT_NODE) {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext,
+		"adding xmlSAX2Comment child to %s\n", parent->name);
+#endif
+	xmlAddChild(parent, ret);
+    } else {
+#ifdef DEBUG_SAX_TREE
+	xmlGenericError(xmlGenericErrorContext,
+		"adding xmlSAX2Comment sibling to ");
+	xmlDebugDumpOneNode(stderr, parent, 0);
+#endif
+	xmlAddSibling(parent, ret);
+    }
+}
+
+/**
+ * xmlSAX2CDataBlock:
+ * @ctx: the user data (XML parser context)
+ * @value:  The pcdata content
+ * @len:  the block length
+ *
+ * called when a pcdata block has been parsed
+ */
+void
+xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlNodePtr ret, lastChild;
+
+#ifdef DEBUG_SAX
+    xmlGenericError(xmlGenericErrorContext,
+	    "SAX.pcdata(%.10s, %d)\n", value, len);
+#endif
+    lastChild = xmlGetLastChild(ctxt->node);
+#ifdef DEBUG_SAX_TREE
+    xmlGenericError(xmlGenericErrorContext,
+	    "add chars to %s \n", ctxt->node->name);
+#endif
+    if ((lastChild != NULL) &&
+        (lastChild->type == XML_CDATA_SECTION_NODE)) {
+	xmlTextConcat(lastChild, value, len);
+    } else {
+	ret = xmlNewCDataBlock(ctxt->myDoc, value, len);
+	xmlAddChild(ctxt->node, ret);
+    }
+}
+
+/**
+ * xmlSAX2InitDefaultSAXHandler:
+ * @hdlr:  the SAX handler
+ * @warning:  flag if non-zero sets the handler warning procedure
+ *
+ * Initialize the default XML SAX2 handler
+ */
+void
+xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
+{
+    if (hdlr->initialized != 0)
+	return;
+
+    hdlr->internalSubset = xmlSAX2InternalSubset;
+    hdlr->externalSubset = xmlSAX2ExternalSubset;
+    hdlr->isStandalone = xmlSAX2IsStandalone;
+    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
+    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
+    hdlr->resolveEntity = xmlSAX2ResolveEntity;
+    hdlr->getEntity = xmlSAX2GetEntity;
+    hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
+    hdlr->entityDecl = xmlSAX2EntityDecl;
+    hdlr->attributeDecl = xmlSAX2AttributeDecl;
+    hdlr->elementDecl = xmlSAX2ElementDecl;
+    hdlr->notationDecl = xmlSAX2NotationDecl;
+    hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+    hdlr->reference = xmlSAX2Reference;
+    hdlr->characters = xmlSAX2Characters;
+    hdlr->cdataBlock = xmlSAX2CDataBlock;
+    hdlr->ignorableWhitespace = xmlSAX2Characters;
+    hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
+    hdlr->comment = xmlSAX2Comment;
+    /* if (xmlGetWarningsDefaultValue == 0) */
+    if (warning == 0)
+	hdlr->warning = NULL;
+    else
+	hdlr->warning = xmlParserWarning;
+    hdlr->error = xmlParserError;
+    hdlr->fatalError = xmlParserError;
+
+    hdlr->initialized = XML_SAX2_MAGIC;
+}
+
+/**
+ * xmlDefaultSAXHandlerInit:
+ *
+ * Initialize the default SAX2 handler
+ */
+void
+xmlDefaultSAXHandlerInit(void)
+{
+    xmlSAX2InitDefaultSAXHandler(&xmlDefaultSAXHandler,
+                                 xmlGetWarningsDefaultValue);
+}
+
+#ifdef LIBXML_HTML_ENABLED
+
+/**
+ * xmlSAX2InitHtmlDefaultSAXHandler:
+ * @hdlr:  the SAX handler
+ *
+ * Initialize the default HTML SAX2 handler
+ */
+void
+xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
+{
+    if(hdlr->initialized != 0)
+	return;
+
+    hdlr->internalSubset = xmlSAX2InternalSubset;
+    hdlr->externalSubset = NULL;
+    hdlr->isStandalone = NULL;
+    hdlr->hasInternalSubset = NULL;
+    hdlr->hasExternalSubset = NULL;
+    hdlr->resolveEntity = NULL;
+    hdlr->getEntity = xmlSAX2GetEntity;
+    hdlr->getParameterEntity = NULL;
+    hdlr->entityDecl = NULL;
+    hdlr->attributeDecl = NULL;
+    hdlr->elementDecl = NULL;
+    hdlr->notationDecl = NULL;
+    hdlr->unparsedEntityDecl = NULL;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+    hdlr->reference = NULL;
+    hdlr->characters = xmlSAX2Characters;
+    hdlr->cdataBlock = xmlSAX2CDataBlock;
+    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
+    hdlr->processingInstruction = NULL;
+    hdlr->comment = xmlSAX2Comment;
+    hdlr->warning = xmlParserWarning;
+    hdlr->error = xmlParserError;
+    hdlr->fatalError = xmlParserError;
+
+    hdlr->initialized = XML_SAX2_MAGIC;
+}
+
+/**
+ * htmlDefaultSAXHandlerInit:
+ *
+ * Initialize the default SAX handler
+ */
+void
+htmlDefaultSAXHandlerInit(void)
+{
+    xmlSAX2InitHtmlDefaultSAXHandler(&htmlDefaultSAXHandler);
+}
+
+#endif /* LIBXML_HTML_ENABLED */
+
+#ifdef LIBXML_DOCB_ENABLED
+
+/**
+ * xmlSAX2InitDocbDefaultSAXHandler:
+ * @hdlr:  the SAX handler
+ *
+ * Initialize the default DocBook SAX2 handler
+ */
+void
+xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr)
+{
+    if(hdlr->initialized != 0)
+	return;
+
+    hdlr->internalSubset = xmlSAX2InternalSubset;
+    hdlr->externalSubset = NULL;
+    hdlr->isStandalone = xmlSAX2IsStandalone;
+    hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
+    hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
+    hdlr->resolveEntity = xmlSAX2ResolveEntity;
+    hdlr->getEntity = xmlSAX2GetEntity;
+    hdlr->getParameterEntity = NULL;
+    hdlr->entityDecl = xmlSAX2EntityDecl;
+    hdlr->attributeDecl = NULL;
+    hdlr->elementDecl = NULL;
+    hdlr->notationDecl = NULL;
+    hdlr->unparsedEntityDecl = NULL;
+    hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
+    hdlr->startDocument = xmlSAX2StartDocument;
+    hdlr->endDocument = xmlSAX2EndDocument;
+    hdlr->startElement = xmlSAX2StartElement;
+    hdlr->endElement = xmlSAX2EndElement;
+    hdlr->reference = xmlSAX2Reference;
+    hdlr->characters = xmlSAX2Characters;
+    hdlr->cdataBlock = NULL;
+    hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
+    hdlr->processingInstruction = NULL;
+    hdlr->comment = xmlSAX2Comment;
+    hdlr->warning = xmlParserWarning;
+    hdlr->error = xmlParserError;
+    hdlr->fatalError = xmlParserError;
+
+    hdlr->initialized = XML_SAX2_MAGIC;
+}
+
+/**
+ * docbDefaultSAXHandlerInit:
+ *
+ * Initialize the default SAX handler
+ */
+void
+docbDefaultSAXHandlerInit(void)
+{
+    xmlSAX2InitDocbDefaultSAXHandler(&docbDefaultSAXHandler);
+}
+
+#endif /* LIBXML_DOCB_ENABLED */
diff --git a/dict.c b/dict.c
index eaa4006..2dd759d 100644
--- a/dict.c
+++ b/dict.c
@@ -61,8 +61,6 @@
 static unsigned long
 xmlDictComputeKey(xmlDictPtr dict, const xmlChar *name, int namelen) {
     unsigned long value = 0L;
-    char ch;
-    int len = 0;
     
     if (name == NULL) return(0);
     value += 30 * (*name);
diff --git a/globals.c b/globals.c
index aec4873..5342340 100644
--- a/globals.c
+++ b/globals.c
@@ -331,34 +331,38 @@
  * Default handler for XML, builds the DOM tree
  */
 xmlSAXHandler xmlDefaultSAXHandler = {
-    internalSubset,
-    isStandalone,
-    hasInternalSubset,
-    hasExternalSubset,
-    resolveEntity,
-    getEntity,
-    entityDecl,
-    notationDecl,
-    attributeDecl,
-    elementDecl,
-    unparsedEntityDecl,
-    setDocumentLocator,
-    startDocument,
-    endDocument,
-    startElement,
-    endElement,
-    reference,
-    characters,
-    characters,
-    processingInstruction,
-    comment,
+    xmlSAX2InternalSubset,
+    xmlSAX2IsStandalone,
+    xmlSAX2HasInternalSubset,
+    xmlSAX2HasExternalSubset,
+    xmlSAX2ResolveEntity,
+    xmlSAX2GetEntity,
+    xmlSAX2EntityDecl,
+    xmlSAX2NotationDecl,
+    xmlSAX2AttributeDecl,
+    xmlSAX2ElementDecl,
+    xmlSAX2UnparsedEntityDecl,
+    xmlSAX2SetDocumentLocator,
+    xmlSAX2StartDocument,
+    xmlSAX2EndDocument,
+    xmlSAX2StartElement,
+    xmlSAX2EndElement,
+    xmlSAX2Reference,
+    xmlSAX2Characters,
+    xmlSAX2Characters,
+    xmlSAX2ProcessingInstruction,
+    xmlSAX2Comment,
     xmlParserWarning,
     xmlParserError,
     xmlParserError,
-    getParameterEntity,
-    cdataBlock,
-    externalSubset,
-    0
+    xmlSAX2GetParameterEntity,
+    xmlSAX2CDataBlock,
+    xmlSAX2ExternalSubset,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL
 };
 
 /**
@@ -368,7 +372,10 @@
  * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
  */
 xmlSAXLocator xmlDefaultSAXLocator = {
-    getPublicId, getSystemId, getLineNumber, getColumnNumber
+    xmlSAX2GetPublicId,
+    xmlSAX2GetSystemId,
+    xmlSAX2GetLineNumber,
+    xmlSAX2GetColumnNumber
 };
 
 #ifdef LIBXML_HTML_ENABLED
@@ -378,34 +385,38 @@
  * Default handler for HTML, builds the DOM tree
  */
 xmlSAXHandler htmlDefaultSAXHandler = {
-    internalSubset,
+    xmlSAX2InternalSubset,
     NULL,
     NULL,
     NULL,
     NULL,
-    getEntity,
+    xmlSAX2GetEntity,
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
-    setDocumentLocator,
-    startDocument,
-    endDocument,
-    startElement,
-    endElement,
+    xmlSAX2SetDocumentLocator,
+    xmlSAX2StartDocument,
+    xmlSAX2EndDocument,
+    xmlSAX2StartElement,
+    xmlSAX2EndElement,
     NULL,
-    characters,
-    ignorableWhitespace,
+    xmlSAX2Characters,
+    xmlSAX2IgnorableWhitespace,
     NULL,
-    comment,
+    xmlSAX2Comment,
     xmlParserWarning,
     xmlParserError,
     xmlParserError,
-    getParameterEntity,
-    cdataBlock,
+    xmlSAX2GetParameterEntity,
+    xmlSAX2CDataBlock,
     NULL,
-    0
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL
 };
 #endif /* LIBXML_HTML_ENABLED */
 
@@ -416,34 +427,38 @@
  * Default handler for SGML DocBook, builds the DOM tree
  */
 xmlSAXHandler docbDefaultSAXHandler = {
-    internalSubset,
-    isStandalone,
-    hasInternalSubset,
-    hasExternalSubset,
-    resolveEntity,
-    getEntity,
-    entityDecl,
+    xmlSAX2InternalSubset,
+    xmlSAX2IsStandalone,
+    xmlSAX2HasInternalSubset,
+    xmlSAX2HasExternalSubset,
+    xmlSAX2ResolveEntity,
+    xmlSAX2GetEntity,
+    xmlSAX2EntityDecl,
     NULL,
     NULL,
     NULL,
     NULL,
-    setDocumentLocator,
-    startDocument,
-    endDocument,
-    startElement,
-    endElement,
-    reference,
-    characters,
-    ignorableWhitespace,
+    xmlSAX2SetDocumentLocator,
+    xmlSAX2StartDocument,
+    xmlSAX2EndDocument,
+    xmlSAX2StartElement,
+    xmlSAX2EndElement,
+    xmlSAX2Reference,
+    xmlSAX2Characters,
+    xmlSAX2IgnorableWhitespace,
     NULL,
-    comment,
+    xmlSAX2Comment,
     xmlParserWarning,
     xmlParserError,
     xmlParserError,
-    getParameterEntity,
+    xmlSAX2GetParameterEntity,
     NULL,
     NULL,
-    0
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL
 };
 #endif /* LIBXML_DOCB_ENABLED */
 
diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am
index 279fb57..ff7f4f3 100644
--- a/include/libxml/Makefile.am
+++ b/include/libxml/Makefile.am
@@ -40,7 +40,8 @@
 		xmlunicode.h \
 		xmlreader.h \
 		relaxng.h \
-		dict.h
+		dict.h \
+		SAX2.h
 
 install-exec-hook:
 	$(mkinstalldirs) $(DESTDIR)$(xmlincdir)
diff --git a/include/libxml/SAX.h b/include/libxml/SAX.h
index d96d9e9..05cb9f8 100644
--- a/include/libxml/SAX.h
+++ b/include/libxml/SAX.h
@@ -119,9 +119,6 @@
 #ifdef LIBXML_DOCB_ENABLED
 void		initdocbDefaultSAXHandler	(xmlSAXHandler *hdlr);
 #endif
-void		xmlDefaultSAXHandlerInit	(void);
-void		htmlDefaultSAXHandlerInit	(void);
-void		docbDefaultSAXHandlerInit	(void);
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/libxml/SAX2.h b/include/libxml/SAX2.h
new file mode 100644
index 0000000..f2b1e19
--- /dev/null
+++ b/include/libxml/SAX2.h
@@ -0,0 +1,125 @@
+/*
+ * SAX.h : Default SAX2 handler interfaces to build a tree.
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel Veillard <daniel@veillard.com>
+ */
+
+
+#ifndef __XML_SAX2_H__
+#define __XML_SAX2_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libxml/parser.h>
+#include <libxml/xlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+const xmlChar *	xmlSAX2GetPublicId		(void *ctx);
+const xmlChar *	xmlSAX2GetSystemId		(void *ctx);
+void		xmlSAX2SetDocumentLocator	(void *ctx,
+						 xmlSAXLocatorPtr loc);
+    
+int		xmlSAX2GetLineNumber		(void *ctx);
+int		xmlSAX2GetColumnNumber		(void *ctx);
+
+int		xmlSAX2IsStandalone		(void *ctx);
+int		xmlSAX2HasInternalSubset	(void *ctx);
+int		xmlSAX2HasExternalSubset	(void *ctx);
+
+void		xmlSAX2InternalSubset		(void *ctx,
+						 const xmlChar *name,
+						 const xmlChar *ExternalID,
+						 const xmlChar *SystemID);
+void		xmlSAX2ExternalSubset		(void *ctx,
+						 const xmlChar *name,
+						 const xmlChar *ExternalID,
+						 const xmlChar *SystemID);
+xmlEntityPtr	xmlSAX2GetEntity		(void *ctx,
+						 const xmlChar *name);
+xmlEntityPtr	xmlSAX2GetParameterEntity	(void *ctx,
+						 const xmlChar *name);
+xmlParserInputPtr xmlSAX2ResolveEntity		(void *ctx,
+						 const xmlChar *publicId,
+						 const xmlChar *systemId);
+
+void		xmlSAX2EntityDecl		(void *ctx,
+						 const xmlChar *name,
+						 int type,
+						 const xmlChar *publicId,
+						 const xmlChar *systemId,
+						 xmlChar *content);
+void		xmlSAX2AttributeDecl		(void *ctx,
+						 const xmlChar *elem,
+						 const xmlChar *fullname,
+						 int type,
+						 int def,
+						 const xmlChar *defaultValue,
+						 xmlEnumerationPtr tree);
+void		xmlSAX2ElementDecl		(void *ctx,
+						 const xmlChar *name,
+						 int type,
+						 xmlElementContentPtr content);
+void		xmlSAX2NotationDecl		(void *ctx,
+						 const xmlChar *name,
+						 const xmlChar *publicId,
+						 const xmlChar *systemId);
+void		xmlSAX2UnparsedEntityDecl	(void *ctx,
+						 const xmlChar *name,
+						 const xmlChar *publicId,
+						 const xmlChar *systemId,
+						 const xmlChar *notationName);
+
+void		xmlSAX2StartDocument		(void *ctx);
+void		xmlSAX2EndDocument		(void *ctx);
+void		xmlSAX2StartElement		(void *ctx,
+						 const xmlChar *fullname,
+						 const xmlChar **atts);
+void		xmlSAX2EndElement		(void *ctx,
+						 const xmlChar *name);
+void		xmlSAX2Reference		(void *ctx,
+						 const xmlChar *name);
+void		xmlSAX2Characters		(void *ctx,
+						 const xmlChar *ch,
+						 int len);
+void		xmlSAX2IgnorableWhitespace	(void *ctx,
+						 const xmlChar *ch,
+						 int len);
+void		xmlSAX2ProcessingInstruction	(void *ctx,
+						 const xmlChar *target,
+						 const xmlChar *data);
+void		xmlSAX2GlobalNamespace		(void *ctx,
+						 const xmlChar *href,
+						 const xmlChar *prefix);
+void		xmlSAX2SetNamespace		(void *ctx,
+						 const xmlChar *name);
+xmlNsPtr	xmlSAX2GetNamespace		(void *ctx);
+int		xmlSAX2CheckNamespace		(void *ctx,
+						 xmlChar *nameSpace);
+void		xmlSAX2NamespaceDecl		(void *ctx,
+						 const xmlChar *href,
+						 const xmlChar *prefix);
+void		xmlSAX2Comment			(void *ctx,
+						 const xmlChar *value);
+void		xmlSAX2CDataBlock		(void *ctx,
+						 const xmlChar *value,
+						 int len);
+
+void		xmlSAX2InitDefaultSAXHandler    (xmlSAXHandler *hdlr,
+						 int warning);
+#ifdef LIBXML_HTML_ENABLED
+void		xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr);
+#endif
+#ifdef LIBXML_DOCB_ENABLED
+void		xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr);
+#endif
+void		xmlDefaultSAXHandlerInit	(void);
+void		htmlDefaultSAXHandlerInit	(void);
+void		docbDefaultSAXHandlerInit	(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* __XML_SAX2_H__ */
diff --git a/include/libxml/globals.h b/include/libxml/globals.h
index 3a832f6..717b6df 100644
--- a/include/libxml/globals.h
+++ b/include/libxml/globals.h
@@ -15,7 +15,7 @@
 
 #include <libxml/parser.h>
 #include <libxml/xmlerror.h>
-#include <libxml/SAX.h>
+#include <libxml/SAX2.h>
 #include <libxml/xmlmemory.h>
 
 #ifdef __cplusplus
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index ac3f055..43dbe35 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -574,6 +574,7 @@
  * Returns 1 if true
  */
 typedef int (*hasInternalSubsetSAXFunc) (void *ctx);
+
 /**
  * hasExternalSubsetSAXFunc:
  * @ctx:  the user data (XML parser context)
@@ -584,6 +585,80 @@
  */
 typedef int (*hasExternalSubsetSAXFunc) (void *ctx);
 
+/************************************************************************
+ *									*
+ *			The SAX version 2 API extensions		*
+ *									*
+ ************************************************************************/
+/**
+ * XML_SAX2_MAGIC:
+ *
+ * Special constant found in SAX2 blocks initialized fields
+ */
+#define XML_SAX2_MAGIC 0xDEEDBEAF
+
+/**
+ * startElementNsSAX2Func:
+ * @ctx:  the user data (XML parser context)
+ * @localname:  the local name of the element
+ * @prefix:  the element namespace prefix if available
+ * @URI:  the element namespace name if available
+ * @nb_namespaces:  number of namespace definitions on that node
+ * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
+ * @nb_attributes:  the number of attributes on that node
+ *
+ * SAX2 callback when an element start has been detected by the parser.
+ * It provides the namespace informations for the element, as well as
+ * the new namespace declarations on the element.
+ * The number of attributes is given in this callback but the attributes
+ * themselves will be provided as separate callbacks.
+ */
+
+typedef void (*startElementNsSAX2Func) (void *ctx,
+					const xmlChar *localname,
+					const xmlChar *prefix,
+					const xmlChar *URI,
+					int nb_namespaces,
+					const xmlChar **namespaces,
+					int nb_attributes);
+ 
+/**
+ * endElementNsSAX2Func:
+ * @ctx:  the user data (XML parser context)
+ * @localname:  the local name of the element
+ * @prefix:  the element namespace prefix if available
+ * @URI:  the element namespace name if available
+ *
+ * SAX2 callback when an element end has been detected by the parser.
+ * It provides the namespace informations for the element.
+ */
+
+typedef void (*endElementNsSAX2Func)   (void *ctx,
+					const xmlChar *localname,
+					const xmlChar *prefix,
+					const xmlChar *URI);
+
+/**
+ * attributeNsSAX2Func:
+ * @ctx:  the user data (XML parser context)
+ * @localname:  the local name of the attribute
+ * @prefix:  the attribute namespace prefix if available
+ * @URI:  the attribute namespace name if available
+ * @value:  pointer to the attribute value string
+ * @valuelen:  lenght of the attribute value string in bytes
+ *
+ * SAX2 callback when an attribute has been detected by the parser.
+ * It provides the namespace informations for the attribute, as well as
+ * the value of the attribute (note that @value may not be zero terminated
+ * and use of the @valuelen is needed to find the value end).
+ */
+typedef void (*attributeNsSAX2Func)    (void *ctx,
+					const xmlChar *localname,
+					const xmlChar *prefix,
+					const xmlChar *URI,
+					const xmlChar *value,
+					int valuelen);
+
 struct _xmlSAXHandler {
     internalSubsetSAXFunc internalSubset;
     isStandaloneSAXFunc isStandalone;
@@ -613,6 +688,11 @@
     cdataBlockSAXFunc cdataBlock;
     externalSubsetSAXFunc externalSubset;
     int initialized;
+    /* The following fields are extensions available only on version 2 */
+    void *_private;
+    startElementNsSAX2Func startElementNs;
+    endElementNsSAX2Func endElementNs;
+    attributeNsSAX2Func attributeNs;
 };
 
 /**
diff --git a/parser.c b/parser.c
index 4eb5265..814ceea 100644
--- a/parser.c
+++ b/parser.c
@@ -3682,8 +3682,8 @@
 			ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 					    BAD_CAST "fake", NULL, NULL);
 
-		    entityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
-			       NULL, NULL, value);
+		    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
+			              NULL, NULL, value);
 		}
 	    } else {
 	        URI = xmlParseExternalID(ctxt, &literal, 1);
@@ -3775,9 +3775,9 @@
 			if (ctxt->myDoc->intSubset == NULL)
 			    ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
 						BAD_CAST "fake", NULL, NULL);
-			entityDecl(ctxt, name,
-				    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
-				    literal, URI, NULL);
+			xmlSAX2EntityDecl(ctxt, name,
+				          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
+				          literal, URI, NULL);
 		    }
 		}
 	    }
@@ -3816,7 +3816,7 @@
 		    (ctxt->sax->getEntity != NULL))
 		    cur = ctxt->sax->getEntity(ctxt->userData, name);
 		if ((cur == NULL) && (ctxt->userData==ctxt)) {
-		    cur = getEntity(ctxt, name);
+		    cur = xmlSAX2GetEntity(ctxt, name);
 		}
 	    }
             if (cur != NULL) {
@@ -5746,7 +5746,7 @@
 		        ent = xmlGetPredefinedEntity(name);
 		    if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
 			(ctxt->userData==ctxt)) {
-			ent = getEntity(ctxt, name);
+			ent = xmlSAX2GetEntity(ctxt, name);
 		    }
 		}
 		/*
@@ -5942,7 +5942,7 @@
 		    if (ent == NULL)
 		        ent = xmlGetPredefinedEntity(name);
 		    if ((ent == NULL) && (ctxt->userData==ctxt)) {
-			ent = getEntity(ctxt, name);
+			ent = xmlSAX2GetEntity(ctxt, name);
 		    }
 		}
 		/*