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, 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 name = do_GetAtom(tmp); + + // combine the nameSpaceID and localName into a node (i.e., a name) + nsCOMPtr 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 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 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: + // 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; imStackPos; i++) { NS_IF_RELEASE(mCurrentContext->mStack[i].mContent); + NS_IF_RELEASE(mCurrentContext->mStack[i].xContent); } delete [] mCurrentContext->mStack;