Completed/revamped the SAX support, removed old namespace suppport, Daniel
diff --git a/ChangeLog b/ChangeLog
index 19b8c69..de4e14b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Mon Apr  5 14:14:40 CEST 1999 Daniel Veillard <Daniel.Veillard@w3.org>
+
+	* parser.[ch] tree.[ch] SAX.c, parserInternals.h valid.[ch]:
+	  large revamping of the parser to use SAX callbacks
+	  http://www.megginson.com/SAX/ (or at least a C like interface
+	  a la Expat). It's now possible to set up your own callbacks
+	  and the parser will not build a DOM tree.
+	* test/* result/*: updated the test suite, I finally removed
+	  the old Namespace draft support (PI based).
+
 Fri Apr  2 17:57:32 CEST 1999 Daniel Veillard <Daniel.Veillard@w3.org>
 
 	* Makefile.am: added test result to EXTRA_DIST for make tests
diff --git a/SAX.c b/SAX.c
index b4a6cb1..7f9ea18 100644
--- a/SAX.c
+++ b/SAX.c
@@ -10,6 +10,8 @@
 #include <stdlib.h>
 #include "tree.h"
 #include "parser.h"
+#include "parserInternals.h"
+#include "valid.h"
 #include "entities.h"
 #include "xml-error.h"
 
@@ -81,6 +83,65 @@
 };
 
 /**
+ * isStandalone:
+ * @ctxt:  An XML parser context
+ *
+ * Is this document tagged standalone ?
+ *
+ * Returns 1 if true
+ */
+int
+isStandalone(xmlParserCtxtPtr ctxt)
+{
+    return(ctxt->myDoc->standalone == 1);
+}
+
+/**
+ * hasInternalSubset:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ *
+ * Returns 1 if true
+ */
+int
+hasInternalSubset(xmlParserCtxtPtr ctxt)
+{
+    return(ctxt->myDoc->intSubset != NULL);
+}
+
+/**
+ * hasExternalSubset:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an external subset
+ *
+ * Returns 1 if true
+ */
+int
+hasExternalSubset(xmlParserCtxtPtr ctxt)
+{
+    return(ctxt->myDoc->extSubset != NULL);
+}
+
+/**
+ * hasInternalSubset:
+ * @ctxt:  An XML parser context
+ *
+ * Does this document has an internal subset
+ */
+void
+internalSubset(xmlParserCtxtPtr ctxt, const CHAR *name,
+	       const CHAR *ExternalID, const CHAR *SystemID)
+{
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.internalSubset(%s, %s, %s)\n",
+            name, ExternalID, SystemID);
+#endif
+    xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
+}
+
+/**
  * resolveEntity:
  * @ctxt:  An XML parser context
  * @publicId: The public ID of the entity
@@ -102,10 +163,107 @@
     fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
 #endif
 
+    /*
+     * TODO : not 100% sure that the appropriate handling in that case.
+     */
     return(NULL);
 }
 
 /**
+ * getEntity:
+ * @ctxt:  An XML parser context
+ * @name: The entity name
+ *
+ * Get an entity by name
+ *
+ * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
+ */
+xmlEntityPtr
+getEntity(xmlParserCtxtPtr ctxt, const CHAR *name)
+{
+    xmlEntityPtr ret;
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.getEntity(%s)\n", name);
+#endif
+
+    ret = xmlGetDocEntity(ctxt->myDoc, name);
+    return(ret);
+}
+
+
+/**
+ * entityDecl:
+ * @ctxt:  An 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
+entityDecl(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
+          const CHAR *publicId, const CHAR *systemId, CHAR *content)
+{
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.entityDecl(%s, %d, %s, %s, %s)\n",
+            name, type, publicId, systemId, content);
+#endif
+    xmlAddDocEntity(ctxt->myDoc, name, type, publicId, systemId, content);
+}
+
+/**
+ * attributeDecl:
+ * @ctxt:  An XML parser context
+ * @name:  the attribute name 
+ * @type:  the attribute type 
+ * @publicId: The public ID of the attribute
+ * @systemId: The system ID of the attribute
+ * @content: the attribute value (without processing).
+ *
+ * An attribute definition has been parsed
+ */
+void
+attributeDecl(xmlParserCtxtPtr ctxt, const CHAR *elem, const CHAR *name,
+              int type, int def, const CHAR *defaultValue,
+	      xmlEnumerationPtr tree)
+{
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
+            elem, name, type, def, defaultValue);
+#endif
+    xmlAddAttributeDecl(ctxt->myDoc->intSubset, elem, name, type, def,
+                        defaultValue, tree);
+}
+
+/**
+ * elementDecl:
+ * @ctxt:  An XML parser context
+ * @name:  the element name 
+ * @type:  the element type 
+ * @publicId: The public ID of the element
+ * @systemId: The system ID of the element
+ * @content: the element value (without processing).
+ *
+ * An element definition has been parsed
+ */
+void
+elementDecl(xmlParserCtxtPtr ctxt, const CHAR *name, int type,
+	    xmlElementContentPtr content)
+{
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.elementDecl(%s, %d, ...)\n",
+            name, type);
+#endif
+    xmlAddElementDecl(ctxt->myDoc->intSubset, name, type, content);
+}
+
+/**
  * notationDecl:
  * @ctxt:  An XML parser context
  * @name: The name of the notation
@@ -122,6 +280,7 @@
 #ifdef DEBUG_SAX
     fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
 #endif
+    xmlAddNotationDecl(ctxt->myDoc->intSubset, name, publicId, systemId);
 }
 
 /**
@@ -171,9 +330,19 @@
 void
 startDocument(xmlParserCtxtPtr ctxt)
 {
+    xmlDocPtr doc;
+
 #ifdef DEBUG_SAX
     fprintf(stderr, "SAX.startDocument()\n");
 #endif
+    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;
+    }
 }
 
 /**
@@ -191,19 +360,151 @@
 }
 
 /**
+ * attribute:
+ * @ctxt:  An XML parser context
+ * @name:  The attribute name
+ * @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.
+ */
+void
+attribute(xmlParserCtxtPtr ctxt, const CHAR *fullname, const CHAR *value)
+{
+    xmlAttrPtr ret;
+    CHAR *name;
+    CHAR *ns;
+
+/****************
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.attribute(%s, %s)\n", fullname, value);
+#endif
+ ****************/
+    /*
+     * Split the full name into a namespace prefix and the tag name
+     */
+    name = xmlSplitQName(fullname, &ns);
+
+    /*
+     * Check whether it's a namespace definition
+     */
+    if ((ns == NULL) &&
+        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
+        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
+	/* a default namespace definition */
+	xmlNewNs(ctxt->node, value, NULL);
+	if (name != NULL) 
+	    free(name);
+	return;
+    }
+    if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
+        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
+	/* a standard namespace definition */
+	xmlNewNs(ctxt->node, value, name);
+	free(ns);
+	if (name != NULL) 
+	    free(name);
+	return;
+    }
+
+    ret = xmlNewProp(ctxt->node, name, NULL);
+    if (ret != NULL)
+	ret->val = xmlStringGetNodeList(ctxt->myDoc, value);
+    if (name != NULL) 
+	free(name);
+    if (ns != NULL) 
+	free(ns);
+}
+
+/**
  * startElement:
  * @ctxt:  An XML parser context
  * @name:  The element name
+ * @atts:  An array of name/value attributes pairs, NULL terminated
  *
  * called when an opening tag has been processed.
  * TODO We currently have a small pblm with the arguments ...
  */
 void
-startElement(xmlParserCtxtPtr ctxt, const CHAR *name)
+startElement(xmlParserCtxtPtr ctxt, const CHAR *fullname, const CHAR **atts)
 {
+    xmlNodePtr ret;
+    xmlNodePtr parent = ctxt->node;
+    xmlNsPtr ns;
+    CHAR *name;
+    CHAR *prefix;
+    const CHAR *att;
+    const CHAR *value;
+
+    int i;
+
 #ifdef DEBUG_SAX
-    fprintf(stderr, "SAX.startElement(%s)\n", name);
+    fprintf(stderr, "SAX.startElement(%s)\n", fullname);
 #endif
+    /*
+     * Split the full name into a namespace prefix and the tag name
+     */
+    name = xmlSplitQName(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 = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
+    if (ret == NULL) return;
+    if (ctxt->myDoc->root == NULL)
+        ctxt->myDoc->root = ret;
+
+    /*
+     * We are parsing a new node.
+     */
+    nodePush(ctxt, ret);
+
+    /*
+     * Link the child element
+     */
+    if (parent != NULL)
+	xmlAddChild(parent, ctxt->node);
+
+    /*
+     * process all the attributes.
+     */
+    if (atts != NULL) {
+        i = 0;
+	att = atts[i++];
+	value = atts[i++];
+        while ((att != NULL) && (value != NULL)) {
+	    /*
+	     * Handle one pair of attribute/value
+	     */
+	    attribute(ctxt, att, value);
+
+	    /*
+	     * Next ones
+	     */
+	    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);
+    xmlSetNs(ret, ns);
+
+    if (prefix != NULL)
+	free(prefix);
+    if (name != NULL)
+	free(name);
+
 }
 
 /**
@@ -216,47 +517,65 @@
 void
 endElement(xmlParserCtxtPtr ctxt, const CHAR *name)
 {
+    xmlParserNodeInfo node_info;
+    xmlNodePtr cur = ctxt->node;
+
 #ifdef DEBUG_SAX
-    fprintf(stderr, "SAX.endElement(%s)\n", name);
+    if (name == NULL)
+        fprintf(stderr, "SAX.endElement(NULL)\n");
+    else
+	fprintf(stderr, "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);
+    }
+
+    /*
+     * end of parsing of this node.
+     */
+    nodePop(ctxt);
 }
 
 /**
- * attribute:
+ * reference:
  * @ctxt:  An XML parser context
- * @name:  The attribute name
- * @value:  The attribute value
+ * @name:  The entity name
  *
- * called when an attribute 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.
+ * called when an entity reference is detected. 
  */
 void
-attribute(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value)
+reference(xmlParserCtxtPtr ctxt, const CHAR *name)
 {
+    xmlNodePtr ret;
+
 #ifdef DEBUG_SAX
-    fprintf(stderr, "SAX.attribute(%s, %s)\n", name, value);
+    fprintf(stderr, "SAX.reference(%s)\n", name);
 #endif
+    ret = xmlNewReference(ctxt->myDoc, name);
+    xmlAddChild(ctxt->node, ret);
 }
 
 /**
  * characters:
  * @ctxt:  An XML parser context
  * @ch:  a CHAR string
- * @start: the first char in the string
  * @len: the number of CHAR
  *
  * receiving some chars from the parser.
  * Question: how much at a time ???
  */
 void
-characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
+characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
 {
     xmlNodePtr lastChild;
 
 #ifdef DEBUG_SAX
-    fprintf(stderr, "SAX.characters(%.30s, %d, %d)\n", ch, start, len);
+    fprintf(stderr, "SAX.characters(%.30s, %d)\n", ch, len);
 #endif
     /*
      * Handle the data if any. If there is no child
@@ -266,12 +585,12 @@
 
     lastChild = xmlGetLastChild(ctxt->node);
     if (lastChild == NULL)
-	xmlNodeAddContentLen(ctxt->node, &ch[start], len);
+	xmlNodeAddContentLen(ctxt->node, ch, len);
     else {
 	if (xmlNodeIsText(lastChild))
-	    xmlTextConcat(lastChild, &ch[start], len);
+	    xmlTextConcat(lastChild, ch, len);
 	else {
-	    lastChild = xmlNewTextLen(&ch[start], len);
+	    lastChild = xmlNewTextLen(ch, len);
 	    xmlAddChild(ctxt->node, lastChild);
 	}
     }
@@ -281,17 +600,16 @@
  * ignorableWhitespace:
  * @ctxt:  An XML parser context
  * @ch:  a CHAR string
- * @start: the first char in the string
  * @len: the number of CHAR
  *
  * receiving some ignorable whitespaces from the parser.
  * Question: how much at a time ???
  */
 void
-ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
+ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int len)
 {
 #ifdef DEBUG_SAX
-    fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d, %d)\n", ch, start, len);
+    fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d)\n", ch, len);
 #endif
 }
 
@@ -313,19 +631,173 @@
 #endif
 }
 
+/**
+ * globalNamespace:
+ * @ctxt:  An XML parser context
+ * @href:  the namespace associated URN
+ * @prefix: the namespace prefix
+ *
+ * An old global namespace has been parsed.
+ */
+void
+globalNamespace(xmlParserCtxtPtr ctxt, const CHAR *href, const CHAR *prefix)
+{
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.globalNamespace(%s, %s)\n", href, prefix);
+#endif
+    xmlNewGlobalNs(ctxt->myDoc, href, prefix);
+}
+
+/**
+ * setNamespace:
+ * @ctxt:  An XML parser context
+ * @name:  the namespace prefix
+ *
+ * Set the current element namespace.
+ */
+void
+setNamespace(xmlParserCtxtPtr ctxt, const CHAR *name)
+{
+    xmlNsPtr ns;
+    xmlNodePtr parent;
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "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);
+}
+
+/**
+ * getNamespace:
+ * @ctxt:  An XML parser context
+ *
+ * Get the current element namespace.
+ */
+xmlNsPtr
+getNamespace(xmlParserCtxtPtr ctxt)
+{
+    xmlNsPtr ret;
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.getNamespace()\n");
+#endif
+    ret = ctxt->node->ns;
+    return(ret);
+}
+
+/**
+ * checkNamespace:
+ * @ctxt:  An XML parser context
+ * @namespace: the namespace to check against
+ *
+ * Check that the current element namespace is the same as the
+ * one read upon parsing.
+ */
+int
+checkNamespace(xmlParserCtxtPtr ctxt, CHAR *namespace)
+{
+    xmlNodePtr cur = ctxt->node;
+
+#ifdef DEBUG_SAX
+    fprintf(stderr, "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 (strcmp(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);
+}
+
+/**
+ * namespaceDecl:
+ * @ctxt:  An XML parser context
+ * @href:  the namespace associated URN
+ * @prefix: the namespace prefix
+ *
+ * A namespace has been parsed.
+ */
+void
+namespaceDecl(xmlParserCtxtPtr ctxt, const CHAR *href, const CHAR *prefix)
+{
+#ifdef DEBUG_SAX
+    if (prefix == NULL)
+	fprintf(stderr, "SAX.namespaceDecl(%s, NULL)\n", href);
+    else
+	fprintf(stderr, "SAX.namespaceDecl(%s, %s)\n", href, prefix);
+#endif
+    xmlNewNs(ctxt->node, href, prefix);
+}
+
+/**
+ * comment:
+ * @ctxt:  An XML parser context
+ * @value:  the comment content
+ *
+ * A comment has been parsed.
+ */
+void
+comment(xmlParserCtxtPtr ctxt, const CHAR *value)
+{
+#ifdef DEBUG_SAX
+    fprintf(stderr, "SAX.comment(%s)\n", value);
+#endif
+    xmlNewDocComment(ctxt->myDoc, value);
+}
+
 xmlSAXHandler xmlDefaultSAXHandler = {
+    internalSubset,
+    isStandalone,
+    hasInternalSubset,
+    hasExternalSubset,
     resolveEntity,
+    getEntity,
+    entityDecl,
     notationDecl,
+    attributeDecl,
+    elementDecl,
     unparsedEntityDecl,
     setDocumentLocator,
     startDocument,
     endDocument,
     startElement,
     endElement,
-    attribute,
+    reference,
     characters,
     ignorableWhitespace,
     processingInstruction,
+    comment,
     xmlParserWarning,
     xmlParserError,
     xmlParserError,
@@ -339,7 +811,15 @@
 void
 xmlDefaultSAXHandlerInit(void)
 {
+    xmlDefaultSAXHandler.internalSubset = internalSubset;
+    xmlDefaultSAXHandler.isStandalone = isStandalone;
+    xmlDefaultSAXHandler.hasInternalSubset = hasInternalSubset;
+    xmlDefaultSAXHandler.hasExternalSubset = hasExternalSubset;
     xmlDefaultSAXHandler.resolveEntity = resolveEntity;
+    xmlDefaultSAXHandler.getEntity = getEntity;
+    xmlDefaultSAXHandler.entityDecl = entityDecl;
+    xmlDefaultSAXHandler.attributeDecl = attributeDecl;
+    xmlDefaultSAXHandler.elementDecl = elementDecl;
     xmlDefaultSAXHandler.notationDecl = notationDecl;
     xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
     xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
@@ -347,10 +827,11 @@
     xmlDefaultSAXHandler.endDocument = endDocument;
     xmlDefaultSAXHandler.startElement = startElement;
     xmlDefaultSAXHandler.endElement = endElement;
-    xmlDefaultSAXHandler.attribute = attribute;
+    xmlDefaultSAXHandler.reference = reference;
     xmlDefaultSAXHandler.characters = characters;
     xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
     xmlDefaultSAXHandler.processingInstruction = processingInstruction;
+    xmlDefaultSAXHandler.comment = comment;
     xmlDefaultSAXHandler.warning = xmlParserWarning;
     xmlDefaultSAXHandler.error = xmlParserError;
     xmlDefaultSAXHandler.fatalError = xmlParserError;
diff --git a/entities.h b/entities.h
index 99ce163..8977054 100644
--- a/entities.h
+++ b/entities.h
@@ -9,7 +9,7 @@
 #ifndef __XML_ENTITIES_H__
 #define __XML_ENTITIES_H__
 
-#include "parser.h"
+#include "tree.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -56,6 +56,8 @@
  * External functions :
  */
 
+#include "parser.h"
+
 void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content);
 void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
diff --git a/include/libxml/entities.h b/include/libxml/entities.h
index 99ce163..8977054 100644
--- a/include/libxml/entities.h
+++ b/include/libxml/entities.h
@@ -9,7 +9,7 @@
 #ifndef __XML_ENTITIES_H__
 #define __XML_ENTITIES_H__
 
-#include "parser.h"
+#include "tree.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -56,6 +56,8 @@
  * External functions :
  */
 
+#include "parser.h"
+
 void xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content);
 void xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 3dc8445..3e433a2 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -51,8 +51,12 @@
 
 typedef struct _xmlParserCtxt {
     struct xmlSAXHandler *sax;        /* The SAX handler */
-    xmlDocPtr doc;                    /* the document being built */
+    void            *userData;        /* the document being built */
+    xmlDocPtr           myDoc;        /* the document being built */
     int            wellFormed;        /* is the document well formed */
+    const CHAR     *version;	      /* the XML version string */
+    const CHAR     *encoding;         /* encoding, if any */
+    int             standalone;       /* standalone document */
 
     /* Input stream stack */
     xmlParserInputPtr  input;         /* Current input stream */
@@ -89,10 +93,24 @@
  * a SAX Exception.
  */
 
+#include "entities.h"
+
 typedef xmlParserInputPtr (*resolveEntitySAXFunc) (xmlParserCtxtPtr ctxt,
 			    const CHAR *publicId, const CHAR *systemId);
+typedef void (*internalSubsetSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
+                            const CHAR *ExternalID, const CHAR *SystemID);
+typedef xmlEntityPtr (*getEntitySAXFunc) (xmlParserCtxtPtr ctxt,
+                            const CHAR *name);
+typedef void (*entityDeclSAXFunc) (xmlParserCtxtPtr ctxt,
+                            const CHAR *name, int type, const CHAR *publicId,
+			    const CHAR *systemId, CHAR *content);
 typedef void (*notationDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name,
 			    const CHAR *publicId, const CHAR *systemId);
+typedef void (*attributeDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *elem,
+                            const CHAR *name, int type, int def,
+			    const CHAR *defaultValue, xmlEnumerationPtr tree);
+typedef void (*elementDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name,
+			    int type, xmlElementContentPtr content);
 typedef void (*unparsedEntityDeclSAXFunc)(xmlParserCtxtPtr ctxt,
                             const CHAR *name, const CHAR *publicId,
 			    const CHAR *systemId, const CHAR *notationName);
@@ -100,33 +118,48 @@
                             xmlSAXLocatorPtr loc);
 typedef void (*startDocumentSAXFunc) (xmlParserCtxtPtr ctxt);
 typedef void (*endDocumentSAXFunc) (xmlParserCtxtPtr ctxt);
-typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
+typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
+                            const CHAR **atts);
 typedef void (*endElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
 typedef void (*attributeSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
                                   const CHAR *value);
+typedef void (*referenceSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
 typedef void (*charactersSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *ch,
-		            int start, int len);
+		            int len);
 typedef void (*ignorableWhitespaceSAXFunc) (xmlParserCtxtPtr ctxt,
-			    const CHAR *ch, int start, int len);
+			    const CHAR *ch, int len);
 typedef void (*processingInstructionSAXFunc) (xmlParserCtxtPtr ctxt,
                             const CHAR *target, const CHAR *data);
+typedef void (*commentSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *value);
 typedef void (*warningSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
 typedef void (*errorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
 typedef void (*fatalErrorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
+typedef int (*isStandaloneSAXFunc) (xmlParserCtxtPtr ctxt);
+typedef int (*hasInternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt);
+typedef int (*hasExternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt);
 
 typedef struct xmlSAXHandler {
+    internalSubsetSAXFunc internalSubset;
+    isStandaloneSAXFunc isStandalone;
+    hasInternalSubsetSAXFunc hasInternalSubset;
+    hasExternalSubsetSAXFunc hasExternalSubset;
     resolveEntitySAXFunc resolveEntity;
+    getEntitySAXFunc getEntity;
+    entityDeclSAXFunc entityDecl;
     notationDeclSAXFunc notationDecl;
+    attributeDeclSAXFunc attributeDecl;
+    elementDeclSAXFunc elementDecl;
     unparsedEntityDeclSAXFunc unparsedEntityDecl;
     setDocumentLocatorSAXFunc setDocumentLocator;
     startDocumentSAXFunc startDocument;
     endDocumentSAXFunc endDocument;
     startElementSAXFunc startElement;
     endElementSAXFunc endElement;
-    attributeSAXFunc attribute;
+    referenceSAXFunc reference;
     charactersSAXFunc characters;
     ignorableWhitespaceSAXFunc ignorableWhitespace;
     processingInstructionSAXFunc processingInstruction;
+    commentSAXFunc comment;
     warningSAXFunc warning;
     errorSAXFunc error;
     fatalErrorSAXFunc fatalError;
diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h
index 28ef54d..75e9e13 100644
--- a/include/libxml/parserInternals.h
+++ b/include/libxml/parserInternals.h
@@ -529,6 +529,8 @@
  * Namespaces.
  */
 CHAR *
+xmlSplitQName(const CHAR *name, CHAR **prefix);
+CHAR *
 xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt);
 CHAR *
 xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix);
@@ -558,7 +560,7 @@
 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata);
 CHAR *
 xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict);
-xmlNodePtr 
+void 
 xmlParseComment(xmlParserCtxtPtr ctxt, int create);
 CHAR *
 xmlParsePITarget(xmlParserCtxtPtr ctxt);
@@ -601,17 +603,17 @@
 xmlParsePEReference(xmlParserCtxtPtr ctxt);
 void
 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt);
-xmlAttrPtr 
-xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node);
-xmlNodePtr 
+CHAR *
+xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value);
+void
 xmlParseStartTag(xmlParserCtxtPtr ctxt);
 void
-xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr);
+xmlParseEndTag(xmlParserCtxtPtr ctxt);
 void
 xmlParseCDSect(xmlParserCtxtPtr ctxt);
 void
 xmlParseContent(xmlParserCtxtPtr ctxt);
-xmlNodePtr 
+void
 xmlParseElement(xmlParserCtxtPtr ctxt);
 CHAR *
 xmlParseVersionNum(xmlParserCtxtPtr ctxt);
@@ -628,5 +630,12 @@
 void
 xmlParseMisc(xmlParserCtxtPtr ctxt);
 
+/*
+ * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP
+ */
+extern int nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value);
+extern xmlNodePtr nodePop(xmlParserCtxtPtr ctxt);
+extern int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value);
+extern xmlParserInputPtr inputPop(xmlParserCtxtPtr ctxt);
 
 #endif /* __XML_PARSER_INTERNALS_H__ */
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 4443836..3f00aa0 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -283,8 +283,8 @@
 xmlNodePtr xmlNewText(const CHAR *content);
 xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len);
 xmlNodePtr xmlNewTextLen(const CHAR *content, int len);
-xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
-xmlNodePtr xmlNewComment(CHAR *content);
+xmlNodePtr xmlNewDocComment(xmlDocPtr doc, const CHAR *content);
+xmlNodePtr xmlNewComment(const CHAR *content);
 xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
 xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
 xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index 14a7228..22c824a 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -54,8 +54,8 @@
 typedef xmlAttributeTable *xmlAttributeTablePtr;
 
 /* Notation */
-xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name,
-	       CHAR *PublicID, CHAR *SystemID);
+xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name,
+	       const CHAR *PublicID, const CHAR *SystemID);
 xmlNotationTablePtr xmlCopyNotationTable(xmlNotationTablePtr table);
 void xmlFreeNotationTable(xmlNotationTablePtr table);
 void xmlDumpNotationTable(xmlNotationTablePtr table);
@@ -66,7 +66,7 @@
 void xmlFreeElementContent(xmlElementContentPtr cur);
 
 /* Element */
-xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, 
+xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, 
                                        xmlElementContentPtr content);
 xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table);
 void xmlFreeElementTable(xmlElementTablePtr table);
@@ -78,9 +78,9 @@
 xmlEnumerationPtr xmlCopyEnumeration(xmlEnumerationPtr cur);
 
 /* Attribute */
-xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem,
-	       CHAR *name, int type, int def,
-	       CHAR *defaultValue, xmlEnumerationPtr tree);
+xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem,
+	       const CHAR *name, int type, int def,
+	       const CHAR *defaultValue, xmlEnumerationPtr tree);
 xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table);
 void xmlFreeAttributeTable(xmlAttributeTablePtr table);
 void xmlDumpAttributeTable(xmlAttributeTablePtr table);
diff --git a/parser.c b/parser.c
index 512611e..f1ea2fb 100644
--- a/parser.c
+++ b/parser.c
@@ -43,7 +43,7 @@
  */
 
 #define PUSH_AND_POP(type, name)					\
-int name##Push(xmlParserCtxtPtr ctxt, type value) {			\
+extern int name##Push(xmlParserCtxtPtr ctxt, type value) {		\
     if (ctxt->name##Nr >= ctxt->name##Max) {				\
 	ctxt->name##Max *= 2;						\
         ctxt->name##Tab = (void *) realloc(ctxt->name##Tab,		\
@@ -57,7 +57,7 @@
     ctxt->name = value;							\
     return(ctxt->name##Nr++);						\
 }									\
-type name##Pop(xmlParserCtxtPtr ctxt) {					\
+extern type name##Pop(xmlParserCtxtPtr ctxt) {				\
     type ret;								\
     if (ctxt->name##Nr <= 0) return(0);					\
     ctxt->name##Nr--;							\
@@ -496,6 +496,7 @@
         if (!(IS_BLANK(str[i]))) return(0);
 
     if (CUR != '<') return(0);
+    if (ctxt->node == NULL) return(0);
     lastChild = xmlGetLastChild(ctxt->node);
     if (lastChild == NULL) {
         if (ctxt->node->content != NULL) return(0);
@@ -540,15 +541,14 @@
     /*
      * Just handle the content as a set of chars.
      */
-    if (ctxt->sax != NULL)
-	ctxt->sax->characters(ctxt, entity->content, 0, len);
+    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
+	ctxt->sax->characters(ctxt, entity->content, len);
 
 }
 
 /*
  * Forward definition for recusive behaviour.
  */
-xmlNodePtr xmlParseElement(xmlParserCtxtPtr ctxt);
 CHAR *xmlParsePEReference(xmlParserCtxtPtr ctxt);
 CHAR *xmlParseReference(xmlParserCtxtPtr ctxt);
 
@@ -626,6 +626,61 @@
 }
 
 /**
+ * xmlSplitQName:
+ * @name:  an XML parser context
+ * @prefix:  a CHAR ** 
+ *
+ * parse an XML qualified name string
+ *
+ * [NS 5] QName ::= (Prefix ':')? LocalPart
+ *
+ * [NS 6] Prefix ::= NCName
+ *
+ * [NS 7] LocalPart ::= NCName
+ *
+ * Returns the function returns the local part, and prefix is updated
+ *   to get the Prefix if any.
+ */
+
+CHAR *
+xmlSplitQName(const CHAR *name, CHAR **prefix) {
+    CHAR *ret = NULL;
+    const CHAR *q;
+    const CHAR *cur = name;
+
+    *prefix = NULL;
+    if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL);
+    q = cur++;
+
+    while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
+           (*cur == '.') || (*cur == '-') ||
+	   (*cur == '_') ||
+	   (IS_COMBINING(*cur)) ||
+	   (IS_EXTENDER(*cur)))
+	cur++;
+    
+    ret = xmlStrndup(q, cur - q);
+
+    if (*cur == ':') {
+	cur++;
+	if (!IS_LETTER(*cur) && (*cur != '_')) return(ret);
+        *prefix = ret;
+
+	q = cur++;
+
+	while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
+	       (*cur == '.') || (*cur == '-') ||
+	       (*cur == '_') ||
+	       (IS_COMBINING(*cur)) ||
+	       (IS_EXTENDER(*cur)))
+	    cur++;
+	
+	ret = xmlStrndup(q, cur - q);
+    }
+
+    return(ret);
+}
+/**
  * xmlNamespaceParseNSDef:
  * @ctxt:  an XML parser context
  *
@@ -789,9 +844,10 @@
 
     /*
      * Register the DTD.
-     */
     if (href != NULL)
-        xmlNewGlobalNs(ctxt->doc, href, prefix);
+	if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
+	    ctxt->sax->globalNamespace(ctxt, href, prefix);
+     */
 
     if (prefix != NULL) free(prefix);
     if (href != NULL) free(href);
@@ -1228,10 +1284,13 @@
      * Ok the segment [q CUR_PTR] is to be consumed as chars.
      */
     if (ctxt->sax != NULL) {
-	if (areBlanks(ctxt, q, CUR_PTR - q))
-	    ctxt->sax->ignorableWhitespace(ctxt, q, 0, CUR_PTR - q);
-	else
-	    ctxt->sax->characters(ctxt, q, 0, CUR_PTR - q);
+	if (areBlanks(ctxt, q, CUR_PTR - q)) {
+	    if (ctxt->sax->ignorableWhitespace != NULL)
+		ctxt->sax->ignorableWhitespace(ctxt, q, CUR_PTR - q);
+	} else {
+	    if (ctxt->sax->characters != NULL)
+		ctxt->sax->characters(ctxt, q, CUR_PTR - q);
+        }
     }
 }
 
@@ -1342,15 +1401,9 @@
  *  must not occur within comments. "
  *
  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
- *
- * TODO: this should call a SAX function which will handle (or not) the
- *       creation of the comment !
- *
- * Returns the comment node, or NULL
  */
-xmlNodePtr
+void
 xmlParseComment(xmlParserCtxtPtr ctxt, int create) {
-    xmlNodePtr ret = NULL;
     const CHAR *q, *start;
     const CHAR *r;
     CHAR *val;
@@ -1359,7 +1412,7 @@
      * Check that there is a comment right here.
      */
     if ((CUR != '<') || (NXT(1) != '!') ||
-        (NXT(2) != '-') || (NXT(3) != '-')) return(NULL);
+        (NXT(2) != '-') || (NXT(3) != '-')) return;
 
     SKIP(4);
     start = q = CUR_PTR;
@@ -1385,11 +1438,11 @@
         NEXT;
 	if (create) {
 	    val = xmlStrndup(start, q - start);
-	    ret = xmlNewDocComment(ctxt->doc, val);
+	    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
+		ctxt->sax->comment(ctxt, val);
 	    free(val);
 	}
     }
-    return(ret);
 }
 
 /**
@@ -1449,54 +1502,29 @@
 	 */
         target = xmlParsePITarget(ctxt);
 	if (target != NULL) {
-	    /*
-	     * Support for the old Processing Instruction related to namespace.
-	     */
-	    if ((target[0] == 'n') && (target[1] == 'a') &&
-		(target[2] == 'm') && (target[3] == 'e') &&
-		(target[4] == 's') && (target[5] == 'p') &&
-		(target[6] == 'a') && (target[7] == 'c') &&
-		(target[8] == 'e')) {
-		xmlParseNamespace(ctxt);
-	    } else if ((target[0] == 'x') && (target[1] == 'm') &&
-		       (target[2] == 'l') && (target[3] == ':') &&
-		       (target[4] == 'n') && (target[5] == 'a') &&
-		       (target[6] == 'm') && (target[7] == 'e') &&
-		       (target[8] == 's') && (target[9] == 'p') &&
-		       (target[10] == 'a') && (target[11] == 'c') &&
-		       (target[12] == 'e')) {
-		xmlParseNamespace(ctxt);
+	    const CHAR *q = CUR_PTR;
+
+	    while (IS_CHAR(CUR) &&
+		   ((CUR != '?') || (NXT(1) != '>')))
+		NEXT;
+	    if (!IS_CHAR(CUR)) {
+		if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+		    ctxt->sax->error(ctxt,
+		      "xmlParsePI: PI %s never end ...\n", target);
+		ctxt->wellFormed = 0;
 	    } else {
-	        const CHAR *q = CUR_PTR;
+		CHAR *data;
 
-		while (IS_CHAR(CUR) &&
-		       ((CUR != '?') || (NXT(1) != '>')))
-		    NEXT;
-		if (!IS_CHAR(CUR)) {
-		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-		        ctxt->sax->error(ctxt,
-			  "xmlParsePI: PI %s never end ...\n", target);
-		    ctxt->wellFormed = 0;
-		} else {
-		    CHAR *data;
+		data = xmlStrndup(q, CUR_PTR - q);
+		SKIP(2);
 
-		    data = xmlStrndup(CUR_PTR, CUR_PTR - q);
-		    SKIP(2);
-
-		    /*
-		     * SAX: PI detected.
-		     */
-		    if (ctxt->sax) 
-			ctxt->sax->processingInstruction(ctxt, target, data);
-		    /*
-		     * Unknown PI, ignore it !
-		     */
-		    else 
-			xmlParserWarning(ctxt,
-		           "xmlParsePI : skipping unknown PI %s\n",
-				         target);
-	            free(data);
-                }
+		/*
+		 * SAX: PI detected.
+		 */
+		if ((ctxt->sax) &&
+		    (ctxt->sax->processingInstruction != NULL))
+		    ctxt->sax->processingInstruction(ctxt, target, data);
+		free(data);
 	    }
 	    free(target);
 	} else {
@@ -1577,7 +1605,8 @@
 
 	if (CUR == '>') {
 	    NEXT;
-	    xmlAddNotationDecl(ctxt->doc->intSubset, name, Pubid, Systemid);
+	    if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
+		ctxt->sax->notationDecl(ctxt, name, Pubid, Systemid);
 	} else {
 	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 		ctxt->sax->error(ctxt,
@@ -1662,14 +1691,16 @@
 	    if ((CUR == '"') || (CUR == '\''))
 	        value = xmlParseEntityValue(ctxt);
 		if (value) {
-		    xmlAddDocEntity(ctxt->doc, name,
+		    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
+			ctxt->sax->entityDecl(ctxt, name,
 		                    XML_INTERNAL_PARAMETER_ENTITY,
 				    NULL, NULL, value);
 		}
 	    else {
 	        URI = xmlParseExternalID(ctxt, &literal, 1);
 		if (URI) {
-		    xmlAddDocEntity(ctxt->doc, name,
+		    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
+			ctxt->sax->entityDecl(ctxt, name,
 		                    XML_EXTERNAL_PARAMETER_ENTITY,
 				    literal, URI, NULL);
 		}
@@ -1677,7 +1708,8 @@
 	} else {
 	    if ((CUR == '"') || (CUR == '\'')) {
 	        value = xmlParseEntityValue(ctxt);
-		xmlAddDocEntity(ctxt->doc, name,
+		if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
+		    ctxt->sax->entityDecl(ctxt, name,
 				XML_INTERNAL_GENERAL_ENTITY,
 				NULL, NULL, value);
 	    } else {
@@ -1701,11 +1733,13 @@
 		    }
 		    SKIP_BLANKS;
 		    ndata = xmlParseName(ctxt);
-		    xmlAddDocEntity(ctxt->doc, name,
+		    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
+			ctxt->sax->entityDecl(ctxt, name,
 				    XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
 				    literal, URI, ndata);
 		} else {
-		    xmlAddDocEntity(ctxt->doc, name,
+		    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
+			ctxt->sax->entityDecl(ctxt, name,
 				    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
 				    literal, URI, NULL);
 		}
@@ -2087,7 +2121,8 @@
 		    "xmlParseAttributeListDecl: detected internal error\n");
 		break;
 	    }
-	    xmlAddAttributeDecl(ctxt->doc->intSubset, elemName, attrName,
+	    if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
+		ctxt->sax->attributeDecl(ctxt, elemName, attrName,
 	                        type, def, defaultValue, tree);
 	    if (attrName != NULL)
 		free(attrName);
@@ -2511,7 +2546,8 @@
 	    ctxt->wellFormed = 0;
 	} else {
 	    NEXT;
-	    xmlAddElementDecl(ctxt->doc->intSubset, name, ret, content);
+	    if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
+	        ctxt->sax->elementDecl(ctxt, name, ret, content);
 	}
 	if (name != NULL) {
 	    free(name);
@@ -2632,7 +2668,7 @@
     CHAR *ret = NULL;
     const CHAR *q;
     CHAR *name;
-    xmlEntityPtr ent;
+    xmlEntityPtr ent = NULL;
     xmlParserInputPtr input = NULL;
 
     q = CUR_PTR;
@@ -2655,19 +2691,28 @@
 		 * then
 		 *   the entity referenced must have been declared
 		 *
-		 * TODO: to be double checked !!!
+		 * TODO: to be double checked !!! This is wrong !
 		 */
-		ent = xmlGetDocEntity(ctxt->doc, name);
-		if ((ctxt->doc->standalone == 1) ||
-		    ((ctxt->doc->intSubset == NULL) &&
-		     (ctxt->doc->extSubset == NULL))) {
-		    if (ent == NULL) {
-			if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-			    ctxt->sax->error(ctxt, 
-			         "Entity '%s' not defined\n", name);
-			ctxt->wellFormed = 0;
+		if (ctxt->sax != NULL) {
+		    if (ctxt->sax->getEntity != NULL)
+			ent = ctxt->sax->getEntity(ctxt, name);
+
+		    if (((ctxt->sax->isStandalone != NULL) &&
+		         ctxt->sax->isStandalone(ctxt) == 1) ||
+			(((ctxt->sax->hasInternalSubset == NULL) ||
+			  ctxt->sax->hasInternalSubset(ctxt) == 0) &&
+			 ((ctxt->sax->hasExternalSubset == NULL) ||
+			  ctxt->sax->hasExternalSubset(ctxt) == 0))) {
+			if (ent == NULL) {
+			    if ((ctxt->sax != NULL) &&
+			        (ctxt->sax->error != NULL))
+				ctxt->sax->error(ctxt, 
+				     "Entity '%s' not defined\n", name);
+			    ctxt->wellFormed = 0;
+			}
 		    }
-		}
+		} else
+		    ctxt->wellFormed = 0;
 
 		/*
 		 * Well Formedness Constraint :
@@ -2703,7 +2748,7 @@
 		 *   - get a new input stream
 		 *   - or keep the reference inline
 		 */
-		if (ctxt->sax)
+		if ((ctxt->sax) && (ctxt->sax->resolveEntity != NULL))
 		    input = ctxt->sax->resolveEntity(ctxt, NULL, name);
 		if (input != NULL)
 		    xmlPushInput(ctxt, input);
@@ -2768,7 +2813,7 @@
 xmlParsePEReference(xmlParserCtxtPtr ctxt) {
     CHAR *ret = NULL;
     CHAR *name;
-    xmlEntityPtr entity;
+    xmlEntityPtr entity = NULL;
     xmlParserInputPtr input;
 
     if (CUR == '%') {
@@ -2781,7 +2826,9 @@
 	} else {
 	    if (CUR == ';') {
 	        NEXT;
-		entity = xmlGetDtdEntity(ctxt->doc, name);
+		if ((ctxt->sax != NULL) && (ctxt->sax->getEntity != NULL))
+			entity = ctxt->sax->getEntity(ctxt, name);
+		/* TODO !!!! Must check that it's of the proper type !!! */
 		if (entity == NULL) {
 		    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
 		        ctxt->sax->warning(ctxt,
@@ -2818,7 +2865,6 @@
 
 void
 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
-    xmlDtdPtr dtd;
     CHAR *name;
     CHAR *ExternalID = NULL;
     CHAR *URI = NULL;
@@ -2848,7 +2894,8 @@
     URI = xmlParseExternalID(ctxt, &ExternalID, 1);
     SKIP_BLANKS;
 
-    dtd = xmlCreateIntSubset(ctxt->doc, name, ExternalID, URI);
+    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
+	ctxt->sax->internalSubset(ctxt, name, ExternalID, URI);
 
     /*
      * Is there any DTD definition ?
@@ -2901,7 +2948,7 @@
 /**
  * xmlParseAttribute:
  * @ctxt:  an XML parser context
- * @node:  the node carrying the attribute
+ * @value:  a CHAR ** used to store the value of the attribute
  *
  * parse an attribute
  *
@@ -2916,17 +2963,15 @@
  * Also the case QName == xmlns:??? is handled independently as a namespace
  * definition.
  *
- * Returns the attribute just parsed of NULL in case of error.
+ * Returns the attribute name, and the value in *value.
  */
 
-xmlAttrPtr
-xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node) {
+CHAR *
+xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value) {
     CHAR *name, *val;
-    CHAR *ns;
-    CHAR *value = NULL;
-    xmlAttrPtr ret;
 
-    name = xmlNamespaceParseQName(ctxt, &ns);
+    *value = NULL;
+    name = xmlParseName(ctxt);
     if (name == NULL) {
 	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 	    ctxt->sax->error(ctxt, "error parsing attribute name\n");
@@ -2941,61 +2986,17 @@
     if (CUR == '=') {
         NEXT;
 	SKIP_BLANKS;
-	value = xmlParseAttValue(ctxt);
+	val = xmlParseAttValue(ctxt);
     } else {
 	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 	    ctxt->sax->error(ctxt,
 	       "Specification mandate value for attribute %s\n", name);
 	ctxt->wellFormed = 0;
-    }
-
-    /*
-     * Check whether it's a namespace definition
-     */
-    if ((ns == NULL) &&
-        (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
-        (name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
-	/* a default namespace definition */
-	xmlNewNs(node, value, NULL);
-	if (name != NULL) 
-	    free(name);
-	if (value != NULL)
-	    free(value);
-	return(NULL);
-    }
-    if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
-        (ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
-	/* a standard namespace definition */
-	xmlNewNs(node, value, name);
-	free(ns);
-	if (name != NULL) 
-	    free(name);
-	if (value != NULL)
-	    free(value);
 	return(NULL);
     }
 
-    /*
-     * Well formedness requires at most one declaration of an attribute
-     */
-    if ((val = xmlGetProp(ctxt->node, name)) != NULL) {
-        free(val);
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, "Attribute %s redefined\n", name);
-	ctxt->wellFormed = 0;
-	ret = NULL;
-    } else {
-	ret = xmlNewProp(ctxt->node, name, NULL);
-	if (ret != NULL)
-	    ret->val = xmlStringGetNodeList(ctxt->doc, value);
-    }
-
-    if (ns != NULL)
-      free(ns);
-    if (value != NULL)
-	free(value);
-    free(name);
-    return(ret);
+    *value = val;
+    return(name);
 }
 
 /**
@@ -3014,48 +3015,31 @@
  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
  *
  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
- *
- * Returns the XML new node or NULL.
  */
 
-xmlNodePtr
+void
 xmlParseStartTag(xmlParserCtxtPtr ctxt) {
-    CHAR *namespace, *name;
-    xmlNsPtr ns = NULL;
-    xmlNodePtr ret = NULL;
-    xmlNodePtr parent = ctxt->node;
+    CHAR *name;
+    CHAR *attname;
+    CHAR *attvalue;
+    const CHAR **atts = NULL;
+    int nbatts = 0;
+    int maxatts = 0;
+    int i;
 
-    if (CUR != '<') return(NULL);
+    if (CUR != '<') return;
     NEXT;
 
-    name = xmlNamespaceParseQName(ctxt, &namespace);
+    name = xmlParseName(ctxt);
     if (name == NULL) {
 	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 	    ctxt->sax->error(ctxt, 
 	     "xmlParseStartTag: invalid element name\n");
 	ctxt->wellFormed = 0;
-        return(NULL);
+        return;
     }
 
     /*
-     * 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 = xmlNewDocNode(ctxt->doc, ns, name, NULL);
-    if (ret == NULL) {
-	if (namespace != NULL)
-	    free(namespace);
-	free(name);
-        return(NULL);
-    }
-
-    /*
-     * We are parsing a new node.
-     */
-    nodePush(ctxt, ret);
-
-    /*
      * Now parse the attributes, it ends up with the ending
      *
      * (S Attribute)* S?
@@ -3066,9 +3050,50 @@
 	   ((CUR != '/') || (NXT(1) != '>'))) {
 	const CHAR *q = CUR_PTR;
 
-	xmlParseAttribute(ctxt, ret);
-	SKIP_BLANKS;
+	attname = xmlParseAttribute(ctxt, &attvalue);
+        if ((attname != NULL) && (attvalue != NULL)) {
+	    /*
+	     * Well formedness requires at most one declaration of an attribute
+	     */
+	    for (i = 0; i < nbatts;i += 2) {
+	        if (!xmlStrcmp(atts[i], attname)) {
+		    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+			ctxt->sax->error(ctxt, "Attribute %s redefined\n",
+			                 name);
+		    ctxt->wellFormed = 0;
+		    free(attname);
+		    free(attvalue);
+		    break;
+		}
+	    }
 
+	    /*
+	     * Add the pair to atts
+	     */
+	    if (atts == NULL) {
+	        maxatts = 10;
+	        atts = (const CHAR **) malloc(maxatts * sizeof(CHAR *));
+		if (atts == NULL) {
+		    fprintf(stderr, "malloc of %d byte failed\n",
+			    maxatts * sizeof(CHAR *));
+		    return;
+		}
+	    } else if (nbatts + 2 < maxatts) {
+	        maxatts *= 2;
+	        atts = (const CHAR **) realloc(atts, maxatts * sizeof(CHAR *));
+		if (atts == NULL) {
+		    fprintf(stderr, "realloc of %d byte failed\n",
+			    maxatts * sizeof(CHAR *));
+		    return;
+		}
+	    }
+	    atts[nbatts++] = attname;
+	    atts[nbatts++] = attvalue;
+	    atts[nbatts] = NULL;
+	    atts[nbatts + 1] = NULL;
+	}
+
+	SKIP_BLANKS;
         if (q == CUR_PTR) {
 	    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
 	        ctxt->sax->error(ctxt, 
@@ -3079,38 +3104,21 @@
     }
 
     /*
-     * Search the namespace
-     */
-    ns = xmlSearchNs(ctxt->doc, ret, namespace);
-    if (ns == NULL) /* ret still doesn't have a parent yet ! */
-	ns = xmlSearchNs(ctxt->doc, parent, namespace);
-    xmlSetNs(ret, ns);
-    if (namespace != NULL)
-	free(namespace);
-
-    /*
      * SAX: Start of Element !
      */
-    if (ctxt->sax != NULL)
-        ctxt->sax->startElement(ctxt, name);
+    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
+        ctxt->sax->startElement(ctxt, name, atts);
+
     free(name);
-
-    /*
-     * Link the child element
-     */
-    if (ctxt->nodeNr < 2) return(ret);
-    parent = ctxt->nodeTab[ctxt->nodeNr - 2];
-    if (parent != NULL)
-	xmlAddChild(parent, ctxt->node);
-
-    return(ret);
+    if (atts != NULL) {
+        for (i = 0;i < nbatts;i++) free((CHAR *) atts[i]);
+	free(atts);
+    }
 }
 
 /**
  * xmlParseEndTag:
  * @ctxt:  an XML parser context
- * @nsPtr:  the current node namespace definition
- * @tagPtr:  CHAR** receive the tag value
  *
  * parse an end of tag
  *
@@ -3118,18 +3126,12 @@
  *
  * With namespace
  *
- * [9] ETag ::= '</' QName S? '>'
- *    
- * tagPtr receive the tag name just read
+ * [NS 9] ETag ::= '</' QName S? '>'
  */
 
 void
-xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr) {
-    CHAR *namespace, *name;
-    xmlNsPtr ns = NULL;
-
-    *nsPtr = NULL;
-    *tagPtr = NULL;
+xmlParseEndTag(xmlParserCtxtPtr ctxt) {
+    CHAR *name;
 
     if ((CUR != '<') || (NXT(1) != '/')) {
 	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
@@ -3139,17 +3141,7 @@
     }
     SKIP(2);
 
-    name = xmlNamespaceParseQName(ctxt, &namespace);
-
-    /*
-     * Search the namespace
-     */
-    ns = xmlSearchNs(ctxt->doc, ctxt->node, namespace);
-    if (namespace != NULL)
-	free(namespace);
-
-    *nsPtr = ns;
-    *tagPtr = name;
+    name = xmlParseName(ctxt);
 
     /*
      * We should definitely be at the ending "S? '>'" part
@@ -3162,6 +3154,15 @@
     } else
 	NEXT;
 
+    /*
+     * SAX: End of Tag
+     */
+    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+        ctxt->sax->endElement(ctxt, name);
+
+    if (name != NULL)
+	free(name);
+
     return;
 }
 
@@ -3221,10 +3222,14 @@
      * Ok the segment [base CUR_PTR] is to be consumed as chars.
      */
     if (ctxt->sax != NULL) {
-	if (areBlanks(ctxt, base, CUR_PTR - base))
-	    ctxt->sax->ignorableWhitespace(ctxt, base, 0, (CUR_PTR - base) - 2);
-	else
-	    ctxt->sax->characters(ctxt, base, 0, (CUR_PTR - base) - 2);
+	if (areBlanks(ctxt, base, CUR_PTR - base)) {
+	    if (ctxt->sax->ignorableWhitespace != NULL)
+		ctxt->sax->ignorableWhitespace(ctxt, base,
+		                               (CUR_PTR - base) - 2);
+	 } else {
+	    if (ctxt->sax->characters != NULL)
+		ctxt->sax->characters(ctxt, base, (CUR_PTR - base) - 2);
+	 }
     }
 }
 
@@ -3239,11 +3244,8 @@
 
 void
 xmlParseContent(xmlParserCtxtPtr ctxt) {
-    xmlNodePtr ret = NULL;
-
     while ((CUR != '<') || (NXT(1) != '/')) {
 	const CHAR *test = CUR_PTR;
-        ret = NULL;
 
 	/*
 	 * First case : a Processing Instruction.
@@ -3251,6 +3253,7 @@
 	if ((CUR == '<') && (NXT(1) == '?')) {
 	    xmlParsePI(ctxt);
 	}
+
 	/*
 	 * Second case : a CDSection
 	 */
@@ -3261,19 +3264,22 @@
 	    (NXT(8) == '[')) {
 	    xmlParseCDSect(ctxt);
 	}
+
 	/*
 	 * Third case :  a comment
 	 */
 	else if ((CUR == '<') && (NXT(1) == '!') &&
 		 (NXT(2) == '-') && (NXT(3) == '-')) {
-	    ret = xmlParseComment(ctxt, 1);
+	    xmlParseComment(ctxt, 1);
 	}
+
 	/*
 	 * Fourth case :  a sub-element.
 	 */
 	else if (CUR == '<') {
-	    ret = xmlParseElement(ctxt);
+	    xmlParseElement(ctxt);
 	}
+
 	/*
 	 * Fifth case : a reference. If if has not been resolved,
 	 *    parsing returns it's Name, create the node 
@@ -3285,19 +3291,19 @@
 		    /*
 		     * inline predefined entity.
 		     */
-                    if (ctxt->sax != NULL)
-			ctxt->sax->characters(ctxt, val, 0, xmlStrlen(val));
+                    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
+			ctxt->sax->characters(ctxt, val, xmlStrlen(val));
 		} else {
 		    /*
 		     * user defined entity, create a node.
 		     */
-		    ret = xmlNewReference(ctxt->doc, val);
-		    xmlAddChild(ctxt->node, ret);
-		    ret = NULL;
+                    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL))
+			ctxt->sax->reference(ctxt, val);
 		}
 		free(val);
 	    }
 	}
+
 	/*
 	 * Last case, text. Note that References are handled directly.
 	 */
@@ -3330,42 +3336,27 @@
  * [39] element ::= EmptyElemTag | STag content ETag
  *
  * [41] Attribute ::= Name Eq AttValue
- *
- * Returns the XML new node or NULL
  */
 
-
-xmlNodePtr
+void
 xmlParseElement(xmlParserCtxtPtr ctxt) {
-    xmlNodePtr ret;
     const CHAR *openTag = CUR_PTR;
     xmlParserNodeInfo node_info;
-    CHAR *endTag;
-    xmlNsPtr endNs;
 
     /* Capture start position */
     node_info.begin_pos = CUR_PTR - ctxt->input->base;
     node_info.begin_line = ctxt->input->line;
 
-    ret = xmlParseStartTag(ctxt);
-    if (ret == NULL) {
-        return(NULL);
-    }
+    xmlParseStartTag(ctxt);
 
     /*
      * Check for an Empty Element.
      */
     if ((CUR == '/') && (NXT(1) == '>')) {
         SKIP(2);
-	if (ctxt->sax != NULL)
-	    ctxt->sax->endElement(ctxt, ret->name);
-
-	/*
-	 * end of parsing of this node.
-	 */
-	nodePop(ctxt);
-
-	return(ret);
+	if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
+	    ctxt->sax->endElement(ctxt, NULL);
+	return;
     }
     if (CUR == '>') NEXT;
     else {
@@ -3376,10 +3367,11 @@
 
 	/*
 	 * end of parsing of this node.
+	 * TODO !!!!!!!! check the macro in case of non DOM parsing
 	 */
 	nodePop(ctxt);
 
-	return(NULL);
+	return;
     }
 
     /*
@@ -3394,61 +3386,17 @@
 
 	/*
 	 * end of parsing of this node.
+	 * TODO !!!!!!!! check the macro in case of non DOM parsing
 	 */
 	nodePop(ctxt);
 
-	return(NULL);
+	return;
     }
 
     /*
      * parse the end of tag: '</' should be here.
      */
-    xmlParseEndTag(ctxt, &endNs, &endTag);
-
-    /*
-     * Check that the Name in the ETag is the same as in the STag.
-     */
-    if (endNs != ret->ns) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	    "Start and End tags don't use the same namespace\n%.30s\n%.30s\n",
-	               openTag, endTag);
-	ctxt->wellFormed = 0;
-    }
-    if (endTag == NULL ) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, "The End tag has no name\n%.30s\n", openTag);
-	ctxt->wellFormed = 0;
-    } else if (xmlStrcmp(ret->name, endTag)) {
-	if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
-	    ctxt->sax->error(ctxt, 
-	    "Start and End tags don't use the same name\n%.30s\n%.30s\n",
-	               openTag, endTag);
-	ctxt->wellFormed = 0;
-    }
-    /*
-     * SAX: End of Tag
-     */
-    else if (ctxt->sax != NULL)
-        ctxt->sax->endElement(ctxt, endTag);
-
-    if (endTag != NULL)
-	free(endTag);
-
-    /* Capture end position and add node */
-    if ( ret != NULL && ctxt->record_info ) {
-      node_info.end_pos = CUR_PTR - ctxt->input->base;
-      node_info.end_line = ctxt->input->line;
-      node_info.node = ret;
-      xmlParserAddNodeInfo(ctxt, &node_info);
-    }
-
-    /*
-     * end of parsing of this node.
-     */
-    nodePop(ctxt);
-
-    return(ret);
+    xmlParseEndTag(ctxt);
 }
 
 /**
@@ -3746,7 +3694,7 @@
     version = xmlParseVersionInfo(ctxt);
     if (version == NULL)
 	version = xmlCharStrdup(XML_DEFAULT_VERSION);
-    ctxt->doc = xmlNewDoc(version);
+    ctxt->version = xmlStrdup(version);
     free(version);
 
     /*
@@ -3761,12 +3709,12 @@
 	    ctxt->sax->error(ctxt, "Blank needed here\n");
 	ctxt->wellFormed = 0;
     }
-    ctxt->doc->encoding = xmlParseEncodingDecl(ctxt);
+    ctxt->encoding = xmlParseEncodingDecl(ctxt);
 
     /*
      * We may have the standalone status.
      */
-    if ((ctxt->doc->encoding != NULL) && (!IS_BLANK(CUR))) {
+    if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
         if ((CUR == '?') && (NXT(1) == '>')) {
 	    SKIP(2);
 	    return;
@@ -3776,7 +3724,7 @@
 	ctxt->wellFormed = 0;
     }
     SKIP_BLANKS;
-    ctxt->doc->standalone = xmlParseSDDecl(ctxt);
+    ctxt->standalone = xmlParseSDDecl(ctxt);
 
     SKIP_BLANKS;
     if ((CUR == '?') && (NXT(1) == '>')) {
@@ -3842,10 +3790,8 @@
     /*
      * SAX: beginning of the document processing.
      */
-    if (ctxt->sax) 
+    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
         ctxt->sax->setDocumentLocator(ctxt, &xmlDefaultSAXLocator);
-    if (ctxt->sax)
-        ctxt->sax->startDocument(ctxt);
 
     /*
      * We should check for encoding here and plug-in some
@@ -3889,12 +3835,10 @@
 	/* SKIP_EOL(cur); */
 	SKIP_BLANKS;
     } else {
-	CHAR *version;
-
-	version = xmlCharStrdup(XML_DEFAULT_VERSION);
-	ctxt->doc = xmlNewDoc(version);
-	free(version);
+	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
     }
+    if ((ctxt->sax) && (ctxt->sax->startDocument))
+        ctxt->sax->startDocument(ctxt);
 
     /*
      * The Misc part of the Prolog
@@ -3917,7 +3861,7 @@
     /*
      * Time to start parsing the tree itself
      */
-    ctxt->doc->root = xmlParseElement(ctxt);
+    xmlParseElement(ctxt);
 
     /*
      * The Misc part at the end
@@ -3934,7 +3878,7 @@
     /*
      * SAX: end of the document processing.
      */
-    if (ctxt->sax) 
+    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
         ctxt->sax->endDocument(ctxt);
     if (! ctxt->wellFormed) return(-1);
     return(0);
@@ -4004,11 +3948,11 @@
     if (sax != NULL) ctxt->sax = sax;
 
     xmlParseDocument(ctxt);
-    if ((ctxt->wellFormed) || recovery) ret = ctxt->doc;
+    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
     else {
        ret = NULL;
-       xmlFreeDoc(ctxt->doc);
-       ctxt->doc = NULL;
+       xmlFreeDoc(ctxt->myDoc);
+       ctxt->myDoc = NULL;
     }
     xmlFreeParserCtxt(ctxt);
     
@@ -4187,11 +4131,11 @@
 
     xmlParseDocument(ctxt);
 
-    if ((ctxt->wellFormed) || recovery) ret = ctxt->doc;
+    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
     else {
        ret = NULL;
-       xmlFreeDoc(ctxt->doc);
-       ctxt->doc = NULL;
+       xmlFreeDoc(ctxt->myDoc);
+       ctxt->myDoc = NULL;
     }
     xmlFreeParserCtxt(ctxt);
     
@@ -4300,11 +4244,11 @@
 
     xmlParseDocument(ctxt);
 
-    if ((ctxt->wellFormed) || recovery) ret = ctxt->doc;
+    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
     else {
        ret = NULL;
-       xmlFreeDoc(ctxt->doc);
-       ctxt->doc = NULL;
+       xmlFreeDoc(ctxt->myDoc);
+       ctxt->myDoc = NULL;
     }
     xmlFreeParserCtxt(ctxt);
     
@@ -4355,6 +4299,9 @@
     ctxt->inputNr = 0;
     ctxt->inputMax = 5;
     ctxt->input = NULL;
+    ctxt->version = NULL;
+    ctxt->encoding = NULL;
+    ctxt->standalone = -1;
 
     /* Allocate the Node stack */
     ctxt->nodeTab = (xmlNodePtr *) malloc(10 * sizeof(xmlNodePtr));
@@ -4363,7 +4310,7 @@
     ctxt->node = NULL;
 
     ctxt->sax = &xmlDefaultSAXHandler;
-    ctxt->doc = NULL;
+    ctxt->myDoc = NULL;
     ctxt->wellFormed = 1;
     ctxt->record_info = 0;
     xmlInitNodeInfoSeq(&ctxt->node_seq);
@@ -4374,7 +4321,7 @@
  * @ctxt:  an XML parser context
  *
  * Free all the memory used by a parser context. However the parsed
- * document in ctxt->doc is not freed.
+ * document in ctxt->myDoc is not freed.
  */
 
 void
@@ -4390,6 +4337,7 @@
 
     if (ctxt->nodeTab != NULL) free(ctxt->nodeTab);
     if (ctxt->inputTab != NULL) free(ctxt->inputTab);
+    if (ctxt->version != NULL) free(ctxt->version);
     free(ctxt);
 }
 
diff --git a/parser.h b/parser.h
index 3dc8445..3e433a2 100644
--- a/parser.h
+++ b/parser.h
@@ -51,8 +51,12 @@
 
 typedef struct _xmlParserCtxt {
     struct xmlSAXHandler *sax;        /* The SAX handler */
-    xmlDocPtr doc;                    /* the document being built */
+    void            *userData;        /* the document being built */
+    xmlDocPtr           myDoc;        /* the document being built */
     int            wellFormed;        /* is the document well formed */
+    const CHAR     *version;	      /* the XML version string */
+    const CHAR     *encoding;         /* encoding, if any */
+    int             standalone;       /* standalone document */
 
     /* Input stream stack */
     xmlParserInputPtr  input;         /* Current input stream */
@@ -89,10 +93,24 @@
  * a SAX Exception.
  */
 
+#include "entities.h"
+
 typedef xmlParserInputPtr (*resolveEntitySAXFunc) (xmlParserCtxtPtr ctxt,
 			    const CHAR *publicId, const CHAR *systemId);
+typedef void (*internalSubsetSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
+                            const CHAR *ExternalID, const CHAR *SystemID);
+typedef xmlEntityPtr (*getEntitySAXFunc) (xmlParserCtxtPtr ctxt,
+                            const CHAR *name);
+typedef void (*entityDeclSAXFunc) (xmlParserCtxtPtr ctxt,
+                            const CHAR *name, int type, const CHAR *publicId,
+			    const CHAR *systemId, CHAR *content);
 typedef void (*notationDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name,
 			    const CHAR *publicId, const CHAR *systemId);
+typedef void (*attributeDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *elem,
+                            const CHAR *name, int type, int def,
+			    const CHAR *defaultValue, xmlEnumerationPtr tree);
+typedef void (*elementDeclSAXFunc)(xmlParserCtxtPtr ctxt, const CHAR *name,
+			    int type, xmlElementContentPtr content);
 typedef void (*unparsedEntityDeclSAXFunc)(xmlParserCtxtPtr ctxt,
                             const CHAR *name, const CHAR *publicId,
 			    const CHAR *systemId, const CHAR *notationName);
@@ -100,33 +118,48 @@
                             xmlSAXLocatorPtr loc);
 typedef void (*startDocumentSAXFunc) (xmlParserCtxtPtr ctxt);
 typedef void (*endDocumentSAXFunc) (xmlParserCtxtPtr ctxt);
-typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
+typedef void (*startElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
+                            const CHAR **atts);
 typedef void (*endElementSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
 typedef void (*attributeSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name,
                                   const CHAR *value);
+typedef void (*referenceSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *name);
 typedef void (*charactersSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *ch,
-		            int start, int len);
+		            int len);
 typedef void (*ignorableWhitespaceSAXFunc) (xmlParserCtxtPtr ctxt,
-			    const CHAR *ch, int start, int len);
+			    const CHAR *ch, int len);
 typedef void (*processingInstructionSAXFunc) (xmlParserCtxtPtr ctxt,
                             const CHAR *target, const CHAR *data);
+typedef void (*commentSAXFunc) (xmlParserCtxtPtr ctxt, const CHAR *value);
 typedef void (*warningSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
 typedef void (*errorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
 typedef void (*fatalErrorSAXFunc) (xmlParserCtxtPtr ctxt, const char *msg, ...);
+typedef int (*isStandaloneSAXFunc) (xmlParserCtxtPtr ctxt);
+typedef int (*hasInternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt);
+typedef int (*hasExternalSubsetSAXFunc) (xmlParserCtxtPtr ctxt);
 
 typedef struct xmlSAXHandler {
+    internalSubsetSAXFunc internalSubset;
+    isStandaloneSAXFunc isStandalone;
+    hasInternalSubsetSAXFunc hasInternalSubset;
+    hasExternalSubsetSAXFunc hasExternalSubset;
     resolveEntitySAXFunc resolveEntity;
+    getEntitySAXFunc getEntity;
+    entityDeclSAXFunc entityDecl;
     notationDeclSAXFunc notationDecl;
+    attributeDeclSAXFunc attributeDecl;
+    elementDeclSAXFunc elementDecl;
     unparsedEntityDeclSAXFunc unparsedEntityDecl;
     setDocumentLocatorSAXFunc setDocumentLocator;
     startDocumentSAXFunc startDocument;
     endDocumentSAXFunc endDocument;
     startElementSAXFunc startElement;
     endElementSAXFunc endElement;
-    attributeSAXFunc attribute;
+    referenceSAXFunc reference;
     charactersSAXFunc characters;
     ignorableWhitespaceSAXFunc ignorableWhitespace;
     processingInstructionSAXFunc processingInstruction;
+    commentSAXFunc comment;
     warningSAXFunc warning;
     errorSAXFunc error;
     fatalErrorSAXFunc fatalError;
diff --git a/parserInternals.h b/parserInternals.h
index 28ef54d..75e9e13 100644
--- a/parserInternals.h
+++ b/parserInternals.h
@@ -529,6 +529,8 @@
  * Namespaces.
  */
 CHAR *
+xmlSplitQName(const CHAR *name, CHAR **prefix);
+CHAR *
 xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt);
 CHAR *
 xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix);
@@ -558,7 +560,7 @@
 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata);
 CHAR *
 xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict);
-xmlNodePtr 
+void 
 xmlParseComment(xmlParserCtxtPtr ctxt, int create);
 CHAR *
 xmlParsePITarget(xmlParserCtxtPtr ctxt);
@@ -601,17 +603,17 @@
 xmlParsePEReference(xmlParserCtxtPtr ctxt);
 void
 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt);
-xmlAttrPtr 
-xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlNodePtr node);
-xmlNodePtr 
+CHAR *
+xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value);
+void
 xmlParseStartTag(xmlParserCtxtPtr ctxt);
 void
-xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlNsPtr *nsPtr, CHAR **tagPtr);
+xmlParseEndTag(xmlParserCtxtPtr ctxt);
 void
 xmlParseCDSect(xmlParserCtxtPtr ctxt);
 void
 xmlParseContent(xmlParserCtxtPtr ctxt);
-xmlNodePtr 
+void
 xmlParseElement(xmlParserCtxtPtr ctxt);
 CHAR *
 xmlParseVersionNum(xmlParserCtxtPtr ctxt);
@@ -628,5 +630,12 @@
 void
 xmlParseMisc(xmlParserCtxtPtr ctxt);
 
+/*
+ * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP
+ */
+extern int nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value);
+extern xmlNodePtr nodePop(xmlParserCtxtPtr ctxt);
+extern int inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value);
+extern xmlParserInputPtr inputPop(xmlParserCtxtPtr ctxt);
 
 #endif /* __XML_PARSER_INTERNALS_H__ */
diff --git a/tree.c b/tree.c
index a331fe1..13c3087 100644
--- a/tree.c
+++ b/tree.c
@@ -1088,7 +1088,7 @@
  * Returns a pointer to the new node object.
  */
 xmlNodePtr
-xmlNewComment(CHAR *content) {
+xmlNewComment(const CHAR *content) {
     xmlNodePtr cur;
 
     /*
@@ -1128,7 +1128,7 @@
  * Returns a pointer to the new node object.
  */
 xmlNodePtr
-xmlNewDocComment(xmlDocPtr doc, CHAR *content) {
+xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
     xmlNodePtr cur;
 
     cur = xmlNewComment(content);
diff --git a/tree.h b/tree.h
index 4443836..3f00aa0 100644
--- a/tree.h
+++ b/tree.h
@@ -283,8 +283,8 @@
 xmlNodePtr xmlNewText(const CHAR *content);
 xmlNodePtr xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len);
 xmlNodePtr xmlNewTextLen(const CHAR *content, int len);
-xmlNodePtr xmlNewDocComment(xmlDocPtr doc, CHAR *content);
-xmlNodePtr xmlNewComment(CHAR *content);
+xmlNodePtr xmlNewDocComment(xmlDocPtr doc, const CHAR *content);
+xmlNodePtr xmlNewComment(const CHAR *content);
 xmlNodePtr xmlNewReference(xmlDocPtr doc, const CHAR *name);
 xmlNodePtr xmlCopyNode(xmlNodePtr node, int recursive);
 xmlNodePtr xmlCopyNodeList(xmlNodePtr node);
diff --git a/valid.c b/valid.c
index 3cb6276..2c1be9f 100644
--- a/valid.c
+++ b/valid.c
@@ -216,7 +216,7 @@
  * Returns NULL if not, othervise the entity
  */
 xmlElementPtr
-xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, 
+xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, 
                   xmlElementContentPtr content) {
     xmlElementPtr ret, cur;
     xmlElementTablePtr table;
@@ -560,8 +560,9 @@
  * Returns NULL if not, othervise the entity
  */
 xmlAttributePtr
-xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem, CHAR *name, int type, int def,
-                    CHAR *defaultValue, xmlEnumerationPtr tree) {
+xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name,
+                    int type, int def, const CHAR *defaultValue,
+		    xmlEnumerationPtr tree) {
     xmlAttributePtr ret, cur;
     xmlAttributeTablePtr table;
     int i;
@@ -890,7 +891,8 @@
  * Returns NULL if not, othervise the entity
  */
 xmlNotationPtr
-xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name, CHAR *PublicID, CHAR *SystemID) {
+xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID,
+                   const CHAR *SystemID) {
     xmlNotationPtr ret, cur;
     xmlNotationTablePtr table;
     int i;
diff --git a/valid.h b/valid.h
index 14a7228..22c824a 100644
--- a/valid.h
+++ b/valid.h
@@ -54,8 +54,8 @@
 typedef xmlAttributeTable *xmlAttributeTablePtr;
 
 /* Notation */
-xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name,
-	       CHAR *PublicID, CHAR *SystemID);
+xmlNotationPtr xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name,
+	       const CHAR *PublicID, const CHAR *SystemID);
 xmlNotationTablePtr xmlCopyNotationTable(xmlNotationTablePtr table);
 void xmlFreeNotationTable(xmlNotationTablePtr table);
 void xmlDumpNotationTable(xmlNotationTablePtr table);
@@ -66,7 +66,7 @@
 void xmlFreeElementContent(xmlElementContentPtr cur);
 
 /* Element */
-xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type, 
+xmlElementPtr xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type, 
                                        xmlElementContentPtr content);
 xmlElementTablePtr xmlCopyElementTable(xmlElementTablePtr table);
 void xmlFreeElementTable(xmlElementTablePtr table);
@@ -78,9 +78,9 @@
 xmlEnumerationPtr xmlCopyEnumeration(xmlEnumerationPtr cur);
 
 /* Attribute */
-xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem,
-	       CHAR *name, int type, int def,
-	       CHAR *defaultValue, xmlEnumerationPtr tree);
+xmlAttributePtr xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem,
+	       const CHAR *name, int type, int def,
+	       const CHAR *defaultValue, xmlEnumerationPtr tree);
 xmlAttributeTablePtr xmlCopyAttributeTable(xmlAttributeTablePtr table);
 void xmlFreeAttributeTable(xmlAttributeTablePtr table);
 void xmlDumpAttributeTable(xmlAttributeTablePtr table);