added a parser XML_PARSE_COMPACT option to allocate small text nodes (less

* HTMLparser.c parser.c SAX2.c debugXML.c tree.c valid.c xmlreader.c
  xmllint.c include/libxml/HTMLparser.h include/libxml/parser.h:
  added a parser XML_PARSE_COMPACT option to allocate small
  text nodes (less than 8 bytes on 32bits, less than 16bytes on 64bits)
  directly within the node, various changes to cope with this.
* result/XPath/tests/* result/XPath/xptr/* result/xmlid/*: this
  slightly change the output
Daniel
diff --git a/ChangeLog b/ChangeLog
index c928c97..a32e9f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu Aug 25 15:14:56 CEST 2005 Daniel Veillard <daniel@veillard.com>
+
+	* HTMLparser.c parser.c SAX2.c debugXML.c tree.c valid.c xmlreader.c
+	  xmllint.c include/libxml/HTMLparser.h include/libxml/parser.h:
+	  added a parser XML_PARSE_COMPACT option to allocate small 
+	  text nodes (less than 8 bytes on 32bits, less than 16bytes on 64bits)
+	  directly within the node, various changes to cope with this.
+	* result/XPath/tests/* result/XPath/xptr/* result/xmlid/*: this 
+	  slightly change the output
+
 Thu Aug 25 12:16:26 CEST 2005 Daniel Veillard <daniel@veillard.com>
 
 	* configure.in: patch from Andrew W. Nosenko, use se $GCC = 'yes'
diff --git a/HTMLparser.c b/HTMLparser.c
index fe36c89..6b8b562 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -5820,6 +5820,10 @@
         ctxt->recovery = 1;
     } else
         ctxt->recovery = 0;
+    if (options & HTML_PARSE_COMPACT) {
+	ctxt->options |= HTML_PARSE_COMPACT;
+        options -= HTML_PARSE_COMPACT;
+    }
     ctxt->dictNames = 0;
     return (options);
 }
diff --git a/SAX2.c b/SAX2.c
index 241e90d..a73fa1f 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -1777,6 +1777,7 @@
         xmlErrMemory(ctxt, "xmlSAX2Characters");
 	return(NULL);
     }
+    memset(ret, 0, sizeof(xmlNode));
     /*
      * intern the formatting blanks found between tags, or the
      * very short strings
@@ -1784,7 +1785,14 @@
     if (ctxt->dictNames) {
         xmlChar cur = str[len];
 
-	if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
+	if ((len < (int) (2 * sizeof(void *))) &&
+	    (ctxt->options & XML_PARSE_COMPACT)) {
+	    /* store the string in the node overrithing properties and nsDef */
+	    xmlChar *tmp = (xmlChar *) &(ret->properties);
+	    memcpy(tmp, str, len);
+	    tmp[len] = 0;
+	    intern = tmp;
+	} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
 	    ((cur == '<') && (str[len + 1] != '!')))) {
 	    intern = xmlDictLookup(ctxt->dict, str, len);
 	} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
@@ -1798,7 +1806,6 @@
 	}
     }
 skip:
-    memset(ret, 0, sizeof(xmlNode));
     ret->type = XML_TEXT_NODE;
 
     ret->name = xmlStringText;
@@ -2407,8 +2414,11 @@
 	     * We try to minimaze realloc() uses and avoid copying
 	     * and recomputing length over and over.
 	     */
-	    if ((ctxt->nodemem == ctxt->nodelen + 1) &&
-	        (xmlDictOwns(ctxt->dict, lastChild->content))) {
+	    if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
+		lastChild->content = xmlStrdup(lastChild->content);
+		lastChild->properties = NULL;
+	    } else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
+	               (xmlDictOwns(ctxt->dict, lastChild->content))) {
 		lastChild->content = xmlStrdup(lastChild->content);
 	    }
 	    if (ctxt->nodelen + len >= ctxt->nodemem) {
diff --git a/debugXML.c b/debugXML.c
index 3cb2848..24c7c4d 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -902,9 +902,15 @@
             if (!ctxt->check) {
                 xmlCtxtDumpSpaces(ctxt);
                 if (node->name == (const xmlChar *) xmlStringTextNoenc)
-                    fprintf(ctxt->output, "TEXT no enc\n");
+                    fprintf(ctxt->output, "TEXT no enc");
                 else
-                    fprintf(ctxt->output, "TEXT\n");
+                    fprintf(ctxt->output, "TEXT");
+		if (node->content == (xmlChar *) &(node->properties))
+		    fprintf(ctxt->output, " compact\n");
+		else if (xmlDictOwns(ctxt->dict, node->content) == 1)
+		    fprintf(ctxt->output, " interned\n");
+		else
+		    fprintf(ctxt->output, "\n");
             }
             break;
         case XML_CDATA_SECTION_NODE:
@@ -1005,9 +1011,9 @@
         fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
     }
     ctxt->depth++;
-    if (node->nsDef != NULL)
+    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
         xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
-    if (node->properties != NULL)
+    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
         xmlCtxtDumpAttrList(ctxt, node->properties);
     if (node->type != XML_ENTITY_REF_NODE) {
         if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h
index 2c1e8d2..8477efb 100644
--- a/include/libxml/HTMLparser.h
+++ b/include/libxml/HTMLparser.h
@@ -178,7 +178,8 @@
     HTML_PARSE_NOWARNING= 1<<6,	/* suppress warning reports */
     HTML_PARSE_PEDANTIC	= 1<<7,	/* pedantic error reporting */
     HTML_PARSE_NOBLANKS	= 1<<8,	/* remove blank nodes */
-    HTML_PARSE_NONET	= 1<<11 /* Forbid network access */
+    HTML_PARSE_NONET	= 1<<11,/* Forbid network access */
+    HTML_PARSE_COMPACT  = 1<<16 /* compact small text nodes */
 } htmlParserOption;
 
 XMLPUBFUN void XMLCALL
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 6e750e7..6d6ea37 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -1088,7 +1088,8 @@
     XML_PARSE_NODICT	= 1<<12,/* Do not reuse the context dictionnary */
     XML_PARSE_NSCLEAN	= 1<<13,/* remove redundant namespaces declarations */
     XML_PARSE_NOCDATA	= 1<<14,/* merge CDATA as text nodes */
-    XML_PARSE_NOXINCNODE= 1<<15 /* do not generate XINCLUDE START/END nodes */
+    XML_PARSE_NOXINCNODE= 1<<15,/* do not generate XINCLUDE START/END nodes */
+    XML_PARSE_COMPACT   = 1<<16 /* compact small text nodes */
 } xmlParserOption;
 
 XMLPUBFUN void XMLCALL
diff --git a/parser.c b/parser.c
index 44e6180..6a905a0 100644
--- a/parser.c
+++ b/parser.c
@@ -684,7 +684,7 @@
     }
 
     /*
-     * plit the element name into prefix:localname , the string found
+     * Split the element name into prefix:localname , the string found
      * are within the DTD and hen not associated to namespace names.
      */
     name = xmlSplitQName3(fullattr, &len);
@@ -11319,8 +11319,9 @@
 	*lst = cur;
 	while (cur != NULL) {
 #ifdef LIBXML_VALID_ENABLED
-	    if (oldctxt->validate && oldctxt->wellFormed &&
-		oldctxt->myDoc && oldctxt->myDoc->intSubset) {
+	    if ((oldctxt->validate) && (oldctxt->wellFormed) &&
+		(oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
+		(cur->type == XML_ELEMENT_NODE)) {
 		oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
 			oldctxt->myDoc, cur);
 	    }
@@ -12843,6 +12844,10 @@
 	ctxt->options |= XML_PARSE_NONET;
         options -= XML_PARSE_NONET;
     }
+    if (options & XML_PARSE_COMPACT) {
+	ctxt->options |= XML_PARSE_COMPACT;
+        options -= XML_PARSE_COMPACT;
+    }
     ctxt->linenumbers = 1;
     return (options);
 }
diff --git a/result/XPath/tests/chaptersbase b/result/XPath/tests/chaptersbase
index 03c6567..10636c3 100644
--- a/result/XPath/tests/chaptersbase
+++ b/result/XPath/tests/chaptersbase
@@ -72,10 +72,10 @@
 Expression: /child::EXAMPLE/child::head/node()
 Object is a Node Set :
 Set contains 3 nodes:
-1  TEXT
+1  TEXT compact
     content=    
 2  ELEMENT title
-3  TEXT
+3  TEXT compact
     content=   
 
 ========================
diff --git a/result/XPath/tests/idsimple b/result/XPath/tests/idsimple
index 891b52e..76d9286 100644
--- a/result/XPath/tests/idsimple
+++ b/result/XPath/tests/idsimple
@@ -5,7 +5,7 @@
 Set contains 1 nodes:
 1  ELEMENT EXAMPLE
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=root
     ATTRIBUTE prop1
       TEXT
diff --git a/result/XPath/tests/langsimple b/result/XPath/tests/langsimple
index d8d7afd..0254462 100644
--- a/result/XPath/tests/langsimple
+++ b/result/XPath/tests/langsimple
@@ -5,30 +5,30 @@
 Set contains 9 nodes:
 1  ELEMENT b
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=en
 2  ELEMENT x
 3  ELEMENT x
 4  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=en
 5  ELEMENT div
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=en
 6  ELEMENT para
 7  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=EN
 8  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=en-us
 9  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=EN-US
 
 ========================
@@ -37,11 +37,11 @@
 Set contains 2 nodes:
 1  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=en-us
 2  ELEMENT para
     ATTRIBUTE lang
-      TEXT
+      TEXT compact
         content=EN-US
 
 ========================
diff --git a/result/XPath/tests/mixedpat b/result/XPath/tests/mixedpat
index 3be0c49..f3d746a 100644
--- a/result/XPath/tests/mixedpat
+++ b/result/XPath/tests/mixedpat
@@ -5,7 +5,7 @@
 Set contains 1 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 
 ========================
@@ -14,11 +14,11 @@
 Set contains 2 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 
 ========================
@@ -27,11 +27,11 @@
 Set contains 2 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 
 ========================
@@ -40,11 +40,11 @@
 Set contains 2 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 
 ========================
@@ -53,15 +53,15 @@
 Set contains 3 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 3  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p2
 
 ========================
@@ -70,16 +70,16 @@
 Set contains 4 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT p1
 3  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 4  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p2
 
 ========================
@@ -88,14 +88,14 @@
 Set contains 4 nodes:
 1  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=root
 2  ELEMENT p1
 3  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p1
 4  ELEMENT s
     ATTRIBUTE p
-      TEXT
+      TEXT compact
         content=p2
diff --git a/result/XPath/tests/simpleabbr b/result/XPath/tests/simpleabbr
index 85da41a..6137812 100644
--- a/result/XPath/tests/simpleabbr
+++ b/result/XPath/tests/simpleabbr
@@ -45,7 +45,7 @@
 Set contains 2 nodes:
 1  TEXT
     content=bla bla bla ...
-2  TEXT
+2  TEXT compact
     content=...
 
 ========================
@@ -54,7 +54,7 @@
 Set contains 2 nodes:
 1  TEXT
     content=bla bla bla ...
-2  TEXT
+2  TEXT compact
     content=...
 
 ========================
@@ -63,7 +63,7 @@
 Set contains 2 nodes:
 1  TEXT
     content=bla bla bla ...
-2  TEXT
+2  TEXT compact
     content=...
 
 ========================
@@ -77,5 +77,5 @@
 Expression: (//p/text())[position()=last()]
 Object is a Node Set :
 Set contains 1 nodes:
-1  TEXT
+1  TEXT compact
     content=...
diff --git a/result/XPath/tests/simplebase b/result/XPath/tests/simplebase
index 38fa144..3ba1749 100644
--- a/result/XPath/tests/simplebase
+++ b/result/XPath/tests/simplebase
@@ -53,10 +53,10 @@
 Expression: /child::EXAMPLE/child::head/node()
 Object is a Node Set :
 Set contains 3 nodes:
-1  TEXT
+1  TEXT compact
     content=    
 2  ELEMENT title
-3  TEXT
+3  TEXT compact
     content=   
 
 ========================
diff --git a/result/XPath/tests/usr1check b/result/XPath/tests/usr1check
index 0308991..f284198 100644
--- a/result/XPath/tests/usr1check
+++ b/result/XPath/tests/usr1check
@@ -5,8 +5,8 @@
 Set contains 1 nodes:
 1  ELEMENT ITEM
     ATTRIBUTE monto
-      TEXT
+      TEXT compact
         content=50.12
     ATTRIBUTE divisa
-      TEXT
+      TEXT compact
         content=DOL
diff --git a/result/XPath/xptr/strrange b/result/XPath/xptr/strrange
index c14ed91..9c0096d 100644
--- a/result/XPath/xptr/strrange
+++ b/result/XPath/xptr/strrange
@@ -44,7 +44,7 @@
 Object is a Location Set:
 1 :   Object is a range :
   From index 3 in node
-    TEXT
+    TEXT compact
       content=a diff
   To index 4 in node
     TEXT
@@ -56,10 +56,10 @@
 Object is a Location Set:
 1 :   Object is a range :
   From index 3 in node
-    TEXT
+    TEXT compact
       content=a span
   To index 3 in node
-    TEXT
+    TEXT compact
       content=ing one
 
 
@@ -80,17 +80,17 @@
 Object is a Location Set:
 1 :   Object is a collapsed range :
   index 1 in node
-    TEXT
+    TEXT compact
       content=123
 2 :   Object is a collapsed range :
   index 2 in node
-    TEXT
+    TEXT compact
       content=123
 3 :   Object is a collapsed range :
   index 3 in node
-    TEXT
+    TEXT compact
       content=123
 4 :   Object is a collapsed range :
   index 4 in node
-    TEXT
+    TEXT compact
       content=123
diff --git a/result/XPath/xptr/strrange2 b/result/XPath/xptr/strrange2
index ea6ee45..fd6c0ea 100644
--- a/result/XPath/xptr/strrange2
+++ b/result/XPath/xptr/strrange2
@@ -60,5 +60,5 @@
 Object is a Location Set:
 1 :   Object is a collapsed range :
   index 3 in node
-    TEXT
+    TEXT compact
       content=a diff
diff --git a/result/xmlid/id_err2.xml b/result/xmlid/id_err2.xml
index 33ee896..c7956dc 100644
--- a/result/xmlid/id_err2.xml
+++ b/result/xmlid/id_err2.xml
@@ -2,5 +2,5 @@
 Set contains 1 nodes:
 1  ELEMENT foo
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=bar
diff --git a/result/xmlid/id_tst1.xml b/result/xmlid/id_tst1.xml
index 33ee896..c7956dc 100644
--- a/result/xmlid/id_tst1.xml
+++ b/result/xmlid/id_tst1.xml
@@ -2,5 +2,5 @@
 Set contains 1 nodes:
 1  ELEMENT foo
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=bar
diff --git a/result/xmlid/id_tst2.xml b/result/xmlid/id_tst2.xml
index 33ee896..c7956dc 100644
--- a/result/xmlid/id_tst2.xml
+++ b/result/xmlid/id_tst2.xml
@@ -2,5 +2,5 @@
 Set contains 1 nodes:
 1  ELEMENT foo
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=bar
diff --git a/result/xmlid/id_tst3.xml b/result/xmlid/id_tst3.xml
index e2f8228..bf020eb 100644
--- a/result/xmlid/id_tst3.xml
+++ b/result/xmlid/id_tst3.xml
@@ -2,5 +2,5 @@
 Set contains 1 nodes:
 1  ELEMENT o:o
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=bar
diff --git a/result/xmlid/id_tst4.xml b/result/xmlid/id_tst4.xml
index 33ee896..c7956dc 100644
--- a/result/xmlid/id_tst4.xml
+++ b/result/xmlid/id_tst4.xml
@@ -2,5 +2,5 @@
 Set contains 1 nodes:
 1  ELEMENT foo
     ATTRIBUTE id
-      TEXT
+      TEXT compact
         content=bar
diff --git a/runtest.c b/runtest.c
index d03322d..897cb9b 100644
--- a/runtest.c
+++ b/runtest.c
@@ -4306,7 +4306,7 @@
 		testErrorsSize = 0;
 		testErrors[0] = 0;
 		res = tst->func(globbuf.gl_pathv[i], result, error,
-		                tst->options);
+		                tst->options | XML_PARSE_COMPACT);
 		xmlResetLastError();
 		if (res != 0) {
 		    fprintf(stderr, "File %s generated an error\n",
diff --git a/testXPath.c b/testXPath.c
index 8086a81..677419a 100644
--- a/testXPath.c
+++ b/testXPath.c
@@ -178,9 +178,9 @@
     }
     if (document == NULL) {
         if (filename == NULL)
-	    document = xmlReadDoc(buffer,NULL,NULL,0);
+	    document = xmlReadDoc(buffer,NULL,NULL,XML_PARSE_COMPACT);
 	else
-	    document = xmlReadFile(filename,NULL,0);
+	    document = xmlReadFile(filename,NULL,XML_PARSE_COMPACT);
     }
     for (i = 1; i < argc ; i++) {
 	if ((!strcmp(argv[i], "-i")) || (!strcmp(argv[i], "--input"))) {
diff --git a/tree.c b/tree.c
index 3e5378f..1da8400 100644
--- a/tree.c
+++ b/tree.c
@@ -3287,7 +3287,8 @@
 	    if ((cur->type != XML_ELEMENT_NODE) &&
 		(cur->type != XML_XINCLUDE_START) &&
 		(cur->type != XML_XINCLUDE_END) &&
-		(cur->type != XML_ENTITY_REF_NODE)) {
+		(cur->type != XML_ENTITY_REF_NODE) &&
+		(cur->content != (xmlChar *) &(cur->properties))) {
 		DICT_FREE(cur->content)
 	    }
 	    if (((cur->type == XML_ELEMENT_NODE) ||
@@ -3356,7 +3357,8 @@
 	(cur->content != NULL) &&
 	(cur->type != XML_ENTITY_REF_NODE) &&
 	(cur->type != XML_XINCLUDE_END) &&
-	(cur->type != XML_XINCLUDE_START)) {
+	(cur->type != XML_XINCLUDE_START) &&
+	(cur->content != (xmlChar *) &(cur->properties))) {
 	DICT_FREE(cur->content)
     }
 
@@ -3811,7 +3813,7 @@
     
     if (!extended)
 	goto out;
-    if (node->nsDef != NULL)
+    if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
         ret->nsDef = xmlCopyNamespaceList(node->nsDef);
 
     if (node->ns != NULL) {
@@ -3838,7 +3840,7 @@
 	    ret->ns = ns;
 	}
     }
-    if (node->properties != NULL)
+    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
         ret->properties = xmlCopyPropList(ret, node->properties);
     if (node->type == XML_ENTITY_REF_NODE) {
 	if ((doc == NULL) || (node->doc != doc)) {
@@ -5106,7 +5108,8 @@
         case XML_ENTITY_NODE:
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
-	    if (cur->content != NULL) {
+	    if ((cur->content != NULL) &&
+	        (cur->content != (xmlChar *) &(cur->properties))) {
 	        if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
 		    (xmlDictOwns(cur->doc->dict, cur->content))))
 		    xmlFree(cur->content);
@@ -5117,6 +5120,8 @@
 		cur->content = xmlStrdup(content);
 	    } else 
 		cur->content = NULL;
+	    cur->properties = NULL;
+	    cur->nsDef = NULL;
 	    break;
         case XML_DOCUMENT_NODE:
         case XML_HTML_DOCUMENT_NODE:
@@ -5178,8 +5183,11 @@
         case XML_PI_NODE:
         case XML_COMMENT_NODE:
         case XML_NOTATION_NODE:
-	    if (cur->content != NULL) {
-		xmlFree(cur->content);
+	    if ((cur->content != NULL) &&
+	        (cur->content != (xmlChar *) &(cur->properties))) {
+	        if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
+		    (xmlDictOwns(cur->doc->dict, cur->content))))
+		    xmlFree(cur->content);
 	    }	
 	    if (cur->children != NULL) xmlFreeNodeList(cur->children);
 	    cur->children = cur->last = NULL;
@@ -5187,6 +5195,8 @@
 		cur->content = xmlStrndup(content, len);
 	    } else 
 		cur->content = NULL;
+	    cur->properties = NULL;
+	    cur->nsDef = NULL;
 	    break;
         case XML_DOCUMENT_NODE:
         case XML_DTD_NODE:
@@ -5257,10 +5267,12 @@
         case XML_COMMENT_NODE:
         case XML_NOTATION_NODE:
 	    if (content != NULL) {
-	        if ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
-			    xmlDictOwns(cur->doc->dict, cur->content)) {
-		    cur->content =
-			    xmlStrncatNew(cur->content, content, len);
+	        if ((cur->content == (xmlChar *) &(cur->properties)) ||
+		    ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
+			    xmlDictOwns(cur->doc->dict, cur->content))) {
+		    cur->content = xmlStrncatNew(cur->content, content, len);
+		    cur->properties = NULL;
+		    cur->nsDef = NULL;
 		    break;
 		}
 		cur->content = xmlStrncat(cur->content, content, len);
@@ -5903,7 +5915,8 @@
     xmlAttrPtr prop;
     xmlDocPtr doc;
 
-    if ((node == NULL) || (name == NULL)) return(NULL);
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
+        return(NULL);
     /*
      * Check on the properties attached to the node
      */
@@ -5959,7 +5972,7 @@
     xmlDocPtr doc;
 #endif /* LIBXML_TREE_ENABLED */
 
-    if (node == NULL)
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
 	return(NULL);
 
     prop = node->properties;
@@ -6057,7 +6070,9 @@
     xmlAttrPtr prop;
     xmlDocPtr doc;
 
-    if ((node == NULL) || (name == NULL)) return(NULL);
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
+        return(NULL);
+
     /*
      * Check on the properties attached to the node
      */
@@ -6114,7 +6129,8 @@
     xmlAttrPtr prop;
     xmlDocPtr doc;
 
-    if ((node == NULL) || (name == NULL)) return(NULL);
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
+	return(NULL);
     /*
      * Check on the properties attached to the node
      */
@@ -6172,7 +6188,7 @@
     xmlDocPtr doc;
     xmlNsPtr ns;
 
-    if (node == NULL)
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE))
 	return(NULL);
 
     prop = node->properties;
@@ -6236,7 +6252,7 @@
 xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
     xmlAttrPtr prop, prev = NULL;;
 
-    if ((node == NULL) || (name == NULL))
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
 	return(-1);
     prop = node->properties;
     while (prop != NULL) {
@@ -6265,7 +6281,7 @@
 xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
     xmlAttrPtr prop, prev = NULL;;
 
-    if ((node == NULL) || (name == NULL))
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
 	return(-1);
     prop = node->properties;
     if (ns == NULL)
@@ -6471,12 +6487,14 @@
         return(-1);
     }
     /* need to check if content is currently in the dictionary */
-    if ((node->doc != NULL) && (node->doc->dict != NULL) &&
-		xmlDictOwns(node->doc->dict, node->content)) {
+    if ((node->content == (xmlChar *) &(node->properties)) ||
+        ((node->doc != NULL) && (node->doc->dict != NULL) &&
+		xmlDictOwns(node->doc->dict, node->content))) {
 	node->content = xmlStrncatNew(node->content, content, len);
     } else {
         node->content = xmlStrncat(node->content, content, len);
     }
+    node->properties = NULL;
     if (node->content == NULL)
         return(-1);
     return(0);
diff --git a/valid.c b/valid.c
index 35c21ae..c0141ff 100644
--- a/valid.c
+++ b/valid.c
@@ -5860,24 +5860,12 @@
 				NULL,NULL,NULL);
 		return(0);
 	    }
-	    if (elem->properties != NULL) {
-		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		                "Text element has attribute !\n",
-				NULL,NULL,NULL);
-		return(0);
-	    }
 	    if (elem->ns != NULL) {
 		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
 		                "Text element has namespace !\n",
 				NULL,NULL,NULL);
 		return(0);
 	    }
-	    if (elem->nsDef != NULL) {
-		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
-		                "Text element has namespace !\n",
-				NULL,NULL,NULL);
-		return(0);
-	    }
 	    if (elem->content == NULL) {
 		xmlErrValidNode(ctxt, elem, XML_ERR_INTERNAL_ERROR,
 		                "Text element has no content !\n",
@@ -6302,23 +6290,25 @@
     }
 
     ret &= xmlValidateOneElement(ctxt, doc, elem);
-    attr = elem->properties;
-    while (attr != NULL) {
-        value = xmlNodeListGetString(doc, attr->children, 0);
-	ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
-	if (value != NULL)
-	    xmlFree((char *)value);
-	attr= attr->next;
-    }
-    ns = elem->nsDef;
-    while (ns != NULL) {
-        if (elem->ns == NULL)
-	    ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
-					   ns, ns->href);
-	else
-	    ret &= xmlValidateOneNamespace(ctxt, doc, elem, elem->ns->prefix,
-					   ns, ns->href);
-        ns = ns->next;
+    if (elem->type == XML_ELEMENT_NODE) {
+	attr = elem->properties;
+	while (attr != NULL) {
+	    value = xmlNodeListGetString(doc, attr->children, 0);
+	    ret &= xmlValidateOneAttribute(ctxt, doc, elem, attr, value);
+	    if (value != NULL)
+		xmlFree((char *)value);
+	    attr= attr->next;
+	}
+	ns = elem->nsDef;
+	while (ns != NULL) {
+	    if (elem->ns == NULL)
+		ret &= xmlValidateOneNamespace(ctxt, doc, elem, NULL,
+					       ns, ns->href);
+	    else
+		ret &= xmlValidateOneNamespace(ctxt, doc, elem,
+		                               elem->ns->prefix, ns, ns->href);
+	    ns = ns->next;
+	}
     }
     child = elem->children;
     while (child != NULL) {
diff --git a/xmllint.c b/xmllint.c
index 65e17b3..607cea3 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -196,7 +196,7 @@
 static xmlPatternPtr patternc = NULL;
 static xmlStreamCtxtPtr patstream = NULL;
 #endif
-static int options = 0;
+static int options = XML_PARSE_COMPACT;
 static int sax = 0;
 
 /************************************************************************
@@ -2793,6 +2793,7 @@
     printf("\t--path 'paths': provide a set of paths for resources\n");
     printf("\t--load-trace : print trace of all external entites loaded\n");
     printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
+    printf("\t--nocompact : do not generate compact text nodes\n");
     printf("\t--htmlout : output results as HTML\n");
     printf("\t--nowrap : do not put HTML doc wrapper\n");
 #ifdef LIBXML_VALID_ENABLED
@@ -3175,6 +3176,9 @@
         } else if ((!strcmp(argv[i], "-nonet")) ||
                    (!strcmp(argv[i], "--nonet"))) {
 	    options |= XML_PARSE_NONET;
+        } else if ((!strcmp(argv[i], "-nocompact")) ||
+                   (!strcmp(argv[i], "--nocompact"))) {
+	    options &= ~XML_PARSE_COMPACT;
 	} else if ((!strcmp(argv[i], "-load-trace")) ||
 	           (!strcmp(argv[i], "--load-trace"))) {
 	    load_trace++;
diff --git a/xmlreader.c b/xmlreader.c
index 5fdf3a5..7efa273 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -348,7 +348,8 @@
 		 (cur->type == XML_XINCLUDE_END)) &&
 		(cur->properties != NULL))
 		xmlTextReaderFreePropList(reader, cur->properties);
-	    if ((cur->type != XML_ELEMENT_NODE) &&
+	    if ((cur->content != (xmlChar *) &(cur->properties)) &&
+	        (cur->type != XML_ELEMENT_NODE) &&
 		(cur->type != XML_XINCLUDE_START) &&
 		(cur->type != XML_XINCLUDE_END) &&
 		(cur->type != XML_ENTITY_REF_NODE)) {
@@ -422,7 +423,8 @@
 	 (cur->type == XML_XINCLUDE_END)) &&
 	(cur->properties != NULL))
 	xmlTextReaderFreePropList(reader, cur->properties);
-    if ((cur->type != XML_ELEMENT_NODE) &&
+    if ((cur->content != (xmlChar *) &(cur->properties)) &&
+        (cur->type != XML_ELEMENT_NODE) &&
 	(cur->type != XML_XINCLUDE_START) &&
 	(cur->type != XML_XINCLUDE_END) &&
 	(cur->type != XML_ENTITY_REF_NODE)) {
@@ -2810,7 +2812,9 @@
 	    reader->faketext = xmlNewDocText(reader->node->doc, 
 		                             ns->href);
 	} else {
-            if (reader->faketext->content != NULL)
+            if ((reader->faketext->content != NULL) &&
+	        (reader->faketext->content !=
+		 (xmlChar *) &(reader->faketext->properties)))
 		xmlFree(reader->faketext->content);
 	    reader->faketext->content = xmlStrdup(ns->href);
 	}
@@ -4776,6 +4780,12 @@
     if (reader == NULL)
         return (-1);
 
+    /*
+     * we force the generation of compact text nodes on the reader
+     * since usr applications should never modify the tree
+     */
+    options |= XML_PARSE_COMPACT;
+
     reader->doc = NULL;
     reader->entNr = 0;
     reader->parserFlags = options;