Index: content/html/document/src/nsHTMLContentSink.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/html/document/src/nsHTMLContentSink.cpp,v
retrieving revision 3.774
diff -u -r3.774 nsHTMLContentSink.cpp
--- content/html/document/src/nsHTMLContentSink.cpp	28 Nov 2006 03:17:02 -0000	3.774
+++ content/html/document/src/nsHTMLContentSink.cpp	18 Dec 2006 04:55:46 -0000
@@ -453,6 +453,9 @@
 
   // Measures content model creation time for current document
   MOZ_TIMER_DECLARE(mWatch)
+
+  // Enable xmlns?
+  PRBool mXHTMLMode;
 };
 
 
@@ -614,6 +617,12 @@
   struct Node {
     nsHTMLTag mType;
     nsGenericHTMLElement* mContent;
+    // In the long run, it would be better if methods like CreateHTMLElement
+    // would return already_AddRefed<nsGenericHTMLElement>, but for 
+    // proof-of-concept purposes, XML subtrees will be built in parallel
+    // on the same stack, and at the last possible moment will be grafted
+    // into the tree in place of the UnknownHTML equivalent.
+    nsIContent* xContent;
     PRUint32 mNumFlushed;
     PRInt32 mInsertionPoint;
   };
@@ -879,6 +888,7 @@
   if (mStack) {
     for (PRInt32 i = 0; i < mStackPos; i++) {
       NS_RELEASE(mStack[i].mContent);
+      NS_IF_RELEASE(mStack[i].xContent);
     }
     delete [] mStack;
   }
@@ -901,6 +911,7 @@
 
   mStack[0].mType = aNodeType;
   mStack[0].mContent = aRoot;
+  mStack[0].xContent = nsnull;
   mStack[0].mNumFlushed = aNumFlushed;
   mStack[0].mInsertionPoint = aInsertionPoint;
   NS_ADDREF(aRoot);
@@ -1014,6 +1025,7 @@
 
   mStack[mStackPos].mType = nodeType;
   mStack[mStackPos].mContent = content;
+  mStack[mStackPos].xContent = nsnull;
   mStack[mStackPos].mNumFlushed = 0;
   mStack[mStackPos].mInsertionPoint = -1;
   ++mStackPos;
@@ -1073,14 +1085,68 @@
   rv = mSink->AddAttributes(aNode, content);
   MaybeSetForm(content, nodeType, mSink);
 
-  nsGenericHTMLElement* parent = mStack[mStackPos - 2].mContent;
+  nsIContent* parent = mStack[mStackPos - 2].mContent;
+  nsIContent* child = content;
 
-  if (mStack[mStackPos - 2].mInsertionPoint != -1) {
-    parent->InsertChildAt(content,
-                          mStack[mStackPos - 2].mInsertionPoint++,
-                          PR_FALSE);
-  } else {
-    parent->AppendChildTo(content, PR_FALSE);
+  if (mSink->mXHTMLMode) {
+    nsAutoString attrValue;
+    if (content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::xmlns, attrValue)) {
+
+      // map xmlns to a nameSpaceID
+      PRInt32 nameSpaceID =
+        nsContentUtils::NameSpaceManager()->GetNameSpaceID(attrValue);
+
+      // retrieve original localName (preserving case)
+      NS_ConvertUTF16toUTF8 tmp(aNode.GetText());
+      nsCOMPtr<nsIAtom> name = do_GetAtom(tmp);
+
+      // combine the nameSpaceID and localName into a node (i.e., a name)
+      nsCOMPtr<nsINodeInfo> xNodeInfo;
+      rv = mSink->mNodeInfoManager->GetNodeInfo(name, nsnull, nameSpaceID,
+                                                getter_AddRefs(xNodeInfo));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // create a "element" with the nameSpaceID and localName
+      nsCOMPtr<nsIContent> xContent;
+      rv = NS_NewElement(getter_AddRefs(xContent), nameSpaceID,
+                         xNodeInfo.get());
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // copy the attributes from the original parse aNode (preserving case)
+      PRInt32 ac = aNode.GetAttributeCount();
+      nsCAutoString k;
+      for (PRInt32 i=ac; --i >= 0;) {
+        const nsAString& key = aNode.GetKeyAt(i);
+        CopyUTF16toUTF8(key, k);
+        nsCOMPtr<nsIAtom> keyAtom = do_GetAtom(k);
+
+        const nsAString& v = aNode.GetValueAt(i);
+        xContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
+      }
+
+      // put the XML node on the stack
+      mStack[mStackPos - 1].xContent = xContent;
+
+      if (mStack[mStackPos - 2].xContent) {
+        // parent is XML: append child element
+        mStack[mStackPos - 2].xContent->AppendChildTo(xContent, PR_FALSE);
+      } else {
+        // parent is HTML: append child element and drop HTML child
+        parent->AppendChildTo(xContent, PR_FALSE);
+        child = nsnull;
+      }
+    }
+  }
+
+  // append HTML child to HTML parent
+  if (child) {
+    if (mStack[mStackPos - 2].mInsertionPoint != -1) {
+      parent->InsertChildAt(child,
+                            mStack[mStackPos - 2].mInsertionPoint++,
+                            PR_FALSE);
+    } else {
+      parent->AppendChildTo(child, PR_FALSE);
+    }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1350,6 +1416,21 @@
         if (!mSink->mInsideNoXXXTag && !mSink->mFrameset) {
           rv = mSink->ProcessMETATag(content);
         }
+
+        {
+          // turn on XHTML/xmlns mode if the following is encountered:
+          // <meta http-equiv="Content-Type" content="application/xhtml>
+          nsAutoString attrValue;
+          if (NS_SUCCEEDED(content->GetAttribute(
+                           NS_LITERAL_STRING("http-equiv"), attrValue)) &&
+              FindInReadable(NS_LITERAL_STRING("content-type"), attrValue,
+                             nsCaseInsensitiveStringComparator()) &&
+              content->GetAttr(kNameSpaceID_None, nsHTMLAtoms::content,
+                               attrValue) &&
+              FindInReadable(NS_LITERAL_STRING("xhtml"),attrValue)) {
+            mSink->mXHTMLMode = PR_TRUE;
+          }
+        }
         break;
 
       case eHTMLTag_input:
@@ -1483,6 +1564,7 @@
 {
   for (PRInt32 i = 0; i < mStackPos; i++) {
     NS_RELEASE(mStack[i].mContent);
+    NS_IF_RELEASE(mStack[i].xContent);
   }
 
   mStackPos = 0;
@@ -1780,7 +1862,6 @@
 {
   // Note: operator new zeros our memory
 
-
 #ifdef NS_DEBUG
   if (!gSinkLogModuleInfo) {
     gSinkLogModuleInfo = PR_NewLogModule("htmlcontentsink");
@@ -2408,6 +2489,7 @@
 
   for (PRInt32 i = 0; i<mCurrentContext->mStackPos; i++) {
     NS_IF_RELEASE(mCurrentContext->mStack[i].mContent);
+    NS_IF_RELEASE(mCurrentContext->mStack[i].xContent);
   }
 
   delete [] mCurrentContext->mStack;
