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;