added checking for names values and dictionnaries generates a tons of

* debugXML.c include/libxml/xmlerror.h: added checking for names
  values and dictionnaries generates a tons of errors
* SAX2.ccatalog.c parser.c relaxng.c tree.c xinclude.c xmlwriter.c
  include/libxml/tree.h: fixing the errors in the regression tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index 59d3807..34e3d25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Tue Oct 26 18:09:59 CEST 2004 Daniel Veillard <daniel@veillard.com>
+
+	* debugXML.c include/libxml/xmlerror.h: added checking for names
+	  values and dictionnaries generates a tons of errors
+	* SAX2.ccatalog.c parser.c relaxng.c tree.c xinclude.c xmlwriter.c
+	  include/libxml/tree.h: fixing the errors in the regression tests
+
 Mon Oct 25 16:04:22 PDT 2004 William Brack <wbrack@mmm.com.hk>
 
 	* parser.c: modified the handling of _private for entity
diff --git a/Makefile.am b/Makefile.am
index adb13ad..583e812 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -277,7 +277,7 @@
 	      log=`$(CHECKER) $(top_builddir)/xmllint $$i 2> error.$$name > result.$$name ; \
 	      grep "MORY ALLO" .memdump  | grep -v "MEMORY ALLOCATED : 0"; \
 	      diff $(srcdir)/result/namespaces/$$name result.$$name ; \
-	      diff $(srcdir)/result/namespaces/$$name.err error.$$name` ; \
+	      diff $(srcdir)/result/namespaces/$$name.err error.$$name`; \
 	      if [ -n "$$log" ] ; then echo $$name result ; echo $$log ; fi ; \
 	      rm result.$$name error.$$name ; \
 	  fi ; fi ; done)
diff --git a/SAX2.c b/SAX2.c
index ddb13e9..cda9ac5 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -2364,7 +2364,7 @@
 	    "SAX.xmlSAX2ProcessingInstruction(%s, %s)\n", target, data);
 #endif
 
-    ret = xmlNewPI(target, data);
+    ret = xmlNewDocPI(ctxt->myDoc, target, data);
     if (ret == NULL) return;
     parent = ctxt->node;
 
diff --git a/catalog.c b/catalog.c
index 3198fc1..93356cd 100644
--- a/catalog.c
+++ b/catalog.c
@@ -912,6 +912,7 @@
     ctxt->validate = 0;
     ctxt->loadsubset = 0;
     ctxt->pedantic = 0;
+    ctxt->dictNames = 1;
 
     xmlParseDocument(ctxt);
 
diff --git a/debugXML.c b/debugXML.c
index afc0114..d0e17c2 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -42,8 +42,10 @@
     int depth;                  /* current depth */
     xmlDocPtr doc;              /* current document */
     xmlNodePtr node;		/* current node */
+    xmlDictPtr dict;		/* the doc dictionnary */
     int check;                  /* do just checkings */
     int errors;                 /* number of errors found */
+    int nodict;			/* if the document has no dictionnary */
 };
 
 static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
@@ -57,6 +59,9 @@
     ctxt->check = 0;
     ctxt->errors = 0;
     ctxt->output = stdout;
+    ctxt->doc = NULL;
+    ctxt->node = NULL;
+    ctxt->dict = NULL;
     for (i = 0; i < 100; i++)
         ctxt->shift[i] = ' ';
     ctxt->shift[100] = 0;
@@ -222,20 +227,69 @@
     if (str == NULL) return;
     if (ctxt->check) {
         if (!xmlCheckUTF8(str)) {
-	    xmlDebugErr3(ctxt, XML_CHECK_NOT_DTD,
+	    xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
 			 "String is not UTF-8 %s", (const char *) str);
 	}
     }
 }
 
+/**
+ * xmlCtxtCheckName:
+ * @ctxt: the debug context
+ * @name: the name
+ *
+ * Do debugging on the name, for example the dictionnary status and
+ * conformance to the Name production.
+ */
+static void
+xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
+{
+    if (ctxt->check) {
+	if (name == NULL) {
+	    xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
+	    return;
+	}
+        if (xmlValidateName(name, 0)) {
+	    xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
+			 "Name is not an NCName '%s'", (const char *) name);
+	}
+	if ((ctxt->dict != NULL) &&
+	    (!xmlDictOwns(ctxt->dict, name))) {
+	    xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
+			 "Name is not from the document dictionnary '%s'",
+			 (const char *) name);
+	}
+    }
+}
+
 static void
 xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
+    xmlDocPtr doc;
+    xmlDictPtr dict;
+
+    doc = node->doc;
+
     if (node->parent == NULL)
         xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
 	            "Node has no parent\n");
-    if (node->doc == NULL)
+    if (node->doc == NULL) {
         xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
 	            "Node has no doc\n");
+        dict = NULL;
+    } else {
+	dict = doc->dict;
+	if ((dict == NULL) && (ctxt->nodict == 0)) {
+	    xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
+			"Document has no dictionnary\n");
+	    ctxt->nodict = 1;
+	}
+	if (ctxt->doc == NULL)
+	    ctxt->doc = doc;
+
+	if (ctxt->dict == NULL) {
+	    ctxt->dict = dict;
+	}
+    }
     if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
         (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
         xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
@@ -292,6 +346,60 @@
 	if (node->content != NULL)
 	    xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
     }
+    switch (node->type) {
+        case XML_ELEMENT_NODE:
+        case XML_ATTRIBUTE_NODE:
+	    xmlCtxtCheckName(ctxt, node->name);
+	    break;
+        case XML_TEXT_NODE:
+	    if ((node->name == xmlStringText) ||
+	        (node->name == xmlStringTextNoenc))
+		break;
+	    /* some case of entity substitution can lead to this */
+	    if ((ctxt->dict != NULL) &&
+	        (node->name == xmlDictLookup(ctxt->dict, "nbktext", 7)))
+		break;
+
+	    xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
+			 "Text node has wrong name '%s'",
+			 (const char *) node->name);
+	    break;
+        case XML_COMMENT_NODE:
+	    if (node->name == xmlStringComment)
+		break;
+	    xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
+			 "Comment node has wrong name '%s'",
+			 (const char *) node->name);
+	    break;
+        case XML_PI_NODE:
+	    xmlCtxtCheckName(ctxt, node->name);
+	    break;
+        case XML_CDATA_SECTION_NODE:
+	    if (node->name == NULL)
+		break;
+	    xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
+			 "CData section has non NULL name '%s'",
+			 (const char *) node->name);
+	    break;
+        case XML_ENTITY_REF_NODE:
+        case XML_ENTITY_NODE:
+        case XML_DOCUMENT_TYPE_NODE:
+        case XML_DOCUMENT_FRAG_NODE:
+        case XML_NOTATION_NODE:
+        case XML_DTD_NODE:
+        case XML_ELEMENT_DECL:
+        case XML_ATTRIBUTE_DECL:
+        case XML_ENTITY_DECL:
+        case XML_NAMESPACE_DECL:
+        case XML_XINCLUDE_START:
+        case XML_XINCLUDE_END:
+#ifdef LIBXML_DOCB_ENABLED
+        case XML_DOCB_DOCUMENT_NODE:
+#endif
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+	    break;
+    }
 }
 
 static void
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index ee6e828..9667916 100644
--- a/doc/examples/Makefile.am
+++ b/doc/examples/Makefile.am
@@ -15,7 +15,7 @@
 	$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)
 	-@INSTALL@ -m 0644 $(srcdir)/*.html $(srcdir)/*.c $(srcdir)/*.xml $(srcdir)/*.xsl $(srcdir)/*.res $(DESTDIR)$(HTML_DIR)
 
-EXTRA_DIST=examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml tst.xml reader1.res reader3.res tree1.res tree2.res io1.res io2.res xpath1.res xpath2.res 
+EXTRA_DIST=examples.xsl index.py test1.xml examples.xml test2.xml writer.xml test3.xml tst.xml reader1.res reader3.res tree1.res tree2.res io1.res io2.res xpath1.res xpath2.res reader4.res 
 
 noinst_PROGRAMS=xpath1 parse1 parse2 tree1 tree2 testWriter reader1 reader2 reader3 io1 parse3 parse4 io2 xpath2 reader4 
 
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 7615ff2..e2a5d01 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -724,6 +724,10 @@
 XMLPUBFUN xmlNodePtr XMLCALL	
 		xmlNewText		(const xmlChar *content);
 XMLPUBFUN xmlNodePtr XMLCALL	
+		xmlNewDocPI		(xmlDocPtr doc,
+					 const xmlChar *name,
+					 const xmlChar *content);
+XMLPUBFUN xmlNodePtr XMLCALL	
 		xmlNewPI		(const xmlChar *name,
 					 const xmlChar *content);
 XMLPUBFUN xmlNodePtr XMLCALL	
@@ -756,6 +760,9 @@
 					 xmlDocPtr doc,
 					 int recursive);
 XMLPUBFUN xmlNodePtr XMLCALL	
+		xmlDocCopyNodeList	(xmlDocPtr doc,
+					 const xmlNodePtr node);
+XMLPUBFUN xmlNodePtr XMLCALL	
 		xmlCopyNodeList		(const xmlNodePtr node);
 #ifdef LIBXML_TREE_ENABLED
 XMLPUBFUN xmlNodePtr XMLCALL	
diff --git a/include/libxml/xmlerror.h b/include/libxml/xmlerror.h
index 61a5ece..d893369 100644
--- a/include/libxml/xmlerror.h
+++ b/include/libxml/xmlerror.h
@@ -777,7 +777,12 @@
     XML_CHECK_WRONG_PARENT,/* 5029 */
     XML_CHECK_NS_SCOPE, /* 5030 */
     XML_CHECK_NS_ANCESTOR, /* 5031 */
-    XML_CHECK_NOT_UTF8 /* 5032 */
+    XML_CHECK_NOT_UTF8, /* 5032 */
+    XML_CHECK_NO_DICT, /* 5033 */
+    XML_CHECK_NOT_NCNAME, /* 5034 */
+    XML_CHECK_OUTSIDE_DICT, /* 5035 */
+    XML_CHECK_WRONG_NAME, /* 5036 */
+    XML_CHECK_NAME_NOT_NULL /* 5037 */
 #if 0
     XML_CHECK_, /* 5033 */
     XML_CHECK_X /* 503 */
diff --git a/parser.c b/parser.c
index 21e7aad..b5ecd2e 100644
--- a/parser.c
+++ b/parser.c
@@ -5643,7 +5643,7 @@
 
 			cur = ent->children;
 			while (cur != NULL) {
-			    nw = xmlCopyNode(cur, 1);
+			    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 			    if (nw != NULL) {
 				if (nw->_private == NULL)
 				    nw->_private = cur->_private;
@@ -5687,7 +5687,7 @@
 			    next = cur->next;
 			    cur->next = NULL;
 			    cur->parent = NULL;
-			    nw = xmlCopyNode(cur, 1);
+			    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
 			    if (nw != NULL) {
 				if (nw->_private == NULL)
 				    nw->_private = cur->_private;
@@ -9937,6 +9937,7 @@
 	xmlFreeParserInputBuffer(buf);
 	return(NULL);
     }
+    ctxt->dictNames = 1;
     ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
     if (ctxt->pushTab == NULL) {
         xmlErrMemory(ctxt, NULL);
@@ -10385,6 +10386,10 @@
 	xmlFreeParserCtxt(ctxt);
 	return(-1);
     }
+    if (ctx->myDoc->dict) {
+	newDoc->dict = ctx->myDoc->dict;
+	xmlDictReference(newDoc->dict);
+    }
     if (ctx->myDoc != NULL) {
 	newDoc->intSubset = ctx->myDoc->intSubset;
 	newDoc->extSubset = ctx->myDoc->extSubset;
@@ -10596,7 +10601,12 @@
     if (doc != NULL) {
 	newDoc->intSubset = doc->intSubset;
 	newDoc->extSubset = doc->extSubset;
+	newDoc->dict = doc->dict;
+    } else if (oldctxt != NULL) {
+	newDoc->dict = oldctxt->dict;
     }
+    xmlDictReference(newDoc->dict);
+
     if (doc->URL != NULL) {
 	newDoc->URL = xmlStrdup(doc->URL);
     }
@@ -10827,6 +10837,8 @@
 	    xmlFreeParserCtxt(ctxt);
 	    return(XML_ERR_INTERNAL_ERROR);
 	}
+	newDoc->dict = ctxt->dict;
+	xmlDictReference(newDoc->dict);
 	ctxt->myDoc = newDoc;
     } else {
 	ctxt->myDoc = oldctxt->myDoc;
@@ -10838,8 +10850,9 @@
 	ctxt->sax = oldsax;
 	ctxt->dict = NULL;
 	xmlFreeParserCtxt(ctxt);
-	if (newDoc != NULL)
+	if (newDoc != NULL) {
 	    xmlFreeDoc(newDoc);
+	}
 	return(XML_ERR_INTERNAL_ERROR);
     }
     ctxt->myDoc->children = NULL;
@@ -10913,8 +10926,9 @@
     ctxt->attsDefault = NULL;
     ctxt->attsSpecial = NULL;
     xmlFreeParserCtxt(ctxt);
-    if (newDoc != NULL)
+    if (newDoc != NULL) {
 	xmlFreeDoc(newDoc);
+    }
     
     return(ret);
 }
@@ -11179,6 +11193,8 @@
 	xmlFreeParserCtxt(ctxt);
 	return(-1);
     }
+    newDoc->dict = ctxt->dict;
+    xmlDictReference(newDoc->dict);
     if (doc != NULL) {
 	newDoc->intSubset = doc->intSubset;
 	newDoc->extSubset = doc->extSubset;
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index 576750c..433da9c 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -647,6 +647,56 @@
 
     # functions from module xpointer
     xpointerNewContext()
+Class xpathContext()
+    # accessors
+    contextDoc()
+    contextNode()
+    contextPosition()
+    contextSize()
+    function()
+    functionURI()
+    setContextDoc()
+    setContextNode()
+
+    # functions from module python
+    registerXPathFunction()
+
+    # functions from module xpath
+    xpathEval()
+    xpathEvalExpression()
+    xpathFreeContext()
+
+    # functions from module xpathInternals
+    xpathNewParserContext()
+    xpathNsLookup()
+    xpathRegisterAllFunctions()
+    xpathRegisterNs()
+    xpathRegisteredFuncsCleanup()
+    xpathRegisteredNsCleanup()
+    xpathRegisteredVariablesCleanup()
+    xpathVariableLookup()
+    xpathVariableLookupNS()
+
+    # functions from module xpointer
+    xpointerEval()
+
+
+Class xmlAttribute(xmlNode)
+Class catalog()
+
+    # functions from module catalog
+    add()
+    catalogIsEmpty()
+    convertSGMLCatalog()
+    dump()
+    remove()
+    resolve()
+    resolvePublic()
+    resolveSystem()
+    resolveURI()
+
+
+Class xmlElement(xmlNode)
 
 
 Class xmlAttr(xmlNode)
@@ -665,12 +715,100 @@
     # functions from module valid
     removeID()
     removeRef()
+
+
+Class xmlTextReader(xmlTextReaderCore)
+
+    # functions from module xmlreader
+    AttributeCount()
+    BaseUri()
+    Close()
+    CurrentDoc()
+    CurrentNode()
+    Depth()
+    Expand()
+    GetAttribute()
+    GetAttributeNo()
+    GetAttributeNs()
+    GetParserProp()
+    GetRemainder()
+    HasAttributes()
+    HasValue()
+    IsDefault()
+    IsEmptyElement()
+    IsValid()
+    LocalName()
+    LookupNamespace()
+    MoveToAttribute()
+    MoveToAttributeNo()
+    MoveToAttributeNs()
+    MoveToElement()
+    MoveToFirstAttribute()
+    MoveToNextAttribute()
+    Name()
+    NamespaceUri()
+    NewDoc()
+    NewFd()
+    NewFile()
+    NewMemory()
+    NewWalker()
+    Next()
+    NextSibling()
+    NodeType()
+    Normalization()
+    Prefix()
+    Preserve()
+    QuoteChar()
+    Read()
+    ReadAttributeValue()
+    ReadInnerXml()
+    ReadOuterXml()
+    ReadState()
+    ReadString()
+    RelaxNGSetSchema()
+    RelaxNGValidate()
+    SetParserProp()
+    String()
+    Value()
+    XmlLang()
 Class xmlReg()
 
     # functions from module xmlregexp
     regexpExec()
     regexpIsDeterminist()
     regexpPrint()
+
+
+Class xmlEntity(xmlNode)
+
+    # functions from module parserInternals
+    handleEntity()
+Class relaxNgSchema()
+
+    # functions from module relaxng
+    relaxNGDump()
+    relaxNGDumpTree()
+    relaxNGNewValidCtxt()
+
+    # functions from module xmlreader
+    RelaxNGSetSchema()
+Class Schema()
+
+    # functions from module xmlschemas
+    schemaDump()
+    schemaNewValidCtxt()
+Class Error()
+    # accessors
+    code()
+    domain()
+    file()
+    level()
+    line()
+    message()
+
+    # functions from module xmlerror
+    copyError()
+    resetError()
 Class relaxNgValidCtxt()
 
     # functions from module relaxng
@@ -679,6 +817,73 @@
     relaxNGValidatePopElement()
     relaxNGValidatePushCData()
     relaxNGValidatePushElement()
+Class xpathParserContext()
+    # accessors
+    context()
+
+    # functions from module xpathInternals
+    xpathAddValues()
+    xpathBooleanFunction()
+    xpathCeilingFunction()
+    xpathCompareValues()
+    xpathConcatFunction()
+    xpathContainsFunction()
+    xpathCountFunction()
+    xpathDivValues()
+    xpathEqualValues()
+    xpathErr()
+    xpathEvalExpr()
+    xpathFalseFunction()
+    xpathFloorFunction()
+    xpathFreeParserContext()
+    xpathIdFunction()
+    xpathLangFunction()
+    xpathLastFunction()
+    xpathLocalNameFunction()
+    xpathModValues()
+    xpathMultValues()
+    xpathNamespaceURIFunction()
+    xpathNextAncestor()
+    xpathNextAncestorOrSelf()
+    xpathNextAttribute()
+    xpathNextChild()
+    xpathNextDescendant()
+    xpathNextDescendantOrSelf()
+    xpathNextFollowing()
+    xpathNextFollowingSibling()
+    xpathNextNamespace()
+    xpathNextParent()
+    xpathNextPreceding()
+    xpathNextPrecedingSibling()
+    xpathNextSelf()
+    xpathNormalizeFunction()
+    xpathNotEqualValues()
+    xpathNotFunction()
+    xpathNumberFunction()
+    xpathParseNCName()
+    xpathParseName()
+    xpathPopBoolean()
+    xpathPopNumber()
+    xpathPopString()
+    xpathPositionFunction()
+    xpathRoot()
+    xpathRoundFunction()
+    xpathStartsWithFunction()
+    xpathStringFunction()
+    xpathStringLengthFunction()
+    xpathSubValues()
+    xpathSubstringAfterFunction()
+    xpathSubstringBeforeFunction()
+    xpathSubstringFunction()
+    xpathSumFunction()
+    xpathTranslateFunction()
+    xpathTrueFunction()
+    xpathValueFlipSign()
+    xpatherror()
+
+    # functions from module xpointer
+    xpointerEvalRangePredicate()
+    xpointerRangeToFunction()
 
 
 Class parserCtxt(parserCtxtCore)
@@ -786,94 +991,6 @@
     dtdElementDesc()
     dtdQAttrDesc()
     dtdQElementDesc()
-Class relaxNgParserCtxt()
-
-    # functions from module relaxng
-    relaxNGParse()
-    relaxParserSetFlag()
-Class xpathParserContext()
-    # accessors
-    context()
-
-    # functions from module xpathInternals
-    xpathAddValues()
-    xpathBooleanFunction()
-    xpathCeilingFunction()
-    xpathCompareValues()
-    xpathConcatFunction()
-    xpathContainsFunction()
-    xpathCountFunction()
-    xpathDivValues()
-    xpathEqualValues()
-    xpathErr()
-    xpathEvalExpr()
-    xpathFalseFunction()
-    xpathFloorFunction()
-    xpathFreeParserContext()
-    xpathIdFunction()
-    xpathLangFunction()
-    xpathLastFunction()
-    xpathLocalNameFunction()
-    xpathModValues()
-    xpathMultValues()
-    xpathNamespaceURIFunction()
-    xpathNextAncestor()
-    xpathNextAncestorOrSelf()
-    xpathNextAttribute()
-    xpathNextChild()
-    xpathNextDescendant()
-    xpathNextDescendantOrSelf()
-    xpathNextFollowing()
-    xpathNextFollowingSibling()
-    xpathNextNamespace()
-    xpathNextParent()
-    xpathNextPreceding()
-    xpathNextPrecedingSibling()
-    xpathNextSelf()
-    xpathNormalizeFunction()
-    xpathNotEqualValues()
-    xpathNotFunction()
-    xpathNumberFunction()
-    xpathParseNCName()
-    xpathParseName()
-    xpathPopBoolean()
-    xpathPopNumber()
-    xpathPopString()
-    xpathPositionFunction()
-    xpathRoot()
-    xpathRoundFunction()
-    xpathStartsWithFunction()
-    xpathStringFunction()
-    xpathStringLengthFunction()
-    xpathSubValues()
-    xpathSubstringAfterFunction()
-    xpathSubstringBeforeFunction()
-    xpathSubstringFunction()
-    xpathSumFunction()
-    xpathTranslateFunction()
-    xpathTrueFunction()
-    xpathValueFlipSign()
-    xpatherror()
-
-    # functions from module xpointer
-    xpointerEvalRangePredicate()
-    xpointerRangeToFunction()
-Class SchemaParserCtxt()
-
-    # functions from module xmlschemas
-    schemaParse()
-Class catalog()
-
-    # functions from module catalog
-    add()
-    catalogIsEmpty()
-    convertSGMLCatalog()
-    dump()
-    remove()
-    resolve()
-    resolvePublic()
-    resolveSystem()
-    resolveURI()
 
 
 Class xmlNs(xmlNode)
@@ -897,6 +1014,51 @@
 
     # functions from module xpathInternals
     xpathNodeSetFreeNs()
+
+
+Class inputBuffer(ioReadWrapper)
+
+    # functions from module xmlIO
+    grow()
+    push()
+    read()
+
+    # functions from module xmlreader
+    newTextReader()
+Class relaxNgParserCtxt()
+
+    # functions from module relaxng
+    relaxNGParse()
+    relaxParserSetFlag()
+
+
+Class outputBuffer(ioWriteWrapper)
+
+    # functions from module HTMLtree
+    htmlDocContentDumpFormatOutput()
+    htmlDocContentDumpOutput()
+    htmlNodeDumpFormatOutput()
+    htmlNodeDumpOutput()
+
+    # functions from module tree
+    nodeDumpOutput()
+    saveFileTo()
+    saveFormatFileTo()
+
+    # functions from module xmlIO
+    write()
+    writeString()
+Class SchemaParserCtxt()
+
+    # functions from module xmlschemas
+    schemaParse()
+Class SchemaValidCtxt()
+
+    # functions from module xmlschemas
+    schemaSetValidOptions()
+    schemaValidCtxtGetOptions()
+    schemaValidateDoc()
+    schemaValidateOneElement()
 Class xmlTextReaderLocator()
 
     # functions from module xmlreader
@@ -927,165 +1089,3 @@
     parseURIReference()
     printURI()
     saveUri()
-
-
-Class xmlAttribute(xmlNode)
-Class xpathContext()
-    # accessors
-    contextDoc()
-    contextNode()
-    contextPosition()
-    contextSize()
-    function()
-    functionURI()
-    setContextDoc()
-    setContextNode()
-
-    # functions from module python
-    registerXPathFunction()
-
-    # functions from module xpath
-    xpathEval()
-    xpathEvalExpression()
-    xpathFreeContext()
-
-    # functions from module xpathInternals
-    xpathNewParserContext()
-    xpathNsLookup()
-    xpathRegisterAllFunctions()
-    xpathRegisterNs()
-    xpathRegisteredFuncsCleanup()
-    xpathRegisteredNsCleanup()
-    xpathRegisteredVariablesCleanup()
-    xpathVariableLookup()
-    xpathVariableLookupNS()
-
-    # functions from module xpointer
-    xpointerEval()
-
-
-Class xmlElement(xmlNode)
-
-
-Class xmlTextReader(xmlTextReaderCore)
-
-    # functions from module xmlreader
-    AttributeCount()
-    BaseUri()
-    Close()
-    CurrentDoc()
-    CurrentNode()
-    Depth()
-    Expand()
-    GetAttribute()
-    GetAttributeNo()
-    GetAttributeNs()
-    GetParserProp()
-    GetRemainder()
-    HasAttributes()
-    HasValue()
-    IsDefault()
-    IsEmptyElement()
-    IsValid()
-    LocalName()
-    LookupNamespace()
-    MoveToAttribute()
-    MoveToAttributeNo()
-    MoveToAttributeNs()
-    MoveToElement()
-    MoveToFirstAttribute()
-    MoveToNextAttribute()
-    Name()
-    NamespaceUri()
-    NewDoc()
-    NewFd()
-    NewFile()
-    NewMemory()
-    NewWalker()
-    Next()
-    NextSibling()
-    NodeType()
-    Normalization()
-    Prefix()
-    Preserve()
-    QuoteChar()
-    Read()
-    ReadAttributeValue()
-    ReadInnerXml()
-    ReadOuterXml()
-    ReadState()
-    ReadString()
-    RelaxNGSetSchema()
-    RelaxNGValidate()
-    SetParserProp()
-    String()
-    Value()
-    XmlLang()
-
-
-Class xmlEntity(xmlNode)
-
-    # functions from module parserInternals
-    handleEntity()
-Class Schema()
-
-    # functions from module xmlschemas
-    schemaDump()
-    schemaNewValidCtxt()
-Class Error()
-    # accessors
-    code()
-    domain()
-    file()
-    level()
-    line()
-    message()
-
-    # functions from module xmlerror
-    copyError()
-    resetError()
-Class relaxNgSchema()
-
-    # functions from module relaxng
-    relaxNGDump()
-    relaxNGDumpTree()
-    relaxNGNewValidCtxt()
-
-    # functions from module xmlreader
-    RelaxNGSetSchema()
-
-
-Class inputBuffer(ioReadWrapper)
-
-    # functions from module xmlIO
-    grow()
-    push()
-    read()
-
-    # functions from module xmlreader
-    newTextReader()
-Class SchemaValidCtxt()
-
-    # functions from module xmlschemas
-    schemaSetValidOptions()
-    schemaValidCtxtGetOptions()
-    schemaValidateDoc()
-    schemaValidateOneElement()
-
-
-Class outputBuffer(ioWriteWrapper)
-
-    # functions from module HTMLtree
-    htmlDocContentDumpFormatOutput()
-    htmlDocContentDumpOutput()
-    htmlNodeDumpFormatOutput()
-    htmlNodeDumpOutput()
-
-    # functions from module tree
-    nodeDumpOutput()
-    saveFileTo()
-    saveFormatFileTo()
-
-    # functions from module xmlIO
-    write()
-    writeString()
diff --git a/relaxng.c b/relaxng.c
index 9c6cf2d..ae6c63d 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -7024,7 +7024,8 @@
                         } else {
                             xmlNodePtr node;
 
-                            node = xmlNewNode(cur->ns, BAD_CAST "name");
+                            node = xmlNewDocNode(cur->doc, cur->ns,
+			                         BAD_CAST "name", NULL);
                             if (node != NULL) {
                                 xmlAddPrevSibling(cur->children, node);
                                 text = xmlNewText(name);
diff --git a/tree.c b/tree.c
index bf112ca..c324e54 100644
--- a/tree.c
+++ b/tree.c
@@ -329,7 +329,7 @@
  
 #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
 
-#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
+#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
 /**
  * xmlValidateNCName:
  * @value: the value to check
@@ -1749,7 +1749,10 @@
 	doc = node->doc;
 	cur->doc = doc;
     }
-    cur->name = xmlStrdup(name);
+    if ((doc != NULL) && (doc->dict != NULL))
+        cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
+    else
+	cur->name = xmlStrdup(name);
     if (value != NULL) {
 	xmlChar *buffer;
 	xmlNodePtr tmp;
@@ -1830,7 +1833,10 @@
 	cur->doc = doc;
     }
     cur->ns = ns;
-    cur->name = xmlStrdup(name);
+    if ((doc != NULL) && (doc->dict != NULL))
+	cur->name = xmlDictLookup(doc->dict, name, -1);
+    else
+	cur->name = xmlStrdup(name);
     if (value != NULL) {
 	xmlChar *buffer;
 	xmlNodePtr tmp;
@@ -1979,7 +1985,10 @@
     memset(cur, 0, sizeof(xmlAttr));
     cur->type = XML_ATTRIBUTE_NODE;
 
-    cur->name = xmlStrdup(name);
+    if ((doc != NULL) && (doc->dict != NULL))
+	cur->name = xmlDictLookup(doc->dict, name, -1);
+    else
+	cur->name = xmlStrdup(name);
     cur->doc = doc; 
     if (value != NULL) {
 	xmlNodePtr tmp;
@@ -2098,7 +2107,8 @@
 #endif /* LIBXML_TREE_ENABLED */
 
 /**
- * xmlNewPI:
+ * xmlNewDocPI:
+ * @doc:  the target document
  * @name:  the processing instruction name
  * @content:  the PI content
  *
@@ -2106,7 +2116,7 @@
  * Returns a pointer to the new node object.
  */
 xmlNodePtr
-xmlNewPI(const xmlChar *name, const xmlChar *content) {
+xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur;
 
     if (name == NULL) {
@@ -2128,7 +2138,10 @@
     memset(cur, 0, sizeof(xmlNode));
     cur->type = XML_PI_NODE;
 
-    cur->name = xmlStrdup(name);
+    if ((doc != NULL) && (doc->dict != NULL))
+        cur->name = xmlDictLookup(doc->dict, name, -1);
+    else
+	cur->name = xmlStrdup(name);
     if (content != NULL) {
 	cur->content = xmlStrdup(content);
     }
@@ -2139,6 +2152,21 @@
 }
 
 /**
+ * xmlNewPI:
+ * @name:  the processing instruction name
+ * @content:  the PI content
+ *
+ * Creation of a processing instruction element.
+ * Use xmlDocNewPI preferably to get string interning
+ *
+ * Returns a pointer to the new node object.
+ */
+xmlNodePtr
+xmlNewPI(const xmlChar *name, const xmlChar *content) {
+    return(xmlNewDocPI(NULL, name, content));
+}
+
+/**
  * xmlNewNode:
  * @ns:  namespace if any
  * @name:  the node name
@@ -2242,7 +2270,11 @@
               const xmlChar *name, const xmlChar *content) {
     xmlNodePtr cur;
 
-    cur = xmlNewNode(ns, name);
+    if (doc->dict != NULL)
+        cur = xmlNewNodeEatName(ns, (xmlChar *)
+	                        xmlDictLookup(doc->dict, name, -1));
+    else
+	cur = xmlNewNode(ns, name);
     if (cur != NULL) {
         cur->doc = doc;
 	if (content != NULL) {
@@ -3804,8 +3836,12 @@
 	ret->name = xmlStringTextNoenc;
     else if (node->name == xmlStringComment)
 	ret->name = xmlStringComment;
-    else if (node->name != NULL)
-	ret->name = xmlStrdup(node->name);
+    else if (node->name != NULL) {
+        if ((doc != NULL) && (doc->dict != NULL))
+	    ret->name = xmlDictLookup(doc->dict, node->name, -1);
+	else
+	    ret->name = xmlStrdup(node->name);
+    }
     if ((node->type != XML_ELEMENT_NODE) &&
 	(node->content != NULL) &&
 	(node->type != XML_ENTITY_REF_NODE) &&
@@ -3969,10 +4005,25 @@
 }
 
 /**
+ * xmlDocCopyNodeList:
+ * @doc: the target document
+ * @node:  the first node in the list.
+ *
+ * Do a recursive copy of the node list.
+ *
+ * Returns: a new #xmlNodePtr, or NULL in case of error.
+ */
+xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, const xmlNodePtr node) {
+    xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
+    return(ret);
+}
+
+/**
  * xmlCopyNodeList:
  * @node:  the first node in the list.
  *
  * Do a recursive copy of the node list.
+ * Use xmlDocCopyNodeList() if possible to ensure string interning.
  *
  * Returns: a new #xmlNodePtr, or NULL in case of error.
  */
diff --git a/xinclude.c b/xinclude.c
index f43a2e8..385faff 100644
--- a/xinclude.c
+++ b/xinclude.c
@@ -1872,7 +1872,8 @@
 	    ret = 0;	/* xmlXIncludeDoProcess can return +ve number */
 	xmlXIncludeFreeContext(newctxt);
 
-	ctxt->incTab[nr]->inc = xmlCopyNodeList(fallback->children);
+	ctxt->incTab[nr]->inc = xmlDocCopyNodeList(ctxt->doc,
+	                                           fallback->children);
     } else {
         ctxt->incTab[nr]->inc = NULL;
 	ctxt->incTab[nr]->emptyFb = 1;	/* flag empty callback */
@@ -2134,7 +2135,7 @@
 	 * XInclude end one
 	 */
 	cur->type = XML_XINCLUDE_START;
-	end = xmlNewNode(cur->ns, cur->name);
+	end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL);
 	if (end == NULL) {
 	    xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref,
 	                   XML_XINCLUDE_BUILD_FAILED,
diff --git a/xmlwriter.c b/xmlwriter.c
index 5a7120d..2a267cc 100644
--- a/xmlwriter.c
+++ b/xmlwriter.c
@@ -304,6 +304,11 @@
                         "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
         return NULL;
     }
+    /*
+     * For some reason this seems to completely break if node names
+     * are interned.
+     */
+    ctxt->dictNames = 0;
 
     ctxt->myDoc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
     if (ctxt->myDoc == NULL) {
@@ -364,6 +369,11 @@
                         "xmlNewTextWriterDoc : error at xmlCreatePushParserCtxt!\n");
         return NULL;
     }
+    /*
+     * For some reason this seems to completely break if node names
+     * are interned.
+     */
+    ctxt->dictNames = 0;
 
     ret = xmlNewTextWriterPushParser(ctxt, compression);
     if (ret == NULL) {