Time to commit 3 days of work rewriting the parser internal,
fixing bugs and migrating to SAX2 interface by default. There
is some work letf TODO, like namespace validation and attributes
normalization (this break C14N right now)
* Makefile.am: fixed the test rules
* include/libxml/SAX2.h include/libxml/parser.h
  include/libxml/parserInternals.h SAX2.c parser.c
  parserInternals.c: changing the parser, migrating to SAX2,
  adding new interface to switch back to SAX1 or initialize a
  SAX block for v1 or v2. Most of the namespace work is done
  below SAX, as well as attribute defaulting
* globals.c: changed initialization of the default SAX handlers
* hash.c tree.c include/libxml/hash.h: added QName specific handling
* xmlIO.c: small fix
* xmllint.c testSAX.c: provide a --sax1 switch to test the old
  version code path
* result/p3p result/p3p.sax result/noent/p3p test/p3p: the new code
  pointed out a typo in a very old test namespace
Daniel
diff --git a/Makefile.am b/Makefile.am
index 3a76030..da1f38b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -222,11 +222,14 @@
 	  if [ ! -f $(srcdir)/result/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint $$i > $(srcdir)/result/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff $(srcdir)/result/$$name result.$$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint result.$$name > result2.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff result.$$name result2.$$name ; \
 	      rm result.$$name result2.$$name ; \
 	  fi ; fi ; done)
@@ -242,11 +245,14 @@
 	  if [ ! -f $(srcdir)/result/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --push $$i > $(srcdir)/result/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --push $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff $(srcdir)/result/$$name result.$$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --push result.$$name > result2.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff result.$$name result2.$$name ; \
 	      rm result.$$name result2.$$name ; \
 	  fi ; fi ; done)
@@ -261,12 +267,14 @@
 	  if [ ! -f $(srcdir)/result/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --memory $$i > $(srcdir)/result/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --memory $$i > result.$$name ; \
 	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      diff $(srcdir)/result/$$name result.$$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --memory result.$$name > result2.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff result.$$name result2.$$name ; \
 	      rm result.$$name result2.$$name ; \
 	  fi ; fi ; done)
@@ -302,11 +310,14 @@
 	  if [ ! -f $(srcdir)/result/noent/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --noent $$i > $(srcdir)/result/noent/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --noent $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff $(srcdir)/result/noent/$$name result.$$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --noent result.$$name > result2.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff result.$$name result2.$$name ; \
 	      rm result.$$name result2.$$name ; \
 	  fi ; fi ; done)
@@ -322,6 +333,7 @@
 	  if [ ! -f $(srcdir)/result/URI/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/testURI -base 'http://foo.com/path/to/index.html?orig#help' < $$i > $(srcdir)/result/URI/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/testURI -base 'http://foo.com/path/to/index.html?orig#help' < $$i > result.$$name ; \
@@ -335,6 +347,7 @@
 	  if [ ! -f $(srcdir)/result/URI/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/testURI < $$i > $(srcdir)/result/URI/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/testURI < $$i > result.$$name ; \
@@ -399,10 +412,11 @@
 	  if [ ! -d $$j ] ; then \
 	  if [ ! -f $(srcdir)/result/XPath/xptr/$$name ] ; then \
 	      echo New test file $$name ; \
-	      ./testXPath -xptr -f -i $$i $$j > $(srcdir)/result/XPath/xptr/$$name ; \
+	      $(CHECKER) $(top_builddir)/testXPath -xptr -f -i $$i $$j > $(srcdir)/result/XPath/xptr/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	  else \
 	      echo Testing $$name ; \
-	      ./testXPath -xptr -f -i $$i $$j > result.$$name ; \
+	      $(CHECKER) $(top_builddir)/testXPath -xptr -f -i $$i $$j > result.$$name ; \
 	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      diff $(srcdir)/result/XPath/xptr/$$name result.$$name ; \
 	      rm result.$$name ; \
@@ -421,6 +435,7 @@
 	  if [ ! -f $(srcdir)/result/XInclude/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude $$i > $(srcdir)/result/XInclude/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --nowarning --xinclude $$i > result.$$name ; \
@@ -442,6 +457,7 @@
 	  if [ ! -f $(srcdir)/result/scripts/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --shell $$xml < $$i > $(srcdir)/result/scripts/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --shell $$xml < $$i > result.$$name ; \
@@ -462,6 +478,7 @@
 	  if [ ! -f $(srcdir)/result/catalogs/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmlcatalog --shell $$xml < $$i > $(srcdir)/result/catalogs/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmlcatalog --shell $$xml < $$i > result.$$name ; \
@@ -476,6 +493,7 @@
 	  if [ ! -f $(srcdir)/result/catalogs/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmlcatalog --shell $$sgml < $$i > $(srcdir)/result/catalogs/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmlcatalog --shell $$sgml < $$i > result.$$name ; \
@@ -514,11 +532,14 @@
 	  if [ ! -f $(srcdir)/result/SVG/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint $$i > $(srcdir)/result/SVG/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      diff $(srcdir)/result/SVG/$$name result.$$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint result.$$name > result2.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      diff result.$$name result2.$$name ; \
 	      rm result.$$name result2.$$name ; \
 	  fi ; fi ; done)
@@ -527,7 +548,8 @@
 	@echo "##"
 	@echo "## Threaded regression tests"
 	@echo "##"
-	$(CHECKER) $(top_builddir)/testThreads
+	-@($(CHECKER) $(top_builddir)/testThreads ; \
+	   grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";)
 
 SAXtests : testSAX$(EXEEXT)
 	@(echo > .memdump)
@@ -540,9 +562,11 @@
 	  if [ ! -f $(srcdir)/result/$$name.sax ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/testSAX $$i > $(srcdir)/result/$$name.sax ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/testSAX $$i > result.$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      diff $(srcdir)/result/$$name.sax result.$$name ; \
 	      rm result.$$name ; \
 	  fi ; fi ; done)
@@ -569,6 +593,7 @@
 	  if [ ! -f $(srcdir)/result/VC/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --noout --valid $$i 2> $(srcdir)/result/VC/$$name ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --noout --valid $$i 2> result.$$name ; \
@@ -585,6 +610,7 @@
 	  if [ ! -f $(srcdir)/result/valid/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --valid $$i > $(srcdir)/result/valid/$$name 2>$(srcdir)/result/valid/$$name.err ; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint --valid $$i > result.$$name 2>error.$$name ; \
@@ -605,6 +631,7 @@
 	  if [ ! -f $(srcdir)/result/regexp/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/testRegexp -i $$i > $(srcdir)/result/regexp/$$name; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/testRegexp -i $$i > result.$$name ; \
@@ -624,6 +651,7 @@
 	  if [ ! -f $(srcdir)/result/automata/$$name ] ; then \
 	      echo New test file $$name ; \
 	      $(CHECKER) $(top_builddir)/testAutomata $$i > $(srcdir)/result/automata/$$name; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Testing $$name ; \
 	      $(CHECKER) $(top_builddir)/testAutomata $$i > result.$$name ; \
@@ -658,6 +686,7 @@
 		    else \
 			echo "C14N failed"; \
 		    fi; \
+		    grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 		fi; \
 		rm -f $(srcdir)/test/c14n/test.tmp; \
 	    done; \
@@ -680,6 +709,7 @@
 		  $(CHECKER) $(top_builddir)/testSchemas $$i $$j \
 		    > $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno" \
 		    2> $(srcdir)/result/schemas/"$$name"_"$$sno"_"$$xno".err; \
+	          grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      else \
 		  echo Testing "$$name"_"$$sno"_"$$xno" ; \
 	          $(CHECKER) $(top_builddir)/testSchemas $$i $$j \
@@ -706,6 +736,7 @@
 	      $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $(srcdir)/test/relaxng/tutorA.rng $$i \
 		      > $(srcdir)/result/relaxng/"$$name"_valid \
 		      2> $(srcdir)/result/relaxng/"$$name"_err; \
+	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	  else \
 	      echo Checking schemas $$name ; \
 	      $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $(srcdir)/test/relaxng/tutorA.rng $$i \
@@ -727,6 +758,7 @@
 		  $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \
 		    > $(srcdir)/result/relaxng/"$$name"_"$$xno" \
 		    2> $(srcdir)/result/relaxng/"$$name"_"$$xno".err; \
+	          grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      else \
 		  echo Testing "$$name"_"$$xno" ; \
 	          $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \
@@ -757,6 +789,7 @@
 		  $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --relaxng $$i $$j \
 		    > $(srcdir)/result/relaxng/"$$name"_"$$xno" \
 		    2> $(srcdir)/result/relaxng/"$$name"_"$$xno".err; \
+	          grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0";\
 	      else \
 		  echo Testing "$$name"_"$$xno" ; \
 	          $(CHECKER) $(top_builddir)/xmllint$(EXEEXT) --noout --stream --relaxng $$i $$j \
diff --git a/NEWS b/NEWS
index 4e2349e..992142a 100644
--- a/NEWS
+++ b/NEWS
@@ -15,16 +15,21 @@
   Schemas
 
 
+2.5.11: Sep 9 2003:
+A bugfix only release:   - risk of crash in Relax-NG
+   - risk of crash when using multithreaded programs
+
+
 2.5.10: Aug 15 2003:
 A bugfixes only release   - Windows Makefiles (William Brack)
    - UTF-16 support fixes (Mark Itzcovitz)
    - Makefile and portability (William Brack) automake, Linux alpha, Mingw
-    on Windows (Mikhail Grushinskiy) 
+    on Windows (Mikhail Grushinskiy)
    - HTML parser (Oliver Stoeneberg)
    - XInclude performance problem reported by Kevin Ruscoe
    - XML parser performance problem reported by Grant Goodale
    - xmlSAXParseDTD() bug fix from Malcolm Tredinnick
-   - and a couple other cleanup 
+   - and a couple other cleanup
 
 
 2.5.9: Aug 9 2003:
diff --git a/dict.c b/dict.c
index aa29976..380e908 100644
--- a/dict.c
+++ b/dict.c
@@ -274,8 +274,6 @@
 
     if (len < 0)
         len = xmlStrlen(name);
-    if (len <= 0)
-	return(NULL);
 
     /*
      * Check for duplicate and insertion location.
diff --git a/globals.c b/globals.c
index 2cddaa8..2d68dbf 100644
--- a/globals.c
+++ b/globals.c
@@ -361,7 +361,6 @@
     0,
     NULL,
     NULL,
-    NULL,
     NULL
 };
 
@@ -415,7 +414,6 @@
     0,
     NULL,
     NULL,
-    NULL,
     NULL
 };
 #endif /* LIBXML_HTML_ENABLED */
@@ -457,7 +455,6 @@
     0,
     NULL,
     NULL,
-    NULL,
     NULL
 };
 #endif /* LIBXML_DOCB_ENABLED */
@@ -486,16 +483,16 @@
     xmlMutexLock(xmlThrDefMutex);
 
 #ifdef LIBXML_DOCB_ENABLED
-    initdocbDefaultSAXHandler(&gs->docbDefaultSAXHandler);
+    xmlSAX2InitDocbDefaultSAXHandler(&gs->docbDefaultSAXHandler);
 #endif
 #ifdef LIBXML_HTML_ENABLED
-    inithtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
+    xmlSAX2InitHtmlDefaultSAXHandler(&gs->htmlDefaultSAXHandler);
 #endif
 
     gs->oldXMLWDcompatibility = 0;
     gs->xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
     gs->xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
-    initxmlDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
+    xmlSAX2InitDefaultSAXHandler(&gs->xmlDefaultSAXHandler, 1);
     gs->xmlDefaultSAXLocator.getPublicId = getPublicId;
     gs->xmlDefaultSAXLocator.getSystemId = getSystemId;
     gs->xmlDefaultSAXLocator.getLineNumber = getLineNumber;
diff --git a/include/libxml/SAX2.h b/include/libxml/SAX2.h
index 70c58c8..1793f91 100644
--- a/include/libxml/SAX2.h
+++ b/include/libxml/SAX2.h
@@ -103,6 +103,21 @@
 XMLPUBFUN void XMLCALL		
 		xmlSAX2EndElement		(void *ctx,
 						 const xmlChar *name);
+XMLPUBFUN void XMLCALL
+		xmlSAX2StartElementNs		(void *ctx,
+						 const xmlChar *localname,
+						 const xmlChar *prefix,
+						 const xmlChar *URI,
+						 int nb_namespaces,
+						 const xmlChar **namespaces,
+						 int nb_attributes,
+						 int nb_defaulted,
+						 const xmlChar **attributes);
+XMLPUBFUN void XMLCALL
+		xmlSAX2EndElementNs		(void *ctx,
+						 const xmlChar *localname,
+						 const xmlChar *prefix,
+						 const xmlChar *URI);
 XMLPUBFUN void XMLCALL		
 		xmlSAX2Reference		(void *ctx,
 						 const xmlChar *name);
@@ -142,6 +157,12 @@
 						 const xmlChar *value,
 						 int len);
 
+XMLPUBFUN int XMLCALL
+		xmlSAXDefaultVersion		(int version);
+
+XMLPUBFUN int XMLCALL
+		xmlSAXVersion			(xmlSAXHandler *hdlr,
+						 int version);
 XMLPUBFUN void XMLCALL		
 		xmlSAX2InitDefaultSAXHandler    (xmlSAXHandler *hdlr,
 						 int warning);
diff --git a/include/libxml/hash.h b/include/libxml/hash.h
index 3822922..8e5d0bb 100644
--- a/include/libxml/hash.h
+++ b/include/libxml/hash.h
@@ -150,6 +150,24 @@
 					 const xmlChar *name,
 					 const xmlChar *name2,
 					 const xmlChar *name3);
+XMLPUBFUN void * XMLCALL			
+			xmlHashQLookup	(xmlHashTablePtr table,
+					 const xmlChar *name,
+					 const xmlChar *prefix);
+XMLPUBFUN void * XMLCALL			
+			xmlHashQLookup2	(xmlHashTablePtr table,
+					 const xmlChar *name,
+					 const xmlChar *prefix,
+					 const xmlChar *name2,
+					 const xmlChar *prefix2);
+XMLPUBFUN void * XMLCALL			
+			xmlHashQLookup3	(xmlHashTablePtr table,
+					 const xmlChar *name,
+					 const xmlChar *prefix,
+					 const xmlChar *name2,
+					 const xmlChar *prefix2,
+					 const xmlChar *name3,
+					 const xmlChar *prefix3);
 
 /*
  * Helpers.
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 8ab2033..967f3fd 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -12,6 +12,7 @@
 #include <libxml/xmlversion.h>
 #include <libxml/tree.h>
 #include <libxml/dict.h>
+#include <libxml/hash.h>
 #include <libxml/valid.h>
 #include <libxml/entities.h>
 
@@ -246,14 +247,19 @@
      */
     const xmlChar *str_xml;
     const xmlChar *str_xmlns;
+    const xmlChar *str_xml_ns;
 
     /*
-     * Everything below is related to the new SAX mode
+     * Everything below is used only by the new SAX mode
      */
     int                sax2;          /* operating in the new SAX mode */
     int                nsNr;          /* the number of inherited namespaces */
     int                nsMax;         /* the size of the arrays */
     const xmlChar *   *nsTab;         /* the array of prefix/namespace name */
+    int               *attallocs;     /* which attribute were allocated */
+    void *            *pushTab;       /* array of data for push */
+    xmlHashTablePtr    attsDefault;   /* defaulted attributes if any */
+    xmlHashTablePtr    attsSpecial;   /* non-CDATA attributes if any */
 };
 
 /**
@@ -622,12 +628,14 @@
  * @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
+ * @nb_defaulted:  the number of defaulted attributes. The defaulted
+ *                  ones are at the end of the array
+ * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
+ *               attribute values.
  *
  * 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,
@@ -636,7 +644,9 @@
 					const xmlChar *URI,
 					int nb_namespaces,
 					const xmlChar **namespaces,
-					int nb_attributes);
+					int nb_attributes,
+					int nb_defaulted,
+					const xmlChar **attributes);
  
 /**
  * endElementNsSAX2Func:
@@ -654,26 +664,6 @@
 					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;
@@ -703,12 +693,11 @@
     getParameterEntitySAXFunc getParameterEntity;
     cdataBlockSAXFunc cdataBlock;
     externalSubsetSAXFunc externalSubset;
-    int initialized;
+    unsigned int initialized;
     /* The following fields are extensions available only on version 2 */
     void *_private;
     startElementNsSAX2Func startElementNs;
     endElementNsSAX2Func endElementNs;
-    attributeNsSAX2Func attributeNs;
 };
 
 /**
@@ -823,6 +812,10 @@
 XMLPUBFUN int XMLCALL		
 		xmlStrEqual		(const xmlChar *str1,
 					 const xmlChar *str2);
+XMLPUBFUN int XMLCALL
+		xmlStrQEqual		(const xmlChar *pref,
+					 const xmlChar *name,
+					 const xmlChar *str);
 XMLPUBFUN int XMLCALL		
 		xmlStrlen		(const xmlChar *str);
 XMLPUBFUN xmlChar * XMLCALL	
diff --git a/include/libxml/parserInternals.h b/include/libxml/parserInternals.h
index 470451a..b691787 100644
--- a/include/libxml/parserInternals.h
+++ b/include/libxml/parserInternals.h
@@ -394,18 +394,28 @@
  */
 #define XML_SUBSTITUTE_BOTH 	3
 
-XMLPUBFUN xmlChar * XMLCALL		xmlDecodeEntities	(xmlParserCtxtPtr ctxt,
+XMLPUBFUN xmlChar * XMLCALL
+		xmlDecodeEntities		(xmlParserCtxtPtr ctxt,
 						 int len,
 						 int what,
 						 xmlChar end,
 						 xmlChar  end2,
 						 xmlChar end3);
-XMLPUBFUN xmlChar * XMLCALL		xmlStringDecodeEntities	(xmlParserCtxtPtr ctxt,
+XMLPUBFUN xmlChar * XMLCALL
+		xmlStringDecodeEntities		(xmlParserCtxtPtr ctxt,
 						 const xmlChar *str,
 						 int what,
 						 xmlChar end,
 						 xmlChar  end2,
 						 xmlChar end3);
+XMLPUBFUN xmlChar * XMLCALL
+		xmlStringLenDecodeEntities	(xmlParserCtxtPtr ctxt,
+						 const xmlChar *str,
+						 int len,
+						 int what,
+						 xmlChar end,
+						 xmlChar  end2,
+						 xmlChar end3);
 
 /*
  * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP.
diff --git a/result/noent/p3p b/result/noent/p3p
index 195eb42..31d5587 100644
--- a/result/noent/p3p
+++ b/result/noent/p3p
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<RDF:RDF xmlns:p3p="http//www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD" xmlns:RDF="http://www.w3.org/TR/WD-rdf-syntax#">
+<RDF:RDF xmlns:p3p="http://www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD" xmlns:RDF="http://www.w3.org/TR/WD-rdf-syntax#">
 <PROP realm="http://www.CoolCatalog.com/catalogue/" entity="CoolCatalog" agreeID="94df1293a3e519bb" assurance="http://www.TrustUs.org">
   <USES>
   <STATEMENT purp="2,3" recpnt="0" id="0" consq="a site with clothes you'd appreciate.">
diff --git a/result/p3p b/result/p3p
index 195eb42..31d5587 100644
--- a/result/p3p
+++ b/result/p3p
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<RDF:RDF xmlns:p3p="http//www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD" xmlns:RDF="http://www.w3.org/TR/WD-rdf-syntax#">
+<RDF:RDF xmlns:p3p="http://www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD" xmlns:RDF="http://www.w3.org/TR/WD-rdf-syntax#">
 <PROP realm="http://www.CoolCatalog.com/catalogue/" entity="CoolCatalog" agreeID="94df1293a3e519bb" assurance="http://www.TrustUs.org">
   <USES>
   <STATEMENT purp="2,3" recpnt="0" id="0" consq="a site with clothes you'd appreciate.">
diff --git a/test/p3p b/test/p3p
index b20cbc7..dad8fb7 100644
--- a/test/p3p
+++ b/test/p3p
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<RDF:RDF xmlns:p3p="http//www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD"
+<RDF:RDF xmlns:p3p="http://www.w3.org/TR/1998/WD-P3P10-syntax#proposal.DTD"
          xmlns:RDF="http://www.w3.org/TR/WD-rdf-syntax#">
 <PROP realm="http://www.CoolCatalog.com/catalogue/" 
  entity="CoolCatalog" agreeID="94df1293a3e519bb"
diff --git a/testSAX.c b/testSAX.c
index 80334d6..0a742a2 100644
--- a/testSAX.c
+++ b/testSAX.c
@@ -81,8 +81,7 @@
     1,
     NULL,
     NULL, /* startElementNs */
-    NULL, /* endElementNs */
-    NULL  /* attributeNs */
+    NULL /* endElementNs */
 };
 
 xmlSAXHandlerPtr emptySAXHandler = &emptySAXHandlerStruct;
@@ -306,19 +305,20 @@
  * An attribute definition has been parsed
  */
 static void
-attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar *elem, const xmlChar *name,
-              int type, int def, const xmlChar *defaultValue,
-	      xmlEnumerationPtr tree ATTRIBUTE_UNUSED)
+attributeDeclDebug(void *ctx ATTRIBUTE_UNUSED, const xmlChar * elem,
+                   const xmlChar * name, int type, int def,
+                   const xmlChar * defaultValue, xmlEnumerationPtr tree)
 {
     callbacks++;
     if (quiet)
-	return;
+        return;
     if (defaultValue == NULL)
-	fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
-            elem, name, type, def);
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, NULL, ...)\n",
+                elem, name, type, def);
     else
-	fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
-            elem, name, type, def, defaultValue);
+        fprintf(stdout, "SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",
+                elem, name, type, def, defaultValue);
+    xmlFreeEnumeration(tree);
 }
 
 /**
@@ -693,7 +693,6 @@
     1,
     NULL,
     NULL,
-    NULL,
     NULL
 };
 
@@ -703,7 +702,7 @@
  * SAX2 specific callbacks
  */
 /**
- * startElementDebug:
+ * startElementNsDebug:
  * @ctxt:  An XML parser context
  * @name:  The element name
  *
@@ -716,7 +715,9 @@
                     const xmlChar *URI,
 		    int nb_namespaces,
 		    const xmlChar **namespaces,
-		    int nb_attributes)
+		    int nb_attributes,
+		    int nb_defaulted,
+		    const xmlChar **attributes)
 {
     int i;
 
@@ -743,7 +744,18 @@
 	    fprintf(stdout, "='%s'", namespaces[i]);
 	}
     }
-    fprintf(stdout, ", %d)\n", nb_attributes);
+    fprintf(stdout, ", %d, %d", nb_attributes, nb_defaulted);
+    if (attributes != NULL) {
+        for (i = 0;i < nb_attributes;i += 5) {
+	    if (attributes[i + 1] != NULL)
+		fprintf(stdout, ", %s:%s='", attributes[i + 1], attributes[i]);
+	    else
+		fprintf(stdout, ", %s='", attributes[i]);
+	    fprintf(stdout, "%.4s...', %d", attributes[i + 3],
+		    attributes[i + 4] - attributes[i + 3]);
+	}
+    }
+    fprintf(stdout, ")\n");
 }
 
 /**
@@ -773,39 +785,6 @@
 	fprintf(stdout, ", '%s')\n", (char *) URI);
 }
 
-/**
- * attributeNsDebug:
- * @ctxt:  An XML parser context
- * @name:  The element name
- *
- * called when the end of an element has been detected.
- */
-static void
-attributeNsDebug(void *ctx ATTRIBUTE_UNUSED,
-                 const xmlChar *localname,
-                 const xmlChar *prefix,
-                 const xmlChar *URI,
-		 const xmlChar *value,
-		 int valuelen)
-{
-    callbacks++;
-    if (quiet)
-	return;
-    fprintf(stdout, "SAX.attributeNs(%s", (char *) localname);
-    if (prefix == NULL)
-	fprintf(stdout, ", NULL");
-    else
-	fprintf(stdout, ", %s", (char *) prefix);
-    if (URI == NULL)
-	fprintf(stdout, ", NULL");
-    else
-	fprintf(stdout, ", '%s'", (char *) URI);
-    if (valuelen > 13) 
-        fprintf(stdout, ", %10s..., %d)\n", value, valuelen);
-    else
-        fprintf(stdout, ", %s, %d)\n", value, valuelen);
-}
-
 xmlSAXHandler debugSAX2HandlerStruct = {
     internalSubsetDebug,
     isStandaloneDebug,
@@ -834,11 +813,10 @@
     getParameterEntityDebug,
     cdataBlockDebug,
     externalSubsetDebug,
-    1,
+    XML_SAX2_MAGIC,
     NULL,
     startElementNsDebug,
-    endElementNsDebug,
-    attributeNsDebug
+    endElementNsDebug
 };
 
 xmlSAXHandlerPtr debugSAX2Handler = &debugSAX2HandlerStruct;
diff --git a/tree.c b/tree.c
index ad99092..a68beb9 100644
--- a/tree.c
+++ b/tree.c
@@ -1078,15 +1078,18 @@
     xmlNodePtr ret = NULL, last = NULL;
     xmlNodePtr node;
     xmlChar *val;
-    const xmlChar *cur = value;
+    const xmlChar *cur = value, *end = cur + len;
     const xmlChar *q;
     xmlEntityPtr ent;
 
     if (value == NULL) return(NULL);
 
     q = cur;
-    while ((*cur != 0) && (cur - value < len)) {
-	if (*cur == '&') {
+    while ((cur < end) && (*cur != 0)) {
+	if (cur[0] == '&') {
+	    int charval = 0;
+	    xmlChar tmp;
+
 	    /*
 	     * Save the current text.
 	     */
@@ -1105,69 +1108,142 @@
 		    }
 		}
 	    }
-	    /*
-	     * Read the entity string
-	     */
-	    cur++;
 	    q = cur;
-	    while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
-	    if ((*cur == 0) || (cur - value >= len)) {
-#ifdef DEBUG_TREE
-	        xmlGenericError(xmlGenericErrorContext,
-		    "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
-#endif
-	        return(ret);
-	    }
-            if (cur != q) {
-		/*
-		 * Predefined entities don't generate nodes
-		 */
-		val = xmlStrndup(q, cur - q);
-		ent = xmlGetDocEntity(doc, val);
-		if ((ent != NULL) &&
-		    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
-		    if (last == NULL) {
-		        node = xmlNewDocText(doc, ent->content);
-			last = ret = node;
-		    } else
-		        xmlNodeAddContent(last, ent->content);
-		        
-		} else {
-		    /*
-		     * Create a new REFERENCE_REF node
-		     */
-		    node = xmlNewReference(doc, val);
-		    if (node == NULL) {
-			if (val != NULL) xmlFree(val);
-		        return(ret);
-		    }
-			else if ((ent != NULL) && (ent->children == NULL)) {
-				xmlNodePtr tmp;
-
-				ent->children =
-					xmlStringGetNodeList(doc, (const xmlChar*)node->content);
-				tmp = ent->children;
-				while (tmp) {
-					tmp->parent = (xmlNodePtr)ent;
-					tmp = tmp->next;
-				}
-			}
-		    if (last == NULL)
-			last = ret = node;
+	    if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
+		cur += 3;
+		if (cur < end)
+		    tmp = *cur;
+		else
+		    tmp = 0;
+		while (tmp != ';') { /* Non input consuming loop */
+		    if ((tmp >= '0') && (tmp <= '9')) 
+			charval = charval * 16 + (tmp - '0');
+		    else if ((tmp >= 'a') && (tmp <= 'f'))
+			charval = charval * 16 + (tmp - 'a') + 10;
+		    else if ((tmp >= 'A') && (tmp <= 'F'))
+			charval = charval * 16 + (tmp - 'A') + 10;
 		    else {
-			last->next = node;
-			node->prev = last;
-			last = node;
+			xmlGenericError(xmlGenericErrorContext,
+		    "xmlStringGetNodeList: invalid hexadecimal charvalue\n");
+			charval = 0;
+			break;
+		    }
+		    cur++;
+		    if (cur < end)
+			tmp = *cur;
+		    else
+			tmp = 0;
+		}
+		if (tmp == ';')
+		    cur++;
+		q = cur;
+	    } else if ((cur + 1 < end) && (cur[1] == '#')) {
+		cur += 2;
+		if (cur < end)
+		    tmp = *cur;
+		else
+		    tmp = 0;
+		while (tmp != ';') { /* Non input consuming loops */
+		    if ((tmp >= '0') && (tmp <= '9')) 
+			charval = charval * 10 + (tmp - '0');
+		    else {
+			xmlGenericError(xmlGenericErrorContext,
+		    "xmlStringGetNodeList: invalid decimal charvalue\n");
+			charval = 0;
+			break;
+		    }
+		    cur++;
+		    if (cur < end)
+			tmp = *cur;
+		    else
+			tmp = 0;
+		}
+		if (tmp == ';')
+		    cur++;
+		q = cur;
+	    } else {
+		/*
+		 * Read the entity string
+		 */
+		cur++;
+		q = cur;
+		while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
+		if ((cur >= end) || (*cur == 0)) {
+#ifdef DEBUG_TREE
+		    xmlGenericError(xmlGenericErrorContext,
+			    "xmlStringGetNodeList: unterminated entity %30s\n", q);
+#endif
+		    return(ret);
+		}
+		if (cur != q) {
+		    /*
+		     * Predefined entities don't generate nodes
+		     */
+		    val = xmlStrndup(q, cur - q);
+		    ent = xmlGetDocEntity(doc, val);
+		    if ((ent != NULL) &&
+			(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
+			if (last == NULL) {
+			    node = xmlNewDocText(doc, ent->content);
+			    last = ret = node;
+			} else if (last->type != XML_TEXT_NODE) {
+			    node = xmlNewDocText(doc, ent->content);
+			    last = xmlAddNextSibling(last, node);
+			} else
+			    xmlNodeAddContent(last, ent->content);
+			    
+		    } else {
+			/*
+			 * Create a new REFERENCE_REF node
+			 */
+			node = xmlNewReference(doc, val);
+			if (node == NULL) {
+			    if (val != NULL) xmlFree(val);
+			    return(ret);
+			}
+			else if ((ent != NULL) && (ent->children == NULL)) {
+			    xmlNodePtr temp;
+
+			    ent->children = xmlStringGetNodeList(doc,
+				    (const xmlChar*)node->content);
+			    ent->owner = 1;
+			    temp = ent->children;
+			    while (temp) {
+				temp->parent = (xmlNodePtr)ent;
+				temp = temp->next;
+			    }
+			}
+			if (last == NULL) {
+			    last = ret = node;
+			} else {
+			    last = xmlAddNextSibling(last, node);
+			}
+		    }
+		    xmlFree(val);
+		}
+		cur++;
+		q = cur;
+	    }
+	    if (charval != 0) {
+		xmlChar buf[10];
+		int l;
+
+		l = xmlCopyCharMultiByte(buf, charval);
+		buf[l] = 0;
+		node = xmlNewDocText(doc, buf);
+		if (node != NULL) {
+		    if (last == NULL) {
+			last = ret = node;
+		    } else {
+			last = xmlAddNextSibling(last, node);
 		    }
 		}
-		xmlFree(val);
+		charval = 0;
 	    }
-	    cur++;
-	    q = cur;
-	} else 
+	} else
 	    cur++;
     }
-    if (cur != q) {
+    if ((cur != q) || (ret == NULL)) {
         /*
 	 * Handle the last piece of text.
 	 */
@@ -1176,12 +1252,10 @@
 	} else {
 	    node = xmlNewDocTextLen(doc, q, cur - q);
 	    if (node == NULL) return(ret);
-	    if (last == NULL)
+	    if (last == NULL) {
 		last = ret = node;
-	    else {
-		last->next = node;
-		node->prev = last;
-		last = node;
+	    } else {
+		last = xmlAddNextSibling(last, node);
 	    }
 	}
     }
diff --git a/valid.c b/valid.c
index ace4b28..5e28d0d 100644
--- a/valid.c
+++ b/valid.c
@@ -3808,8 +3808,8 @@
 
 int
 xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
-                        xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value) {
-    /* xmlElementPtr elemDecl; */
+                        xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value) 
+{
     xmlAttributePtr attrDecl =  NULL;
     int val;
     int ret = 1;
diff --git a/xmlIO.c b/xmlIO.c
index df7d975..0c40946 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -1753,7 +1753,7 @@
 	if (xmlInputCallbackTable[i].opencallback == xmlGzfileOpen) {
 	    if (((z_stream *)context)->avail_in > 4) {
 	        char *cptr, buff4[4];
-		cptr = ((z_stream *)context)->next_in;
+		cptr = (char *) ((z_stream *)context)->next_in;
 		if (gzread(context, buff4, 4) == 4) {
 		    if (strncmp(buff4, cptr, 4) == 0)
 		        ret->compressed = 0;
diff --git a/xmllint.c b/xmllint.c
index ccf4ae0..200ce68 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -13,7 +13,7 @@
 #include <assert.h>
 
 #if defined (_WIN32) && !defined(__CYGWIN__)
-#ifdef _MSC_VER
+#if defined (_MSC_VER) || defined(__BORLANDC__)
 #include <winsock2.h>
 #pragma comment(lib, "ws2_32.lib")
 #define gettimeofday(p1,p2)
@@ -148,6 +148,7 @@
 #endif
 static int stream = 0;
 static int chkregister = 0;
+static int sax1 = 0;
 static const char *output = NULL;
 
 /*
@@ -1550,6 +1551,10 @@
 	         (!strcmp(argv[i], "--stream"))) {
 	     stream++;
 	}
+	else if ((!strcmp(argv[i], "-sax1")) ||
+	         (!strcmp(argv[i], "--sax1"))) {
+	     sax1++;
+	}
 	else if ((!strcmp(argv[i], "-chkregister")) ||
 	         (!strcmp(argv[i], "--chkregister"))) {
 	     chkregister++;
@@ -1590,6 +1595,11 @@
     }
 #endif
 
+    if (sax1)
+        xmlSAXDefaultVersion(1);
+    else
+        xmlSAXDefaultVersion(2);
+
     if (chkregister) {
 	xmlRegisterNodeDefault(registerNode);
 	xmlDeregisterNodeDefault(deregisterNode);
diff --git a/xmlreader.c b/xmlreader.c
index a8ec578..54778bd 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -103,6 +103,8 @@
     xmlParserInputBufferPtr	input;	/* the input */
     startElementSAXFunc		startElement;/* initial SAX callbacks */
     endElementSAXFunc		endElement;  /* idem */
+    startElementNsSAX2Func	startElementNs;/* idem */
+    endElementNsSAX2Func		endElementNs;  /* idem */
     charactersSAXFunc		characters;
     cdataBlockSAXFunc		cdataBlock;
     unsigned int 		base;	/* base of the segment in the input */
@@ -272,6 +274,78 @@
 }
 
 /**
+ * xmlTextReaderStartElementNs:
+ * @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
+ * nb_defaulted:  the number of defaulted attributes.
+ * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
+ *               attribute values.
+ *
+ * called when an opening tag has been processed.
+ */
+static void
+xmlTextReaderStartElementNs(void *ctx,
+                      const xmlChar *localname,
+		      const xmlChar *prefix,
+		      const xmlChar *URI,
+		      int nb_namespaces,
+		      const xmlChar **namespaces,
+		      int nb_attributes,
+		      int nb_defaulted,
+		      const xmlChar **attributes)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlTextReaderPtr reader = ctxt->_private;
+
+#ifdef DEBUG_CALLBACKS
+    printf("xmlTextReaderStartElementNs(%s)\n", fullname);
+#endif
+    if ((reader != NULL) && (reader->startElementNs != NULL)) {
+	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
+	                       namespaces, nb_attributes, nb_defaulted,
+			       attributes);
+	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
+	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
+	    (ctxt->input->cur[1] == '>'))
+	    ctxt->node->_private = (void *) xmlTextReaderIsEmpty;
+    }
+    if (reader != NULL)
+	reader->state = XML_TEXTREADER_ELEMENT;
+}
+
+/**
+ * xmlTextReaderEndElementNs:
+ * @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
+ *
+ * called when an ending tag has been processed.
+ */
+static void
+xmlTextReaderEndElementNs(void *ctx,
+                          const xmlChar * localname,
+                          const xmlChar * prefix,
+		          const xmlChar * URI)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    xmlTextReaderPtr reader = ctxt->_private;
+
+#ifdef DEBUG_CALLBACKS
+    printf("xmlTextReaderEndElementNs(%s)\n", fullname);
+#endif
+    if ((reader != NULL) && (reader->endElementNs != NULL)) {
+	reader->endElementNs(ctx, localname, prefix, URI);
+    }
+}
+
+
+/**
  * xmlTextReaderCharacters:
  * @ctx: the user data (XML parser context)
  * @ch:  a xmlChar string
@@ -1123,6 +1197,15 @@
     ret->sax->startElement = xmlTextReaderStartElement;
     ret->endElement = ret->sax->endElement;
     ret->sax->endElement = xmlTextReaderEndElement;
+    if (ret->sax->initialized == XML_SAX2_MAGIC) {
+	ret->startElementNs = ret->sax->startElementNs;
+	ret->sax->startElementNs = xmlTextReaderStartElementNs;
+	ret->endElementNs = ret->sax->endElementNs;
+	ret->sax->endElementNs = xmlTextReaderEndElementNs;
+    } else {
+	ret->startElementNs = NULL;
+	ret->endElementNs = NULL;
+    }
     ret->characters = ret->sax->characters;
     ret->sax->characters = xmlTextReaderCharacters;
     ret->sax->ignorableWhitespace = xmlTextReaderCharacters;