Bug 422403 - improvements to the XML and XHTML serializers, r=smaug, sr=sicking
authorlaurent@xulfr.org
Sat, 25 Apr 2009 12:00:14 +0300
changeset 27852 f6d27eb05ec1
parent 27851 dfff608ebad0
child 27853 ac4d8886164c
push id6740
push useropettay@mozilla.com
push date2009-04-25 11:18 +0000
treeherdermozilla-central@f6d27eb05ec1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, sicking
bugs422403
milestone1.9.2a1pre
Bug 422403 - improvements to the XML and XHTML serializers, r=smaug, sr=sicking
content/base/public/nsContentCID.h
content/base/public/nsIDocumentEncoder.idl
content/base/src/Makefile.in
content/base/src/nsContentAreaDragDrop.cpp
content/base/src/nsHTMLContentSerializer.cpp
content/base/src/nsHTMLContentSerializer.h
content/base/src/nsXHTMLContentSerializer.cpp
content/base/src/nsXHTMLContentSerializer.h
content/base/src/nsXMLContentSerializer.cpp
content/base/src/nsXMLContentSerializer.h
content/base/test/Makefile.in
content/base/test/file_htmlserializer_1.html
content/base/test/file_htmlserializer_1_bodyonly.html
content/base/test/file_htmlserializer_1_format.html
content/base/test/file_htmlserializer_1_linebreak.html
content/base/test/file_htmlserializer_1_links.html
content/base/test/file_htmlserializer_1_nested_body.html
content/base/test/file_htmlserializer_1_noflag.html
content/base/test/file_htmlserializer_1_noformatpre.html
content/base/test/file_htmlserializer_1_raw.html
content/base/test/file_htmlserializer_1_sibling_body.html
content/base/test/file_htmlserializer_1_sibling_body_only_body.html
content/base/test/file_htmlserializer_2_basic.html
content/base/test/file_htmlserializer_2_enthtml.html
content/base/test/file_htmlserializer_2_entw3c.html
content/base/test/file_htmlserializer_2_latin1.html
content/base/test/file_xhtmlserializer_1.xhtml
content/base/test/file_xhtmlserializer_1_bodyonly.xhtml
content/base/test/file_xhtmlserializer_1_format.xhtml
content/base/test/file_xhtmlserializer_1_linebreak.xhtml
content/base/test/file_xhtmlserializer_1_links.xhtml
content/base/test/file_xhtmlserializer_1_nested_body.xhtml
content/base/test/file_xhtmlserializer_1_no_body.xhtml
content/base/test/file_xhtmlserializer_1_noflag.xhtml
content/base/test/file_xhtmlserializer_1_noformatpre.xhtml
content/base/test/file_xhtmlserializer_1_raw.xhtml
content/base/test/file_xhtmlserializer_1_sibling_body.xhtml
content/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml
content/base/test/file_xhtmlserializer_2.xhtml
content/base/test/file_xhtmlserializer_2_basic.xhtml
content/base/test/file_xhtmlserializer_2_enthtml.xhtml
content/base/test/file_xhtmlserializer_2_entw3c.xhtml
content/base/test/file_xhtmlserializer_2_latin1.xhtml
content/base/test/test_bug270145.xhtml
content/base/test/test_bug422403-1.html
content/base/test/test_bug422403-2.xhtml
content/base/test/test_bug424359-1.html
content/base/test/test_bug424359-2.html
content/base/test/test_htmlcopyencoder.html
content/base/test/test_htmlcopyencoder.xhtml
content/base/test/unit/2_original.xml
content/base/test/unit/2_result_1.xml
content/base/test/unit/2_result_2.xml
content/base/test/unit/2_result_3.xml
content/base/test/unit/2_result_4.xml
content/base/test/unit/3_original.xml
content/base/test/unit/3_result.xml
content/base/test/unit/3_result_2.xml
content/base/test/unit/4_original.xml
content/base/test/unit/4_result_1.xml
content/base/test/unit/4_result_2.xml
content/base/test/unit/4_result_3.xml
content/base/test/unit/4_result_4.xml
content/base/test/unit/4_result_5.xml
content/base/test/unit/4_result_6.xml
content/base/test/unit/test_xmlserializer.js
embedding/test/test_bug293834.html
layout/build/nsLayoutCID.h
layout/build/nsLayoutModule.cpp
--- a/content/base/public/nsContentCID.h
+++ b/content/base/public/nsContentCID.h
@@ -190,16 +190,20 @@
 // {ECEA1B28-AE54-4047-8BBE-C624235106B4}
 #define NS_COMPUTEDDOMSTYLE_CID \
 { 0xecea1b28, 0xae54, 0x4047, { 0x8b, 0xbe, 0xc6, 0x24, 0x23, 0x51, 0x06, 0xb4 } }
 
 // {4aef38b7-6364-4e23-a5e7-12f837fbbd9c}
 #define NS_XMLCONTENTSERIALIZER_CID \
 { 0x4aef38b7, 0x6364, 0x4e23, { 0xa5, 0xe7, 0x12, 0xf8, 0x37, 0xfb, 0xbd, 0x9c } }
 
+// {e7c2aaf5-c11a-4954-9dbf-e28edec1fd91}
+#define NS_XHTMLCONTENTSERIALIZER_CID \
+{ 0xe7c2aaf5, 0xc11a, 0x4954, { 0x9d, 0xbf, 0xe2, 0x8e, 0xde, 0xc1, 0xfd, 0x91 } }
+
 // {9d3f70da-86e9-11d4-95ec-00b0d03e37b7}
 #define NS_HTMLCONTENTSERIALIZER_CID \
 { 0x9d3f70da, 0x86e9, 0x11d4, { 0x95, 0xec, 0x00, 0xb0, 0xd0, 0x3e, 0x37, 0xb7 } }
 
 // {feca3c34-205e-4ae5-bd1c-03c686ff012b}
 #define MOZ_SANITIZINGHTMLSERIALIZER_CID \
 { 0xfeca3c34, 0x205e, 0x4ae5, { 0xbd, 0x1c, 0x03, 0xc6, 0x86, 0xff, 0x01, 0x2b  } }
 
--- a/content/base/public/nsIDocumentEncoder.idl
+++ b/content/base/public/nsIDocumentEncoder.idl
@@ -70,76 +70,79 @@ interface nsIDocumentEncoder : nsISuppor
 
   /** 
    * Output only the selection (as opposed to the whole document).
    */
   const unsigned long OutputSelectionOnly = (1 << 0);
 
   /** Plaintext output: Convert html to plaintext that looks like the html.
     * Implies wrap (except inside <pre>), since html wraps.
-    * HTML output: always do prettyprinting, ignoring existing formatting.
-    * (Probably not well tested for HTML output.)
-    * XML output: unsupported
+    * HTML, XHTML and XML output: do prettyprinting, ignoring existing formatting.
+    * XML output : it doesn't implicitly wrap
     */
   const unsigned long OutputFormatted     = (1 << 1);
 
-  /** Don't do prettyprinting of HTML.  Don't do any wrapping that's not in
-   * the existing HTML source.  This option overrides OutputFormatted if both
-   * are set.
-   * Plaintext and HTML output only.
+  /** Don't do prettyprinting. Don't do any wrapping that's not in the existing
+   * HTML/XML source. This option overrides OutputFormatted if both are set.
+   * HTML/XHTML output: If neither are set, there won't be prettyprinting too, but
+   * long lines will be wrapped.
+   * Supported also in XML and Plaintext output.
    * @note This option does not affect entity conversion.
    */
   const unsigned long OutputRaw           = (1 << 2);
 
   /** 
    * Do not print html head tags.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputBodyOnly      = (1 << 3);
 
   /**
-   * Wrap even if we're not doing formatted output (e.g. for text fields).
-   * Plaintext output only.
-   * XXXbz How does this interact with
-   * OutputFormatted/OutputRaw/OutputWrap/OutputFormatFlowed?
-   */
-  const unsigned long OutputPreformatted  = (1 << 4);
-
-  /**
    * Output as though the content is preformatted
    * (e.g. maybe it's wrapped in a PRE or PRE_WRAP style tag)
    * Plaintext output only.
    * XXXbz How does this interact with
    * OutputFormatted/OutputRaw/OutputPreformatted/OutputFormatFlowed?
    */
+  const unsigned long OutputPreformatted  = (1 << 4);
+
+  /**
+   * Wrap even if we're not doing formatted output (e.g. for text fields).
+   * Supported in XML, XHTML, HTML and Plaintext output.
+   * Set implicitly in HTML/XHTML output when no OutputRaw.
+   * Ignored when OutputRaw.
+   * XXXLJ: set implicitly in HTML/XHTML output, to keep compatible behaviors
+   *        for old callers of this interface
+   * XXXbz How does this interact with OutputFormatFlowed?
+   */
   const unsigned long OutputWrap          = (1 << 5);
 
   /**
    * Output for format flowed (RFC 2646). This is used when converting
    * to text for mail sending. This differs just slightly
    * but in an important way from normal formatted, and that is that
    * lines are space stuffed. This can't (correctly) be done later.
    * PlainText output only.
    * XXXbz How does this interact with
    * OutputFormatted/OutputRaw/OutputPreformatted/OutputWrap?
    */
   const unsigned long OutputFormatFlowed  = (1 << 6);
 
   /**
    * Convert links, image src, and script src to absolute URLs when possible.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputAbsoluteLinks = (1 << 7);
 
   /**
    * Attempt to encode entities standardized at W3C (HTML, MathML, etc).
    * This is a catch-all flag for documents with mixed contents. Beware of
    * interoperability issues. See below for other flags which might likely
    * do what you want.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputEncodeW3CEntities = (1 << 8);
 
   /** 
    * LineBreak processing: if this flag is set than CR line breaks will
    * be written. If neither this nor OutputLFLineBreak is set, then we
    * will use platform line breaks. The combination of the two flags will
    * cause CRLF line breaks to be written.
@@ -163,42 +166,42 @@ interface nsIDocumentEncoder : nsISuppor
   /**
    * Output the content of noframes elements (only for serializing
    * to plaintext).
    */
   const unsigned long OutputNoFramesContent = (1 << 12);
 
   /**
    * Don't allow any formatting nodes (e.g. <br>, <b>) inside a <pre>.
-   * This is used primarily by mail. HTML output only.
+   * This is used primarily by mail. XHTML/HTML output only.
    */
   const unsigned long OutputNoFormattingInPre = (1 << 13);
 
   /**
    * Encode entities when outputting to a string.
    * E.g. If set, we'll output &nbsp; if clear, we'll output 0xa0.
    * The basic set is just &nbsp; &amp; &lt; &gt; &quot; for interoperability
    * with older products that don't support &alpha; and friends.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputEncodeBasicEntities = (1 << 14);
     
   /**
    * Encode entities when outputting to a string.
    * The Latin1 entity set additionally includes 8bit accented letters
    * between 128 and 255.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputEncodeLatin1Entities = (1 << 15);
   
   /**
    * Encode entities when outputting to a string.
    * The HTML entity set additionally includes accented letters, greek
    * letters, and other special markup symbols as defined in HTML4.
-   * HTML output only.
+   * XHTML/HTML output only.
    */
   const unsigned long OutputEncodeHTMLEntities = (1 << 16);
 
   /**
    * Normally &nbsp; is replaced with a space character when
    * encoding data as plain text, set this flag if that's
    * not desired.
    * Plaintext output only.
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -163,16 +163,17 @@ CPPSRCS		= \
 		nsStubMutationObserver.cpp \
 		nsStyledElement.cpp \
 		nsStyleLinkElement.cpp \
 		nsSyncLoadService.cpp \
 		nsTextFragment.cpp \
 		nsTextNode.cpp \
 		nsTraversal.cpp \
 		nsTreeWalker.cpp \
+		nsXHTMLContentSerializer.cpp \
 		nsXMLContentSerializer.cpp \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
 		$(NULL)
 
 GQI_SRCS = contentbase.gqi
 
 # we don't want the shared lib, but we want to force the creation of a
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -1415,17 +1415,18 @@ nsTransferableFactory::SerializeNodeOrSe
     do_CreateInstance(NS_HTMLCOPY_ENCODER_CONTRACTID);
   NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   inWindow->GetDocument(getter_AddRefs(domDoc));
   NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
 
   PRUint32 flags = nsIDocumentEncoder::OutputAbsoluteLinks |
-                   nsIDocumentEncoder::OutputEncodeHTMLEntities;
+                   nsIDocumentEncoder::OutputEncodeHTMLEntities |
+                   nsIDocumentEncoder::OutputRaw;
   nsCOMPtr<nsIDOMRange> range;
   nsCOMPtr<nsISelection> selection;
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(inNode);
   if (node) {
     // make a range around this node
     rv = NS_NewRange(getter_AddRefs(range));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = range->SelectNode(node);
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -63,448 +63,53 @@
 #include "nsEscape.h"
 #include "nsITextToSubURI.h"
 #include "nsCRT.h"
 #include "nsIParserService.h"
 #include "nsContentUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsIScriptElement.h"
 #include "nsAttrName.h"
-#include "nsILineBreaker.h"
-
-#define kIndentStr NS_LITERAL_STRING("  ")
-#define kLessThan NS_LITERAL_STRING("<")
-#define kGreaterThan NS_LITERAL_STRING(">")
-#define kEndTag NS_LITERAL_STRING("</")
 
 static const char kMozStr[] = "moz";
 
 static const PRInt32 kLongLineLen = 128;
 
 nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsHTMLContentSerializer* it = new nsHTMLContentSerializer();
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return CallQueryInterface(it, aSerializer);
 }
 
 nsHTMLContentSerializer::nsHTMLContentSerializer()
-: mIndent(0),
-  mInBody(0),
-  mAddSpace(PR_FALSE),
-  mMayIgnoreLineBreakSequence(PR_FALSE),
-  mIsWholeDocument(PR_FALSE),
-  mInCDATA(PR_FALSE)
 {
+    mIsHTMLSerializer = PR_TRUE;
 }
 
 nsHTMLContentSerializer::~nsHTMLContentSerializer()
 {
-  NS_ASSERTION(mOLStateStack.IsEmpty(), "Expected OL State stack to be empty");
-}
-
-NS_IMETHODIMP 
-nsHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
-                              const char* aCharSet, PRBool aIsCopying,
-                              PRBool aIsWholeDocument)
-{
-  nsresult rv;
-  rv = nsXMLContentSerializer::Init(aFlags, aWrapColumn, aCharSet, aIsCopying, aIsWholeDocument);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!aWrapColumn) {
-    mMaxColumn = 72;
-  }
-  else {
-    mMaxColumn = aWrapColumn;
-  }
-
-  mIsWholeDocument = aIsWholeDocument;
-  mIsCopying = aIsCopying;
-  mIsFirstChildOfOL = PR_FALSE;
-  mDoFormat = (mFlags & nsIDocumentEncoder::OutputFormatted) ? PR_TRUE
-                                                             : PR_FALSE;
-  mBodyOnly = (mFlags & nsIDocumentEncoder::OutputBodyOnly) ? PR_TRUE
-                                                            : PR_FALSE;
-
-  mPreLevel = 0;
-
-  // set up entity converter if we are going to need it
-  if (mFlags & nsIDocumentEncoder::OutputEncodeW3CEntities) {
-    mEntityConverter = do_CreateInstance(NS_ENTITYCONVERTER_CONTRACTID);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP 
-nsHTMLContentSerializer::AppendText(nsIDOMText* aText, 
-                                    PRInt32 aStartOffset,
-                                    PRInt32 aEndOffset,
-                                    nsAString& aStr)
-{
-  NS_ENSURE_ARG(aText);
-
-  nsAutoString data;
-
-  nsresult rv;
-  rv = AppendTextData((nsIDOMNode*)aText, aStartOffset, 
-                      aEndOffset, data, PR_TRUE, PR_FALSE);
-  if (NS_FAILED(rv))
-    return NS_ERROR_FAILURE;
-
-  if (mPreLevel > 0) {
-    AppendToStringConvertLF(data, aStr);
-  }
-  else if (mFlags & nsIDocumentEncoder::OutputRaw) {
-    PRInt32 lastNewlineOffset = data.RFindChar('\n');
-    AppendToString(data, aStr);
-    if (lastNewlineOffset != kNotFound)
-      mColPos = data.Length() - lastNewlineOffset;
-  }
-  else if (!mDoFormat) {
-    PRInt32 lastNewlineOffset = kNotFound;
-    PRBool hasLongLines = HasLongLines(data, lastNewlineOffset);
-    if (hasLongLines) {
-      // We have long lines, rewrap
-      AppendToStringWrapped(data, aStr, PR_FALSE);
-      if (lastNewlineOffset != kNotFound)
-        mColPos = data.Length() - lastNewlineOffset;
-    }
-    else {
-      AppendToStringConvertLF(data, aStr);
-    }
-  }
-  else {
-    AppendToStringWrapped(data, aStr, PR_FALSE);
-  }
-
-  return NS_OK;
 }
 
-void nsHTMLContentSerializer::AppendWrapped_WhitespaceSequence(
-                               nsASingleFragmentString::const_char_iterator &aPos,
-                               const nsASingleFragmentString::const_char_iterator aEnd,
-                               const nsASingleFragmentString::const_char_iterator aSequenceStart,
-                               PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
-                               nsAString &aOutputStr)
-{
-  // Handle the complete sequence of whitespace.
-  // Continue to iterate until we find the first non-whitespace char.
-  // Updates "aPos" to point to the first unhandled char.
-  // Also updates the aMayIgnoreStartOfLineWhitespaceSequence flag,
-  // as well as the other "global" state flags.
-
-  PRBool sawBlankOrTab = PR_FALSE;
-  PRBool leaveLoop = PR_FALSE;
-
-  do {
-    switch (*aPos) {
-      case ' ':
-      case '\t':
-        sawBlankOrTab = PR_TRUE;
-        // no break
-      case '\n':
-        ++aPos;
-        // do not increase mColPos,
-        // because we will reduce the whitespace to a single char
-        break;
-      default:
-        leaveLoop = PR_TRUE;
-        break;
-    }
-  } while (!leaveLoop && aPos < aEnd);
-
-  if (mAddSpace) {
-    // if we had previously been asked to add space,
-    // our situation has not changed
-  }
-  else if (!sawBlankOrTab && mMayIgnoreLineBreakSequence) {
-    // nothing to do
-    mMayIgnoreLineBreakSequence = PR_FALSE;
-  }
-  else if (aMayIgnoreStartOfLineWhitespaceSequence) {
-    // nothing to do
-    aMayIgnoreStartOfLineWhitespaceSequence = PR_FALSE;
-  }
-  else {
-    if (sawBlankOrTab) {
-      if (mColPos + 1 >= mMaxColumn) {
-        // no much sense in delaying, we only have one slot left,
-        // let's write a break now
-        aOutputStr.Append(mLineBreak);
-        mColPos = 0;
-      }
-      else {
-        // do not write out yet, we may write out either a space or a linebreak
-        // let's delay writing it out until we know more
-
-        mAddSpace = PR_TRUE;
-        ++mColPos; // eat a slot of available space
-      }
-    }
-    else {
-      // Asian text usually does not contain spaces, therefore we should not
-      // transform a linebreak into a space.
-      // Since we only saw linebreaks, but no spaces or tabs,
-      // let's write a linebreak now.
-      aOutputStr.Append(mLineBreak);
-      mMayIgnoreLineBreakSequence = PR_TRUE;
-      mColPos = 0;
-    }
-  }
-}
-
-void nsHTMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
-                               nsASingleFragmentString::const_char_iterator &aPos,
-                               const nsASingleFragmentString::const_char_iterator aEnd,
-                               const nsASingleFragmentString::const_char_iterator aSequenceStart,
-                               PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
-                               nsAString& aOutputStr)
-{
-  mMayIgnoreLineBreakSequence = PR_FALSE;
-  aMayIgnoreStartOfLineWhitespaceSequence = PR_FALSE;
-
-  // Handle the complete sequence of non-whitespace in this block
-  // Iterate until we find the first whitespace char or an aEnd condition
-  // Updates "aPos" to point to the first unhandled char.
-  // Also updates the aMayIgnoreStartOfLineWhitespaceSequence flag,
-  // as well as the other "global" state flags.
-
-  PRBool thisSequenceStartsAtBeginningOfLine = !mColPos;
-  PRBool onceAgainBecauseWeAddedBreakInFront;
-  PRBool foundWhitespaceInLoop;
-
-  do {
-    onceAgainBecauseWeAddedBreakInFront = PR_FALSE;
-    foundWhitespaceInLoop = PR_FALSE;
-
-    do {
-      if (*aPos == ' ' || *aPos == '\t' || *aPos == '\n') {
-        foundWhitespaceInLoop = PR_TRUE;
-        break;
-      }
-
-      ++aPos;
-      ++mColPos;
-    } while (mColPos < mMaxColumn && aPos < aEnd);
-
-    if (aPos == aEnd || foundWhitespaceInLoop) {
-      // there is enough room for the complete block we found
-
-      if (mAddSpace) {
-        aOutputStr.Append(PRUnichar(' '));
-        mAddSpace = PR_FALSE;
-      }
-
-      aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
-      // We have not yet reached the max column, we will continue to
-      // fill the current line in the next outer loop iteration.
-    }
-    else { // mColPos == mMaxColumn
-      if (!thisSequenceStartsAtBeginningOfLine && mAddSpace) {
-        // We can avoid to wrap.
-
-        aOutputStr.Append(mLineBreak);
-        mAddSpace = PR_FALSE;
-        aPos = aSequenceStart;
-        mColPos = 0;
-        thisSequenceStartsAtBeginningOfLine = PR_TRUE;
-        onceAgainBecauseWeAddedBreakInFront = PR_TRUE;
-      }
-      else {
-        // we must wrap
-
-        PRBool foundWrapPosition = PR_FALSE;
-        nsILineBreaker *lineBreaker = nsContentUtils::LineBreaker();
-
-        PRInt32 wrapPosition;
-
-        wrapPosition = lineBreaker->Prev(aSequenceStart,
-                                         (aEnd - aSequenceStart),
-                                         (aPos - aSequenceStart) + 1);
-        if (wrapPosition != NS_LINEBREAKER_NEED_MORE_TEXT) {
-          foundWrapPosition = PR_TRUE;
-        }
-        else {
-          wrapPosition = lineBreaker->Next(aSequenceStart,
-                                           (aEnd - aSequenceStart),
-                                           (aPos - aSequenceStart));
-          if (wrapPosition != NS_LINEBREAKER_NEED_MORE_TEXT) {
-            foundWrapPosition = PR_TRUE;
-          }
-        }
-
-        if (foundWrapPosition) {
-          if (mAddSpace) {
-            aOutputStr.Append(PRUnichar(' '));
-            mAddSpace = PR_FALSE;
-          }
-
-          aOutputStr.Append(aSequenceStart, wrapPosition);
-          aOutputStr.Append(mLineBreak);
-          aPos = aSequenceStart + wrapPosition;
-          mColPos = 0;
-          aMayIgnoreStartOfLineWhitespaceSequence = PR_TRUE;
-          mMayIgnoreLineBreakSequence = PR_TRUE;
-        }
-        else {
-          // try some simple fallback logic
-          // go forward up to the next whitespace position,
-          // in the worst case this will be all the rest of the data
-
-          do {
-            if (*aPos == ' ' || *aPos == '\t' || *aPos == '\n') {
-              break;
-            }
-
-            ++aPos;
-            ++mColPos;
-          } while (aPos < aEnd);
-
-          if (mAddSpace) {
-            aOutputStr.Append(PRUnichar(' '));
-            mAddSpace = PR_FALSE;
-          }
-
-          aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
-        }
-      }
-    }
-  } while (onceAgainBecauseWeAddedBreakInFront);
-}
-
-void 
-nsHTMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aStr,
-                                               nsAString& aOutputStr,
-                                               PRBool aTranslateEntities)
-{
-  nsASingleFragmentString::const_char_iterator pos, end, sequenceStart;
-
-  aStr.BeginReading(pos);
-  aStr.EndReading(end);
-
-  // if the current line already has text on it, such as a tag,
-  // leading whitespace is significant
-
-  PRBool mayIgnoreStartOfLineWhitespaceSequence = !mColPos;
-
-  while (pos < end) {
-    sequenceStart = pos;
-
-    // if beginning of a whitespace sequence
-    if (*pos == ' ' || *pos == '\n' || *pos == '\t') {
-      AppendWrapped_WhitespaceSequence(pos, end, sequenceStart, 
-        mayIgnoreStartOfLineWhitespaceSequence, aOutputStr);
-    }
-    else { // any other non-whitespace char
-      AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart, 
-        mayIgnoreStartOfLineWhitespaceSequence, aOutputStr);
-    }
-  }
-}
 
 NS_IMETHODIMP
 nsHTMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument,
                                              nsAString& aStr)
 {
   return NS_OK;
 }
 
-PRBool
-nsHTMLContentSerializer::IsJavaScript(nsIAtom* aAttrNameAtom, const nsAString& aValueString)
-{
-  if (aAttrNameAtom == nsGkAtoms::href ||
-      aAttrNameAtom == nsGkAtoms::src) {
-    static const char kJavaScript[] = "javascript";
-    PRInt32 pos = aValueString.FindChar(':');
-    if (pos < (PRInt32)(sizeof kJavaScript - 1))
-        return PR_FALSE;
-    nsAutoString scheme(Substring(aValueString, 0, pos));
-    scheme.StripWhitespace();
-    if ((scheme.Length() == (sizeof kJavaScript - 1)) &&
-        scheme.EqualsIgnoreCase(kJavaScript))
-      return PR_TRUE;
-    else
-      return PR_FALSE;  
-  }
-
-  return nsContentUtils::IsEventAttributeName(aAttrNameAtom,
-                                              EventNameType_HTML);
-}
-
-nsresult 
-nsHTMLContentSerializer::EscapeURI(const nsAString& aURI, nsAString& aEscapedURI)
-{
-  // URL escape %xx cannot be used in JS.
-  // No escaping if the scheme is 'javascript'.
-  if (IsJavaScript(nsGkAtoms::href, aURI)) {
-    aEscapedURI = aURI;
-    return NS_OK;
-  }
-
-  // nsITextToSubURI does charset convert plus uri escape
-  // This is needed to convert to a document charset which is needed to support existing browsers.
-  // But we eventually want to use UTF-8 instead of a document charset, then the code would be much simpler.
-  // See HTML 4.01 spec, "Appendix B.2.1 Non-ASCII characters in URI attribute values"
-  nsCOMPtr<nsITextToSubURI> textToSubURI;
-  nsAutoString uri(aURI); // in order to use FindCharInSet()
-  nsresult rv = NS_OK;
-
-
-  if (!mCharset.IsEmpty() && !IsASCII(uri)) {
-    textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  PRInt32 start = 0;
-  PRInt32 end;
-  nsAutoString part;
-  nsXPIDLCString escapedURI;
-  aEscapedURI.Truncate(0);
-
-  // Loop and escape parts by avoiding escaping reserved characters (and '%', '#' ).
-  while ((end = uri.FindCharInSet("%#;/?:@&=+$,", start)) != -1) {
-    part = Substring(aURI, start, (end-start));
-    if (textToSubURI && !IsASCII(part)) {
-      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    else {
-      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
-    }
-    AppendASCIItoUTF16(escapedURI, aEscapedURI);
-
-    // Append a reserved character without escaping.
-    part = Substring(aURI, end, 1);
-    aEscapedURI.Append(part);
-    start = end + 1;
-  }
-
-  if (start < (PRInt32) aURI.Length()) {
-    // Escape the remaining part.
-    part = Substring(aURI, start, aURI.Length()-start);
-    if (textToSubURI) {
-      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    else {
-      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
-    }
-    AppendASCIItoUTF16(escapedURI, aEscapedURI);
-  }
-
-  return rv;
-}
-
 void 
 nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
+                                             nsIDOMElement *aOriginalElement,
+                                             nsAString& aTagPrefix,
+                                             const nsAString& aTagNamespaceURI,
                                              nsIAtom* aTagName,
                                              nsAString& aStr)
 {
   nsresult rv;
   PRUint32 index, count;
   nsAutoString nameStr, valueStr;
 
   count = aContent->GetAttrCount();
@@ -538,17 +143,17 @@ nsHTMLContentSerializer::SerializeAttrib
       continue;
     }
 
     if (mIsCopying && mIsFirstChildOfOL && (aTagName == nsGkAtoms::li) && 
         (attrName == nsGkAtoms::value)){
       // This is handled separately in SerializeLIValueAttribute()
       continue;
     }
-    PRBool isJS = IsJavaScript(attrName, valueStr);
+    PRBool isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
     
     if (((attrName == nsGkAtoms::href) || 
          (attrName == nsGkAtoms::src))) {
       // Make all links absolute when converting only the selection:
       if (mFlags & nsIDocumentEncoder::OutputAbsoluteLinks) {
         // Would be nice to handle OBJECT and APPLET tags,
         // but that gets more complicated since we have to
         // search the tag list for CODEBASE as well.
@@ -559,46 +164,33 @@ nsHTMLContentSerializer::SerializeAttrib
           rv = NS_MakeAbsoluteURI(absURI, valueStr, uri);
           if (NS_SUCCEEDED(rv)) {
             valueStr = absURI;
           }
         }
       }
       // Need to escape URI.
       nsAutoString tempURI(valueStr);
-      if (!isJS && NS_FAILED(EscapeURI(tempURI, valueStr)))
+      if (!isJS && NS_FAILED(EscapeURI(aContent, tempURI, valueStr)))
         valueStr = tempURI;
     }
 
     if (mIsWholeDocument && aTagName == nsGkAtoms::meta &&
         attrName == nsGkAtoms::content) {
       // If we're serializing a <meta http-equiv="content-type">,
       // use the proper value, rather than what's in the document.
       nsAutoString header;
       aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
       if (header.LowerCaseEqualsLiteral("content-type")) {
         valueStr = NS_LITERAL_STRING("text/html; charset=") +
           NS_ConvertASCIItoUTF16(mCharset);
       }
     }
 
     attrName->ToString(nameStr);
-    
-    /*If we already crossed the MaxColumn limit or 
-    * if this attr name-value pair(including a space,=,opening and closing quotes) is greater than MaxColumn limit
-    * then start the attribute from a new line.
-    */
-
-    if (mDoFormat
-        && (mColPos >= mMaxColumn
-            || ((PRInt32)(mColPos + nameStr.Length() +
-                          valueStr.Length() + 4) > mMaxColumn))) {
-        aStr.Append(mLineBreak);
-        mColPos = 0;
-    }
 
     // Expand shorthand attribute.
     if (IsShorthandAttr(attrName, aTagName) && valueStr.IsEmpty()) {
       valueStr = nameStr;
     }
     SerializeAttr(EmptyString(), nameStr, valueStr, aStr, !isJS);
   }
 }
@@ -608,67 +200,62 @@ nsHTMLContentSerializer::AppendElementSt
                                             nsIDOMElement *aOriginalElement,
                                             nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   if (!content) return NS_ERROR_FAILURE;
 
-  // The _moz_dirty attribute is emitted by the editor to
-  // indicate that this element should be pretty printed
-  // even if we're not in pretty printing mode
-  PRBool hasDirtyAttr = content->HasAttr(kNameSpaceID_None,
-                                         nsGkAtoms::mozdirty);
-
-  nsIAtom *name = content->Tag();
-
-  if (name == nsGkAtoms::br && mPreLevel > 0
-      && (mFlags & nsIDocumentEncoder::OutputNoFormattingInPre)) {
-    AppendToString(mLineBreak, aStr);
-    mMayIgnoreLineBreakSequence = PR_TRUE;
-    mColPos = 0;
+  PRBool forceFormat;
+  if (!CheckElementStart(content, forceFormat, aStr)) {
     return NS_OK;
   }
 
-  if (name == nsGkAtoms::body) {
-    ++mInBody;
-  }
+  nsIAtom *name = content->Tag();
+  PRBool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
 
-  if (LineBreakBeforeOpen(name, hasDirtyAttr)) {
-    AppendToString(mLineBreak, aStr);
-    mMayIgnoreLineBreakSequence = PR_TRUE;
-    mColPos = 0;
-    mAddSpace = PR_FALSE;
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+    if (mColPos && lineBreakBeforeOpen) {
+      AppendNewLineToString(aStr);
+    }
+    else {
+      MaybeAddNewlineForRootNode(aStr);
+    }
+    if (!mColPos) {
+      AppendIndentation(aStr);
+    }
+    else if (mAddSpace) {
+      AppendToString(PRUnichar(' '), aStr);
+      mAddSpace = PR_FALSE;
+    }
   }
   else if (mAddSpace) {
     AppendToString(PRUnichar(' '), aStr);
     mAddSpace = PR_FALSE;
   }
   else {
-    MaybeAddNewline(aStr);
+    MaybeAddNewlineForRootNode(aStr);
   }
-  // Always reset to avoid false newlines in case MaybeAddNewline wasn't
+  // Always reset to avoid false newlines in case MaybeAddNewlineForRootNode wasn't
   // called
-  mAddNewline = PR_FALSE;
-
-  StartIndentation(name, hasDirtyAttr, aStr);
-
-  if (name == nsGkAtoms::pre ||
-      name == nsGkAtoms::script ||
-      name == nsGkAtoms::style) {
-    mPreLevel++;
-  }
+  mAddNewlineForRootNode = PR_FALSE;
   
   AppendToString(kLessThan, aStr);
 
   nsAutoString nameStr;
   name->ToString(nameStr);
   AppendToString(nameStr.get(), -1, aStr);
 
+  MaybeEnterInPreContent(content);
+
+  // for block elements, we increase the indentation
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw)
+    IncrIndentation(name);
+
   // Need to keep track of OL and LI elements in order to get ordinal number 
   // for the LI.
   if (mIsCopying && name == nsGkAtoms::ol){
     // We are copying and current node is an OL;
     // Store its start attribute value in olState->startVal.
     nsAutoString start;
     PRInt32 startAttrVal = 0;
     aElement->GetAttribute(NS_LITERAL_STRING("start"), start);
@@ -691,632 +278,129 @@ nsHTMLContentSerializer::AppendElementSt
     if (mIsFirstChildOfOL){
       // If OL is parent of this LI, serialize attributes in different manner.
       SerializeLIValueAttribute(aElement, aStr);
     }
   }
 
   // Even LI passed above have to go through this 
   // for serializing attributes other than "value".
-  SerializeAttributes(content, name, aStr);
+  nsAutoString dummyPrefix;
+  SerializeAttributes(content, aOriginalElement, dummyPrefix, EmptyString(), name, aStr);
 
   AppendToString(kGreaterThan, aStr);
 
-  if (LineBreakAfterOpen(name, hasDirtyAttr)) {
-    AppendToString(mLineBreak, aStr);
-    mMayIgnoreLineBreakSequence = PR_TRUE;
-    mColPos = 0;
-  }
-
   if (name == nsGkAtoms::script ||
       name == nsGkAtoms::style ||
       name == nsGkAtoms::noscript ||
       name == nsGkAtoms::noframes) {
-    mInCDATA = PR_TRUE;
+    ++mDisableEntityEncoding;
   }
 
-  if (mIsWholeDocument && name == nsGkAtoms::head) {
-    // Check if there already are any content-type meta children.
-    // If there are, they will be modified to use the correct charset.
-    // If there aren't, we'll insert one here.
-    PRBool hasMeta = PR_FALSE;
-    PRUint32 i, childCount = content->GetChildCount();
-    for (i = 0; i < childCount; ++i) {
-      nsIContent* child = content->GetChildAt(i);
-      if (child->IsNodeOfType(nsINode::eHTML) &&
-          child->Tag() == nsGkAtoms::meta &&
-          child->HasAttr(kNameSpaceID_None, nsGkAtoms::content)) {
-        nsAutoString header;
-        child->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+  if ((mDoFormat || forceFormat) && !mPreLevel &&
+    !mDoRaw && LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
+    AppendNewLineToString(aStr);
+  }
 
-        if (header.LowerCaseEqualsLiteral("content-type")) {
-          hasMeta = PR_TRUE;
-          break;
-        }
-      }
-    }
-
-    if (!hasMeta) {
-      AppendToString(mLineBreak, aStr);
-      AppendToString(NS_LITERAL_STRING("<meta http-equiv=\"content-type\""),
-                     aStr);
-      AppendToString(NS_LITERAL_STRING(" content=\"text/html; charset="), aStr);
-      AppendToString(NS_ConvertASCIItoUTF16(mCharset), aStr);
-      AppendToString(NS_LITERAL_STRING("\">"), aStr);
-    }
-  }
+  AfterElementStart(content, aOriginalElement, aStr);
 
   return NS_OK;
 }
   
 NS_IMETHODIMP 
 nsHTMLContentSerializer::AppendElementEnd(nsIDOMElement *aElement,
                                           nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   if (!content) return NS_ERROR_FAILURE;
 
-  PRBool hasDirtyAttr = content->HasAttr(kNameSpaceID_None,
-                                         nsGkAtoms::mozdirty);
+  nsIAtom *name = content->Tag();
 
-  nsIAtom *name = content->Tag();
+  if (name == nsGkAtoms::script ||
+      name == nsGkAtoms::style ||
+      name == nsGkAtoms::noscript ||
+      name == nsGkAtoms::noframes) {
+    --mDisableEntityEncoding;
+  }
+
+  PRBool forceFormat = content->HasAttr(kNameSpaceID_None,
+                                        nsGkAtoms::mozdirty);
+
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+    DecrIndentation(name);
+  }
 
   if (name == nsGkAtoms::script) {
     nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aElement);
 
     if (script && script->IsMalformed()) {
       // We're looking at a malformed script tag. This means that the end tag
       // was missing in the source. Imitate that here by not serializing the end
       // tag.
+      --mPreLevel;
       return NS_OK;
     }
   }
-
-  if (name == nsGkAtoms::pre ||
-      name == nsGkAtoms::script ||
-      name == nsGkAtoms::style) {
-    mPreLevel--;
-  }
-
-  if (mIsCopying && (name == nsGkAtoms::ol)){
-    NS_ASSERTION(!mOLStateStack.IsEmpty(), "Cannot have an empty OL Stack");
+  else if (mIsCopying && name == nsGkAtoms::ol) {
+    NS_ASSERTION((!mOLStateStack.IsEmpty()), "Cannot have an empty OL Stack");
     /* Though at this point we must always have an state to be deleted as all 
     the OL opening tags are supposed to push an olState object to the stack*/
     if (!mOLStateStack.IsEmpty()) {
       mOLStateStack.RemoveElementAt(mOLStateStack.Length() -1);
     }
   }
   
   nsIParserService* parserService = nsContentUtils::GetParserService();
 
-  if (parserService && (name != nsGkAtoms::style)) {
+  if (parserService) {
     PRBool isContainer;
 
     parserService->IsContainer(parserService->HTMLAtomTagToId(name),
                                isContainer);
-    if (!isContainer) return NS_OK;
+    if (!isContainer)
+      return NS_OK;
   }
 
-  if (LineBreakBeforeClose(name, hasDirtyAttr)) {
-    AppendToString(mLineBreak, aStr);
-    mMayIgnoreLineBreakSequence = PR_TRUE;
-    mColPos = 0;
-    mAddSpace = PR_FALSE;
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+
+    PRBool lineBreakBeforeClose = LineBreakBeforeClose(content->GetNameSpaceID(), name);
+
+    if (mColPos && lineBreakBeforeClose) {
+      AppendNewLineToString(aStr);
+    }
+    if (!mColPos) {
+      AppendIndentation(aStr);
+    }
+    else if (mAddSpace) {
+      AppendToString(PRUnichar(' '), aStr);
+      mAddSpace = PR_FALSE;
+    }
   }
   else if (mAddSpace) {
     AppendToString(PRUnichar(' '), aStr);
     mAddSpace = PR_FALSE;
   }
 
-  EndIndentation(name, hasDirtyAttr, aStr);
-
   nsAutoString nameStr;
   name->ToString(nameStr);
 
   AppendToString(kEndTag, aStr);
   AppendToString(nameStr.get(), -1, aStr);
   AppendToString(kGreaterThan, aStr);
 
-  if (LineBreakAfterClose(name, hasDirtyAttr)) {
-    AppendToString(mLineBreak, aStr);
-    mMayIgnoreLineBreakSequence = PR_TRUE;
-    mColPos = 0;
+  MaybeLeaveFromPreContent(content);
+
+  if ((mDoFormat || forceFormat) && !mPreLevel
+      && !mDoRaw && LineBreakAfterClose(content->GetNameSpaceID(), name)) {
+    AppendNewLineToString(aStr);
   }
   else {
-    MaybeFlagNewline(aElement);
+    MaybeFlagNewlineForRootNode(aElement);
   }
 
   if (name == nsGkAtoms::body) {
     --mInBody;
   }
 
-  mInCDATA = PR_FALSE;
-
   return NS_OK;
 }
-
-void
-nsHTMLContentSerializer::AppendToString(const PRUnichar* aStr,
-                                        PRInt32 aLength,
-                                        nsAString& aOutputStr)
-{
-  if (mBodyOnly && !mInBody) {
-    return;
-  }
-
-  PRInt32 length = (aLength == -1) ? nsCRT::strlen(aStr) : aLength;
-  
-  mColPos += length;
-
-  aOutputStr.Append(aStr, length);
-}
-
-void 
-nsHTMLContentSerializer::AppendToString(const PRUnichar aChar,
-                                        nsAString& aOutputStr)
-{
-  if (mBodyOnly && !mInBody) {
-    return;
-  }
-
-  mColPos += 1;
-
-  aOutputStr.Append(aChar);
-}
-
-static const PRUint16 kValNBSP = 160;
-static const char kEntityNBSP[] = "nbsp";
-
-static const PRUint16 kGTVal = 62;
-static const char* kEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "amp", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "lt", "", "gt"
-};
-
-static const char* kAttrEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "quot", "", "", "", "amp", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "lt", "", "gt"
-};
-
-void
-nsHTMLContentSerializer::AppendToString(const nsAString& aStr,
-                                        nsAString& aOutputStr,
-                                        PRBool aTranslateEntities,
-                                        PRBool aIncrColumn)
-{
-  if (mBodyOnly && !mInBody) {
-    return;
-  }
-
-  if (aIncrColumn) {
-    mColPos += aStr.Length();
-  }
-
-  if (aTranslateEntities && !mInCDATA) {
-    if (mFlags & (nsIDocumentEncoder::OutputEncodeBasicEntities  |
-                  nsIDocumentEncoder::OutputEncodeLatin1Entities |
-                  nsIDocumentEncoder::OutputEncodeHTMLEntities   |
-                  nsIDocumentEncoder::OutputEncodeW3CEntities)) {
-      nsIParserService* parserService = nsContentUtils::GetParserService();
-
-      if (!parserService) {
-        NS_ERROR("Can't get parser service");
-        return;
-      }
-
-      nsReadingIterator<PRUnichar> done_reading;
-      aStr.EndReading(done_reading);
-
-      // for each chunk of |aString|...
-      PRUint32 advanceLength = 0;
-      nsReadingIterator<PRUnichar> iter;
-
-      const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
-
-      for (aStr.BeginReading(iter); 
-           iter != done_reading; 
-           iter.advance(PRInt32(advanceLength))) {
-        PRUint32 fragmentLength = iter.size_forward();
-        PRUint32 lengthReplaced = 0; // the number of UTF-16 codepoints
-                                     //  replaced by a particular entity
-        const PRUnichar* c = iter.get();
-        const PRUnichar* fragmentStart = c;
-        const PRUnichar* fragmentEnd = c + fragmentLength;
-        const char* entityText = nsnull;
-        nsCAutoString entityReplacement;
-        char* fullEntityText = nsnull;
-
-        advanceLength = 0;
-        // for each character in this chunk, check if it
-        // needs to be replaced
-        for (; c < fragmentEnd; c++, advanceLength++) {
-          PRUnichar val = *c;
-          if (val == kValNBSP) {
-            entityText = kEntityNBSP;
-            break;
-          }
-          else if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
-            entityText = entityTable[val];
-            break;
-          } else if (val > 127 &&
-                    ((val < 256 &&
-                      mFlags & nsIDocumentEncoder::OutputEncodeLatin1Entities) ||
-                      mFlags & nsIDocumentEncoder::OutputEncodeHTMLEntities)) {
-            parserService->HTMLConvertUnicodeToEntity(val, entityReplacement);
-
-            if (!entityReplacement.IsEmpty()) {
-              entityText = entityReplacement.get();
-              break;
-            }
-          }
-          else if (val > 127 && 
-                   mFlags & nsIDocumentEncoder::OutputEncodeW3CEntities &&
-                   mEntityConverter) {
-            if (NS_IS_HIGH_SURROGATE(val) &&
-                c + 1 < fragmentEnd &&
-                NS_IS_LOW_SURROGATE(*(c + 1))) {
-              PRUint32 valUTF32 = SURROGATE_TO_UCS4(val, *(++c));
-              if (NS_SUCCEEDED(mEntityConverter->ConvertUTF32ToEntity(valUTF32,
-                               nsIEntityConverter::entityW3C, &fullEntityText))) {
-                lengthReplaced = 2;
-                break;
-              }
-              else {
-                advanceLength++;
-              }
-            }
-            else if (NS_SUCCEEDED(mEntityConverter->ConvertToEntity(val,
-                                  nsIEntityConverter::entityW3C, 
-                                  &fullEntityText))) {
-              lengthReplaced = 1;
-              break;
-            }
-          }
-        }
-
-        aOutputStr.Append(fragmentStart, advanceLength);
-        if (entityText) {
-          aOutputStr.Append(PRUnichar('&'));
-          AppendASCIItoUTF16(entityText, aOutputStr);
-          aOutputStr.Append(PRUnichar(';'));
-          advanceLength++;
-        }
-        // if it comes from nsIEntityConverter, it already has '&' and ';'
-        else if (fullEntityText) {
-          AppendASCIItoUTF16(fullEntityText, aOutputStr);
-          nsMemory::Free(fullEntityText);
-          advanceLength += lengthReplaced;
-        }
-      }
-    } else {
-      nsXMLContentSerializer::AppendToString(aStr, aOutputStr, aTranslateEntities, aIncrColumn);
-    }
-
-    return;
-  }
-
-  aOutputStr.Append(aStr);
-}
-
-PRBool
-nsHTMLContentSerializer::LineBreakBeforeOpen(nsIAtom* aName, 
-                                             PRBool aHasDirtyAttr)
-{
-  if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
-      (mFlags & nsIDocumentEncoder::OutputRaw)) {
-    return PR_FALSE;
-  }
-        
-  if (aName == nsGkAtoms::title ||
-      aName == nsGkAtoms::meta  ||
-      aName == nsGkAtoms::link  ||
-      aName == nsGkAtoms::style ||
-      aName == nsGkAtoms::select ||
-      aName == nsGkAtoms::option ||
-      aName == nsGkAtoms::script ||
-      aName == nsGkAtoms::html) {
-    return PR_TRUE;
-  }
-  else {
-    nsIParserService* parserService = nsContentUtils::GetParserService();
-    
-    if (parserService) {
-      PRBool res;
-      parserService->IsBlock(parserService->HTMLAtomTagToId(aName), res);
-      return res;
-    }
-  }
-
-  return PR_FALSE;
-}
-
-PRBool 
-nsHTMLContentSerializer::LineBreakAfterOpen(nsIAtom* aName, 
-                                            PRBool aHasDirtyAttr)
-{
-  if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
-      (mFlags & nsIDocumentEncoder::OutputRaw)) {
-    return PR_FALSE;
-  }
-
-  if ((aName == nsGkAtoms::html) ||
-      (aName == nsGkAtoms::head) ||
-      (aName == nsGkAtoms::body) ||
-      (aName == nsGkAtoms::ul) ||
-      (aName == nsGkAtoms::ol) ||
-      (aName == nsGkAtoms::dl) ||
-      (aName == nsGkAtoms::table) ||
-      (aName == nsGkAtoms::tbody) ||
-      (aName == nsGkAtoms::tr) ||
-      (aName == nsGkAtoms::br) ||
-      (aName == nsGkAtoms::meta) ||
-      (aName == nsGkAtoms::link) ||
-      (aName == nsGkAtoms::script) ||
-      (aName == nsGkAtoms::select) ||
-      (aName == nsGkAtoms::map) ||
-      (aName == nsGkAtoms::area) ||
-      (aName == nsGkAtoms::style)) {
-    return PR_TRUE;
-  }
-
-  return PR_FALSE;
-}
-
-PRBool 
-nsHTMLContentSerializer::LineBreakBeforeClose(nsIAtom* aName, 
-                                              PRBool aHasDirtyAttr)
-{
-  if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
-      (mFlags & nsIDocumentEncoder::OutputRaw)) {
-    return PR_FALSE;
-  }
-
-  if ((aName == nsGkAtoms::html) ||
-      (aName == nsGkAtoms::head) ||
-      (aName == nsGkAtoms::body) ||
-      (aName == nsGkAtoms::ul) ||
-      (aName == nsGkAtoms::ol) ||
-      (aName == nsGkAtoms::dl) ||
-      (aName == nsGkAtoms::select) ||
-      (aName == nsGkAtoms::table) ||
-      (aName == nsGkAtoms::tbody)) {
-    return PR_TRUE;
-  }
-  
-  return PR_FALSE;
-}
-
-PRBool 
-nsHTMLContentSerializer::LineBreakAfterClose(nsIAtom* aName, 
-                                             PRBool aHasDirtyAttr)
-{
-  if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
-      (mFlags & nsIDocumentEncoder::OutputRaw)) {
-    return PR_FALSE;
-  }
-
-  if ((aName == nsGkAtoms::html) ||
-      (aName == nsGkAtoms::head) ||
-      (aName == nsGkAtoms::body) ||
-      (aName == nsGkAtoms::tr) ||
-      (aName == nsGkAtoms::th) ||
-      (aName == nsGkAtoms::td) ||
-      (aName == nsGkAtoms::pre) ||
-      (aName == nsGkAtoms::title) ||
-      (aName == nsGkAtoms::li) ||
-      (aName == nsGkAtoms::dt) ||
-      (aName == nsGkAtoms::dd) ||
-      (aName == nsGkAtoms::blockquote) ||
-      (aName == nsGkAtoms::select) ||
-      (aName == nsGkAtoms::option) ||
-      (aName == nsGkAtoms::p) ||
-      (aName == nsGkAtoms::map) ||
-      (aName == nsGkAtoms::div)) {
-    return PR_TRUE;
-  }
-  else {
-    nsIParserService* parserService = nsContentUtils::GetParserService();
-    
-    if (parserService) {
-      PRBool res;
-      parserService->IsBlock(parserService->HTMLAtomTagToId(aName), res);
-      return res;
-    }
-  }
-
-  return PR_FALSE;
-}
-
-void
-nsHTMLContentSerializer::StartIndentation(nsIAtom* aName,
-                                          PRBool aHasDirtyAttr,
-                                          nsAString& aStr)
-{
-  if ((mDoFormat || aHasDirtyAttr) && !mPreLevel && !mColPos) {
-    for (PRInt32 i = mIndent; --i >= 0; ) {
-      AppendToString(kIndentStr, aStr);
-    }
-  }
-
-  if ((aName == nsGkAtoms::head) ||
-      (aName == nsGkAtoms::table) ||
-      (aName == nsGkAtoms::tr) ||
-      (aName == nsGkAtoms::ul) ||
-      (aName == nsGkAtoms::ol) ||
-      (aName == nsGkAtoms::dl) ||
-      (aName == nsGkAtoms::tbody) ||
-      (aName == nsGkAtoms::form) ||
-      (aName == nsGkAtoms::frameset) ||
-      (aName == nsGkAtoms::blockquote) ||
-      (aName == nsGkAtoms::li) ||
-      (aName == nsGkAtoms::dt) ||
-      (aName == nsGkAtoms::dd)) {
-    mIndent++;
-  }
-}
-
-void
-nsHTMLContentSerializer::EndIndentation(nsIAtom* aName,
-                                        PRBool aHasDirtyAttr,
-                                        nsAString& aStr)
-{
-  if ((aName == nsGkAtoms::head) ||
-      (aName == nsGkAtoms::table) ||
-      (aName == nsGkAtoms::tr) ||
-      (aName == nsGkAtoms::ul) ||
-      (aName == nsGkAtoms::ol) ||
-      (aName == nsGkAtoms::dl) ||
-      (aName == nsGkAtoms::li) ||
-      (aName == nsGkAtoms::tbody) ||
-      (aName == nsGkAtoms::form) ||
-      (aName == nsGkAtoms::blockquote) ||
-      (aName == nsGkAtoms::dt) ||
-      (aName == nsGkAtoms::dd) ||
-      (aName == nsGkAtoms::frameset)) {
-    mIndent--;
-  }
-
-  if ((mDoFormat || aHasDirtyAttr) && !mPreLevel && !mColPos) {
-    for (PRInt32 i = mIndent; --i >= 0; ) {
-      AppendToString(kIndentStr, aStr);
-    }
-  }
-}
-
-// See if the string has any lines longer than longLineLen:
-// if so, we presume formatting is wonky (e.g. the node has been edited)
-// and we'd better rewrap the whole text node.
-PRBool 
-nsHTMLContentSerializer::HasLongLines(const nsString& text, PRInt32& aLastNewlineOffset)
-{
-  PRUint32 start=0;
-  PRUint32 theLen=text.Length();
-  PRBool rv = PR_FALSE;
-  aLastNewlineOffset = kNotFound;
-  for (start = 0; start < theLen; )
-  {
-    PRInt32 eol = text.FindChar('\n', start);
-    if (eol < 0) {
-      eol = text.Length();
-    }
-    else {
-      aLastNewlineOffset = eol;
-    }
-    if (PRInt32(eol - start) > kLongLineLen)
-      rv = PR_TRUE;
-    start = eol+1;
-  }
-  return rv;
-}
-
-void 
-nsHTMLContentSerializer::SerializeLIValueAttribute(nsIDOMElement* aElement,
-                                                   nsAString& aStr)
-{
-  // We are copying and we are at the "first" LI node of OL in selected range.
-  // It may not be the first LI child of OL but it's first in the selected range.
-  // Note that we get into this condition only once per a OL.
-  PRBool found = PR_FALSE;
-  nsCOMPtr<nsIDOMNode> currNode = do_QueryInterface(aElement);
-  nsAutoString valueStr;
-  PRInt32 offset = 0;
-  olState defaultOLState(0, PR_FALSE);
-  olState* state = nsnull;
-  if (!mOLStateStack.IsEmpty())
-    state = &mOLStateStack.ElementAt(mOLStateStack.Length()-1);
-  /* Though we should never reach to a "state" as null or mOLStateStack.IsEmpty()
-  at this point as all LI are supposed to be inside some OL and OL tag should have 
-  pushed a state to the olStateStack.*/
-  if (!state || mOLStateStack.IsEmpty())
-    state = &defaultOLState;
-  PRInt32 startVal = state->startVal;
-  state->isFirstListItem = PR_FALSE;
-  // Traverse previous siblings until we find one with "value" attribute.
-  // offset keeps track of how many previous siblings we had tocurrNode traverse.
-  while (currNode && !found) {
-    nsCOMPtr<nsIDOMElement> currElement = do_QueryInterface(currNode);
-    // currElement may be null if it were a text node.
-    if (currElement) {
-      nsAutoString tagName;
-      currElement->GetTagName(tagName);
-      if (tagName.LowerCaseEqualsLiteral("li")) {
-        currElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
-        if (valueStr.IsEmpty())
-          offset++;
-        else {
-          found = PR_TRUE;
-          PRInt32 rv = 0;
-          startVal = valueStr.ToInteger(&rv); 
-        }
-      }
-    }
-    nsCOMPtr<nsIDOMNode> tmp;
-    currNode->GetPreviousSibling(getter_AddRefs(tmp));
-    currNode.swap(tmp);
-  }
-  // If LI was not having "value", Set the "value" attribute for it.
-  // Note that We are at the first LI in the selected range of OL.
-  if (offset == 0 && found) {
-    // offset = 0 => LI itself has the value attribute and we did not need to traverse back.
-    // Just serialize value attribute like other tags.
-    SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, PR_FALSE);
-  }
-  else if (offset == 1 && !found) {
-    /*(offset = 1 && !found) means either LI is the first child node of OL 
-    and LI is not having "value" attribute. 
-    In that case we would not like to set "value" attribute to reduce the changes.
-    */
-     //do nothing...
-  }
-  else if (offset > 0) {
-    // Set value attribute.
-    nsAutoString valueStr;
-
-    //As serializer needs to use this valueAttr we are creating here, 
-    valueStr.AppendInt(startVal + offset);
-    SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, PR_FALSE);
-  }
-}
-
-PRBool
-nsHTMLContentSerializer::IsFirstChildOfOL(nsIDOMElement* aElement){
-  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
-  nsAutoString parentName;
-  {
-    nsCOMPtr<nsIDOMNode> parentNode;
-    node->GetParentNode(getter_AddRefs(parentNode));
-    if (parentNode)
-      parentNode->GetNodeName(parentName);
-    else
-      return PR_FALSE;
-  }
-  
-  if (parentName.LowerCaseEqualsLiteral("ol")) {
-    olState defaultOLState(0, PR_FALSE);
-    olState* state = nsnull;
-    if (!mOLStateStack.IsEmpty())
-      state = &mOLStateStack.ElementAt(mOLStateStack.Length()-1);
-    /* Though we should never reach to a "state" as null at this point as 
-    all LI are supposed to be inside some OL and OL tag should have pushed
-    a state to the mOLStateStack.*/
-    if (!state)
-      state = &defaultOLState;
-    
-    if (state->isFirstListItem)
-      return PR_TRUE;
-
-    return PR_FALSE;
-  }
-  else
-    return PR_FALSE;
-}
--- a/content/base/src/nsHTMLContentSerializer.h
+++ b/content/base/src/nsHTMLContentSerializer.h
@@ -40,140 +40,43 @@
  * nsIContentSerializer implementation that can be used with an
  * nsIDocumentEncoder to convert an HTML (not XHTML!) DOM to an HTML
  * string that could be parsed into more or less the original DOM.
  */
 
 #ifndef nsHTMLContentSerializer_h__
 #define nsHTMLContentSerializer_h__
 
-#include "nsXMLContentSerializer.h"
+#include "nsXHTMLContentSerializer.h"
 #include "nsIEntityConverter.h"
 #include "nsString.h"
-#include "nsTArray.h"
 
 class nsIContent;
 class nsIAtom;
 
-class nsHTMLContentSerializer : public nsXMLContentSerializer {
+class nsHTMLContentSerializer : public nsXHTMLContentSerializer {
  public:
   nsHTMLContentSerializer();
   virtual ~nsHTMLContentSerializer();
 
-  NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
-                  const char* aCharSet, PRBool aIsCopying,
-                  PRBool aIsWholeDocument);
-
-  NS_IMETHOD AppendText(nsIDOMText* aText, 
-                        PRInt32 aStartOffset,
-                        PRInt32 aEndOffset,
-                        nsAString& aStr);
   NS_IMETHOD AppendElementStart(nsIDOMElement *aElement,
                                 nsIDOMElement *aOriginalElement,
                                 nsAString& aStr);
   
   NS_IMETHOD AppendElementEnd(nsIDOMElement *aElement,
                               nsAString& aStr);
 
   NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument,
                                  nsAString& aStr);
  protected:
-  PRBool LineBreakBeforeOpen(nsIAtom* aName, PRBool aHasDirtyAttr);
-  PRBool LineBreakAfterOpen(nsIAtom* aName, PRBool aHasDirtyAttr);
-  PRBool LineBreakBeforeClose(nsIAtom* aName, PRBool aHasDirtyAttr);
-  PRBool LineBreakAfterClose(nsIAtom* aName, PRBool aHasDirtyAttr);
-  PRBool IsFirstChildOfOL(nsIDOMElement* aElement);
-  void StartIndentation(nsIAtom* aName, 
-                        PRBool aHasDirtyAttr,
-                        nsAString& aStr);
-  void EndIndentation(nsIAtom* aName, 
-                      PRBool aHasDirtyAttr,
-                      nsAString& aStr);
-  nsresult GetEntityConverter(nsIEntityConverter** aConverter);
-  void SerializeAttributes(nsIContent* aContent,
+
+  virtual void SerializeAttributes(nsIContent* aContent,
+                           nsIDOMElement *aOriginalElement,
+                           nsAString& aTagPrefix,
+                           const nsAString& aTagNamespaceURI,
                            nsIAtom* aTagName,
                            nsAString& aStr);
-  void SerializeLIValueAttribute(nsIDOMElement* aElement,
-                                 nsAString& aStr);
-  virtual void AppendToString(const PRUnichar* aStr,
-                              PRInt32 aLength,
-                              nsAString& aOutputStr);
-  virtual void AppendToString(const PRUnichar aChar,
-                              nsAString& aOutputStr);
-  virtual void AppendToString(const nsAString& aStr,
-                              nsAString& aOutputStr,
-                              PRBool aTranslateEntities = PR_FALSE,
-                              PRBool aIncrColumn = PR_TRUE);
-
-  void AppendWrapped_WhitespaceSequence(
-          nsASingleFragmentString::const_char_iterator &aPos,
-          const nsASingleFragmentString::const_char_iterator aEnd,
-          const nsASingleFragmentString::const_char_iterator aSequenceStart,
-          PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
-          nsAString &aOutputStr);
-  void AppendWrapped_NonWhitespaceSequence(
-          nsASingleFragmentString::const_char_iterator &aPos,
-          const nsASingleFragmentString::const_char_iterator aEnd,
-          const nsASingleFragmentString::const_char_iterator aSequenceStart,
-          PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
-          nsAString &aOutputStr);
-  virtual void AppendToStringWrapped(const nsASingleFragmentString& aStr,
-                                     nsAString& aOutputStr,
-                                     PRBool aTranslateEntities);
-  PRBool HasLongLines(const nsString& text, PRInt32& aLastNewlineOffset);
-  nsresult EscapeURI(const nsAString& aURI, nsAString& aEscapedURI);
-  PRBool IsJavaScript(nsIAtom* aAttrNameAtom, const nsAString& aAttrValueString);
-
-  nsCOMPtr<nsIEntityConverter> mEntityConverter;
-
-  PRInt32   mIndent;
-
-  PRUint32  mInBody;
-
-  PRPackedBool  mDoFormat;
-  PRPackedBool  mDoHeader;
-  PRPackedBool  mBodyOnly;
-  PRPackedBool  mIsCopying; // Set to PR_TRUE only while copying
-
-  // Indicates that a space will be added if and only if content is
-  // continued on the same line while serializing source.  Otherwise,
-  // the newline character acts as the whitespace and no space is needed.
-  PRPackedBool  mAddSpace;
-  PRPackedBool  mMayIgnoreLineBreakSequence;
-
-  // This is to ensure that we only do meta tag fixups when dealing with
-  // whole documents.
-  PRPackedBool  mIsWholeDocument;
-
-  // To keep track of First LI child of OL in selected range 
-  PRPackedBool  mIsFirstChildOfOL;
-  PRInt32       mPreLevel;
-
-  /*
-   * mInCDATA is set to PR_TRUE while the serializer is serializing
-   * the content of a element whose content is considerd CDATA by the
-   * serializer (such elements are 'script', 'style', 'noscript' and
-   * possibly others) This doesn't have anything to do with if the
-   * element is defined as CDATA in the DTD, it simply means we'll
-   * output the content of the element without doing any entity encoding
-   * what so ever.
-   */
-  PRPackedBool mInCDATA;
-
-  PRInt32   mMaxColumn;
-
-  // To keep track of startvalue of OL and first list item for nested lists
-  struct olState {
-    olState(PRInt32 aStart, PRBool aIsFirst):startVal(aStart),isFirstListItem(aIsFirst)
-    {
-    }
-    PRInt32 startVal;
-    PRBool isFirstListItem;
-  };
-
-  // Stack to store one olState struct per <OL>.
-  nsAutoTArray<olState, 8> mOLStateStack;
 };
 
 nsresult
 NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer);
 
 #endif
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsXHTMLContentSerializer.cpp
@@ -0,0 +1,1205 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ryan Jones <sciguyryan@gmail.com>
+ *   Laurent Jouanneau <laurent.jouanneau@disruptive-innovations.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * nsIContentSerializer implementation that can be used with an
+ * nsIDocumentEncoder to convert an XHTML (not HTML!) DOM to an XHTML
+ * string that could be parsed into more or less the original DOM.
+ */
+
+#include "nsXHTMLContentSerializer.h"
+
+#include "nsIDOMElement.h"
+#include "nsIDOMText.h"
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "nsIDOMDocument.h"
+#include "nsINameSpaceManager.h"
+#include "nsString.h"
+#include "nsUnicharUtils.h"
+#include "nsXPIDLString.h"
+#include "nsIServiceManager.h"
+#include "nsIDocumentEncoder.h"
+#include "nsGkAtoms.h"
+#include "nsIURI.h"
+#include "nsNetUtil.h"
+#include "nsEscape.h"
+#include "nsITextToSubURI.h"
+#include "nsCRT.h"
+#include "nsIParserService.h"
+#include "nsContentUtils.h"
+#include "nsLWBrkCIID.h"
+#include "nsIScriptElement.h"
+#include "nsAttrName.h"
+
+static const char kMozStr[] = "moz";
+
+static const PRInt32 kLongLineLen = 128;
+
+#define kXMLNS "xmlns"
+
+nsresult NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer)
+{
+  nsXHTMLContentSerializer* it = new nsXHTMLContentSerializer();
+  if (!it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return CallQueryInterface(it, aSerializer);
+}
+
+nsXHTMLContentSerializer::nsXHTMLContentSerializer()
+  : mInBody(0),
+    mIsHTMLSerializer(PR_FALSE)
+{
+}
+
+nsXHTMLContentSerializer::~nsXHTMLContentSerializer()
+{
+  NS_ASSERTION(mOLStateStack.IsEmpty(), "Expected OL State stack to be empty");
+}
+
+NS_IMETHODIMP
+nsXHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
+                              const char* aCharSet, PRBool aIsCopying,
+                              PRBool aIsWholeDocument)
+{
+  // The previous version of the HTML serializer did implicit wrapping
+  // when there is no flags, so we keep wrapping in order to keep
+  // compatibility with the existing calling code
+  // XXXLJ perhaps we should remove these two default settings later ?
+  if (aFlags & nsIDocumentEncoder::OutputFormatted ) {
+      aFlags = aFlags | nsIDocumentEncoder::OutputWrap;
+  }
+  else if (!(aFlags & nsIDocumentEncoder::OutputRaw)) {
+      aFlags = aFlags | nsIDocumentEncoder::OutputWrap;
+  }
+
+  nsresult rv;
+  rv = nsXMLContentSerializer::Init(aFlags, aWrapColumn, aCharSet, aIsCopying, aIsWholeDocument);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mIsWholeDocument = aIsWholeDocument;
+  mIsCopying = aIsCopying;
+  mIsFirstChildOfOL = PR_FALSE;
+  mInBody = 0;
+  mDisableEntityEncoding = 0;
+  mBodyOnly = (mFlags & nsIDocumentEncoder::OutputBodyOnly) ? PR_TRUE
+                                                            : PR_FALSE;
+
+  // set up entity converter if we are going to need it
+  if (mFlags & nsIDocumentEncoder::OutputEncodeW3CEntities) {
+    mEntityConverter = do_CreateInstance(NS_ENTITYCONVERTER_CONTRACTID);
+  }
+  return NS_OK;
+}
+
+
+// See if the string has any lines longer than longLineLen:
+// if so, we presume formatting is wonky (e.g. the node has been edited)
+// and we'd better rewrap the whole text node.
+PRBool
+nsXHTMLContentSerializer::HasLongLines(const nsString& text, PRInt32& aLastNewlineOffset)
+{
+  PRUint32 start=0;
+  PRUint32 theLen = text.Length();
+  PRBool rv = PR_FALSE;
+  aLastNewlineOffset = kNotFound;
+  for (start = 0; start < theLen; ) {
+    PRInt32 eol = text.FindChar('\n', start);
+    if (eol < 0) {
+      eol = text.Length();
+    }
+    else {
+      aLastNewlineOffset = eol;
+    }
+    if (PRInt32(eol - start) > kLongLineLen)
+      rv = PR_TRUE;
+    start = eol + 1;
+  }
+  return rv;
+}
+
+NS_IMETHODIMP
+nsXHTMLContentSerializer::AppendText(nsIDOMText* aText,
+                                     PRInt32 aStartOffset,
+                                     PRInt32 aEndOffset,
+                                     nsAString& aStr)
+{
+  NS_ENSURE_ARG(aText);
+
+  nsAutoString data;
+  nsresult rv;
+
+  rv = AppendTextData(aText, aStartOffset, aEndOffset, data, PR_TRUE);
+  if (NS_FAILED(rv))
+    return NS_ERROR_FAILURE;
+
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToStringConvertLF(data, aStr);
+  }
+  else if (mDoFormat) {
+    AppendToStringFormatedWrapped(data, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(data, aStr);
+  }
+  else {
+    PRInt32 lastNewlineOffset = kNotFound;
+    if (HasLongLines(data, lastNewlineOffset)) {
+      // We have long lines, rewrap
+      AppendToStringWrapped(data, aStr);
+    }
+    else {
+      AppendToStringConvertLF(data, aStr);
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsXHTMLContentSerializer::EscapeURI(nsIContent* aContent, const nsAString& aURI, nsAString& aEscapedURI)
+{
+  // URL escape %xx cannot be used in JS.
+  // No escaping if the scheme is 'javascript'.
+  if (IsJavaScript(aContent, nsGkAtoms::href, kNameSpaceID_None, aURI)) {
+    aEscapedURI = aURI;
+    return NS_OK;
+  }
+
+  // nsITextToSubURI does charset convert plus uri escape
+  // This is needed to convert to a document charset which is needed to support existing browsers.
+  // But we eventually want to use UTF-8 instead of a document charset, then the code would be much simpler.
+  // See HTML 4.01 spec, "Appendix B.2.1 Non-ASCII characters in URI attribute values"
+  nsCOMPtr<nsITextToSubURI> textToSubURI;
+  nsAutoString uri(aURI); // in order to use FindCharInSet()
+  nsresult rv = NS_OK;
+
+  if (!mCharset.IsEmpty() && !IsASCII(uri)) {
+    textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  PRInt32 start = 0;
+  PRInt32 end;
+  nsAutoString part;
+  nsXPIDLCString escapedURI;
+  aEscapedURI.Truncate(0);
+
+  // Loop and escape parts by avoiding escaping reserved characters (and '%', '#' ).
+  while ((end = uri.FindCharInSet("%#;/?:@&=+$,", start)) != -1) {
+    part = Substring(aURI, start, (end-start));
+    if (textToSubURI && !IsASCII(part)) {
+      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    else {
+      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
+    }
+    AppendASCIItoUTF16(escapedURI, aEscapedURI);
+
+    // Append a reserved character without escaping.
+    part = Substring(aURI, end, 1);
+    aEscapedURI.Append(part);
+    start = end + 1;
+  }
+
+  if (start < (PRInt32) aURI.Length()) {
+    // Escape the remaining part.
+    part = Substring(aURI, start, aURI.Length()-start);
+    if (textToSubURI) {
+      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+    else {
+      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
+    }
+    AppendASCIItoUTF16(escapedURI, aEscapedURI);
+  }
+
+  return rv;
+}
+
+void
+nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
+                                              nsIDOMElement *aOriginalElement,
+                                              nsAString& aTagPrefix,
+                                              const nsAString& aTagNamespaceURI,
+                                              nsIAtom* aTagName,
+                                              nsAString& aStr,
+                                              PRUint32 aSkipAttr,
+                                              PRBool aAddNSAttr)
+{
+  nsresult rv;
+  PRUint32 index, count;
+  nsAutoString nameStr, prefixStr, uriStr, valueStr;
+  nsAutoString xmlnsStr;
+  xmlnsStr.AssignLiteral(kXMLNS);
+
+  PRInt32 contentNamespaceID = aContent->GetNameSpaceID();
+
+  // this method is not called by nsHTMLContentSerializer
+  // so we don't have to check HTML element, just XHTML
+
+  if (mIsCopying && kNameSpaceID_XHTML == contentNamespaceID) {
+
+    // Need to keep track of OL and LI elements in order to get ordinal number 
+    // for the LI.
+    if (aTagName == nsGkAtoms::ol) {
+      // We are copying and current node is an OL;
+      // Store its start attribute value in olState->startVal.
+      nsAutoString start;
+      PRInt32 startAttrVal = 0;
+      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::start, start);
+      if (!start.IsEmpty()) {
+        PRInt32 rv = 0;
+        startAttrVal = start.ToInteger(&rv);
+        //If OL has "start" attribute, first LI element has to start with that value
+        //Therefore subtracting 1 as all the LI elements are incrementing it before using it;
+        //In failure of ToInteger(), default StartAttrValue to 0.
+        if (NS_SUCCEEDED(rv))
+          --startAttrVal;
+        else
+          startAttrVal = 0;
+      }
+      olState state (startAttrVal, PR_TRUE);
+      mOLStateStack.AppendElement(state);
+    }
+    else if (aTagName == nsGkAtoms::li) {
+      mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
+      if (mIsFirstChildOfOL) {
+        nsCOMPtr<nsIDOMElement> element (do_QueryInterface(aContent));
+        // If OL is parent of this LI, serialize attributes in different manner.
+        SerializeLIValueAttribute(element, aStr);
+      }
+    }
+  }
+
+  // If we had to add a new namespace declaration, serialize
+  // and push it on the namespace stack
+  if (aAddNSAttr) {
+    if (aTagPrefix.IsEmpty()) {
+      // Serialize default namespace decl
+      SerializeAttr(EmptyString(), xmlnsStr, aTagNamespaceURI, aStr, PR_TRUE);
+    } else {
+      // Serialize namespace decl
+      SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, PR_TRUE);
+    }
+    PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
+  }
+
+  NS_NAMED_LITERAL_STRING(_mozStr, "_moz");
+
+  count = aContent->GetAttrCount();
+
+  // Now serialize each of the attributes
+  // XXX Unfortunately we need a namespace manager to get
+  // attribute URIs.
+  for (index = 0; index < count; index++) {
+
+    if (aSkipAttr == index) {
+        continue;
+    }
+
+    const nsAttrName* name = aContent->GetAttrNameAt(index);
+    PRInt32 namespaceID = name->NamespaceID();
+    nsIAtom* attrName = name->LocalName();
+    nsIAtom* attrPrefix = name->GetPrefix();
+
+    // Filter out any attribute starting with [-|_]moz
+    const char* sharedName;
+    attrName->GetUTF8String(&sharedName);
+    if ((('_' == *sharedName) || ('-' == *sharedName)) &&
+        !nsCRT::strncmp(sharedName+1, kMozStr, PRUint32(sizeof(kMozStr)-1))) {
+      continue;
+    }
+
+    if (attrPrefix) {
+      attrPrefix->ToString(prefixStr);
+    }
+    else {
+      prefixStr.Truncate();
+    }
+
+    PRBool addNSAttr = PR_FALSE;
+    if (kNameSpaceID_XMLNS != namespaceID) {
+      nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID, uriStr);
+      addNSAttr = ConfirmPrefix(prefixStr, uriStr, aOriginalElement, PR_TRUE);
+    }
+
+    aContent->GetAttr(namespaceID, attrName, valueStr);
+
+    attrName->ToString(nameStr);
+
+    // XXX Hack to get around the fact that MathML can add
+    //     attributes starting with '-', which makes them
+    //     invalid XML. see Bug 475518
+    if (!nameStr.IsEmpty() && nameStr.First() == '-')
+      continue;
+
+    PRBool isJS = PR_FALSE;
+
+    if (kNameSpaceID_XHTML == contentNamespaceID) {
+      //
+      // Filter out special case of <br type="_moz"> or <br _moz*>,
+      // used by the editor.  Bug 16988.  Yuck.
+      //
+      if (namespaceID == kNameSpaceID_None && aTagName == nsGkAtoms::br && attrName == nsGkAtoms::type
+          && StringBeginsWith(valueStr, _mozStr)) {
+        continue;
+      }
+
+      if (mIsCopying && mIsFirstChildOfOL && (aTagName == nsGkAtoms::li)
+          && (attrName == nsGkAtoms::value)) {
+        // This is handled separately in SerializeLIValueAttribute()
+        continue;
+      }
+
+      isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+
+      if (namespaceID == kNameSpaceID_None && 
+          ((attrName == nsGkAtoms::href) ||
+          (attrName == nsGkAtoms::src))) {
+        // Make all links absolute when converting only the selection:
+        if (mFlags & nsIDocumentEncoder::OutputAbsoluteLinks) {
+          // Would be nice to handle OBJECT and APPLET tags,
+          // but that gets more complicated since we have to
+          // search the tag list for CODEBASE as well.
+          // For now, just leave them relative.
+          nsCOMPtr<nsIURI> uri = aContent->GetBaseURI();
+          if (uri) {
+            nsAutoString absURI;
+            rv = NS_MakeAbsoluteURI(absURI, valueStr, uri);
+            if (NS_SUCCEEDED(rv)) {
+              valueStr = absURI;
+            }
+          }
+        }
+        // Need to escape URI.
+        nsAutoString tempURI(valueStr);
+        if (!isJS && NS_FAILED(EscapeURI(aContent, tempURI, valueStr)))
+          valueStr = tempURI;
+      }
+
+      if (mIsWholeDocument && aTagName == nsGkAtoms::meta &&
+          attrName == nsGkAtoms::content) {
+        // If we're serializing a <meta http-equiv="content-type">,
+        // use the proper value, rather than what's in the document.
+        nsAutoString header;
+        aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+        if (header.LowerCaseEqualsLiteral("content-type")) {
+          valueStr = NS_LITERAL_STRING("text/html; charset=") +
+            NS_ConvertASCIItoUTF16(mCharset);
+        }
+      }
+
+      // Expand shorthand attribute.
+      if (namespaceID == kNameSpaceID_None && IsShorthandAttr(attrName, aTagName) && valueStr.IsEmpty()) {
+        valueStr = nameStr;
+      }
+    }
+    else {
+      isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+    }
+
+    SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS);
+
+    if (addNSAttr) {
+      NS_ASSERTION(!prefixStr.IsEmpty(),
+                   "Namespaced attributes must have a prefix");
+      SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, PR_TRUE);
+      PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
+    }
+  }
+}
+
+
+void 
+nsXHTMLContentSerializer::AppendEndOfElementStart(nsIDOMElement *aOriginalElement,
+                                                  nsIAtom * aName,
+                                                  PRInt32 aNamespaceID,
+                                                  nsAString& aStr)
+{
+  // this method is not called by nsHTMLContentSerializer
+  // so we don't have to check HTML element, just XHTML
+  NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
+
+  if (kNameSpaceID_XHTML != aNamespaceID) {
+    nsXMLContentSerializer::AppendEndOfElementStart(aOriginalElement, aName,
+                                                    aNamespaceID, aStr);
+    return;
+  }
+
+  nsIParserService* parserService = nsContentUtils::GetParserService();
+
+  if (parserService) {
+    PRBool isContainer;
+    parserService->IsContainer(parserService->HTMLAtomTagToId(aName),
+                             isContainer);
+    if (!isContainer) {
+      // for backward compatibility with HTML 4 user agents
+      // only non-container HTML elements can be closed immediatly,
+      // and a space is added before />
+      AppendToString(NS_LITERAL_STRING(" />"), aStr);
+      return;
+    }
+  }
+  AppendToString(kGreaterThan, aStr);
+}
+
+void
+nsXHTMLContentSerializer::AfterElementStart(nsIContent * aContent,
+                                            nsIDOMElement *aOriginalElement,
+                                            nsAString& aStr)
+{
+  nsIAtom *name = aContent->Tag();
+  if (((mIsHTMLSerializer && aContent->GetNameSpaceID() == kNameSpaceID_None) ||
+       (!mIsHTMLSerializer && aContent->GetNameSpaceID() == kNameSpaceID_XHTML)) &&
+      mIsWholeDocument &&
+      name == nsGkAtoms::head) {
+
+    // Check if there already are any content-type meta children.
+    // If there are, they will be modified to use the correct charset.
+    // If there aren't, we'll insert one here.
+    PRBool hasMeta = PR_FALSE;
+    PRUint32 i, childCount = aContent->GetChildCount();
+    for (i = 0; i < childCount; ++i) {
+      nsIContent* child = aContent->GetChildAt(i);
+      if (child->IsNodeOfType(nsINode::eHTML) &&
+          child->Tag() == nsGkAtoms::meta &&
+          child->HasAttr(kNameSpaceID_None, nsGkAtoms::content)) {
+        nsAutoString header;
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header);
+
+        if (header.LowerCaseEqualsLiteral("content-type")) {
+          hasMeta = PR_TRUE;
+          break;
+        }
+      }
+    }
+
+    if (!hasMeta) {
+      AppendNewLineToString(aStr);
+      if (mDoFormat) {
+        AppendIndentation(aStr);
+      }
+      AppendToString(NS_LITERAL_STRING("<meta http-equiv=\"content-type\""),
+                    aStr);
+      AppendToString(NS_LITERAL_STRING(" content=\"text/html; charset="), aStr);
+      AppendToString(NS_ConvertASCIItoUTF16(mCharset), aStr);
+      if (mIsHTMLSerializer)
+        AppendToString(NS_LITERAL_STRING("\">"), aStr);
+      else
+        AppendToString(NS_LITERAL_STRING("\" />"), aStr);
+    }
+  }
+}
+
+void
+nsXHTMLContentSerializer::AfterElementEnd(nsIContent * aContent,
+                                          nsAString& aStr)
+{
+  NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
+
+  PRInt32 namespaceID = aContent->GetNameSpaceID();
+  nsIAtom *name = aContent->Tag();
+
+  // this method is not called by nsHTMLContentSerializer
+  // so we don't have to check HTML element, just XHTML
+  if (kNameSpaceID_XHTML == namespaceID && name == nsGkAtoms::body) {
+    --mInBody;
+  }
+}
+
+
+NS_IMETHODIMP
+nsXHTMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument,
+                                              nsAString& aStr)
+{
+  if (!mBodyOnly)
+    return nsXMLContentSerializer::AppendDocumentStart(aDocument, aStr);
+
+  return NS_OK;
+}
+
+PRBool
+nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
+                                            PRBool & aForceFormat,
+                                            nsAString& aStr)
+{
+  // The _moz_dirty attribute is emitted by the editor to
+  // indicate that this element should be pretty printed
+  // even if we're not in pretty printing mode
+  aForceFormat = aContent->HasAttr(kNameSpaceID_None,
+                                   nsGkAtoms::mozdirty);
+
+  nsIAtom *name = aContent->Tag();
+  PRInt32 namespaceID = aContent->GetNameSpaceID();
+
+  if ((mIsHTMLSerializer && namespaceID == kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && namespaceID == kNameSpaceID_XHTML)) {
+    if (name == nsGkAtoms::br && mPreLevel > 0 && 
+        (mFlags & nsIDocumentEncoder::OutputNoFormattingInPre)) {
+      AppendNewLineToString(aStr);
+      return PR_FALSE;
+    }
+
+    if (name == nsGkAtoms::body) {
+      ++mInBody;
+    }
+  }
+  return PR_TRUE;
+}
+
+PRBool
+nsXHTMLContentSerializer::CheckElementEnd(nsIContent * aContent,
+                                          PRBool & aForceFormat,
+                                          nsAString& aStr)
+{
+  NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
+
+  aForceFormat = aContent->HasAttr(kNameSpaceID_None,
+                                   nsGkAtoms::mozdirty);
+
+  nsIAtom *name = aContent->Tag();
+  PRInt32 namespaceID = aContent->GetNameSpaceID();
+
+  // this method is not called by nsHTMLContentSerializer
+  // so we don't have to check HTML element, just XHTML
+  if (namespaceID == kNameSpaceID_XHTML) {
+    if (mIsCopying && name == nsGkAtoms::ol) {
+      NS_ASSERTION((!mOLStateStack.IsEmpty()), "Cannot have an empty OL Stack");
+      /* Though at this point we must always have an state to be deleted as all 
+      the OL opening tags are supposed to push an olState object to the stack*/
+      if (!mOLStateStack.IsEmpty()) {
+        mOLStateStack.RemoveElementAt(mOLStateStack.Length() -1);
+      }
+    }
+
+    nsIParserService* parserService = nsContentUtils::GetParserService();
+
+    if (parserService) {
+      PRBool isContainer;
+
+      parserService->IsContainer(parserService->HTMLAtomTagToId(name),
+                                 isContainer);
+      if (!isContainer) {
+        // non-container HTML elements are already closed,
+        // see AppendEndOfElementStart
+        return PR_FALSE;
+      }
+    }
+    // for backward compatibility with old HTML user agents,
+    // empty elements should have an ending tag, so we mustn't call
+    // nsXMLContentSerializer::CheckElementEnd
+    return PR_TRUE;
+  }
+
+  PRBool dummyFormat;
+  return nsXMLContentSerializer::CheckElementEnd(aContent, dummyFormat, aStr);
+}
+
+void
+nsXHTMLContentSerializer::AppendToString(const PRUnichar* aStr,
+                                         PRInt32 aLength,
+                                         nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToString(aStr, aLength, aOutputStr);
+}
+
+void 
+nsXHTMLContentSerializer::AppendToString(const PRUnichar aChar,
+                                         nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToString(aChar, aOutputStr);
+}
+
+void
+nsXHTMLContentSerializer::AppendToString(const nsAString& aStr,
+                                         nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToString(aStr, aOutputStr);
+}
+
+
+static const PRUint16 kValNBSP = 160;
+static const char kEntityNBSP[] = "nbsp";
+
+static const PRUint16 kGTVal = 62;
+static const char* kEntities[] = {
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "amp", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "lt", "", "gt"
+};
+
+static const char* kAttrEntities[] = {
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "quot", "", "", "", "amp", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "lt", "", "gt"
+};
+
+void
+nsXHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
+                                                     nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+
+  if (mDisableEntityEncoding) {
+    aOutputStr.Append(aStr);
+    return;
+  }
+
+  if (mFlags & (nsIDocumentEncoder::OutputEncodeBasicEntities  |
+                nsIDocumentEncoder::OutputEncodeLatin1Entities |
+                nsIDocumentEncoder::OutputEncodeHTMLEntities   |
+                nsIDocumentEncoder::OutputEncodeW3CEntities)) {
+    nsIParserService* parserService = nsContentUtils::GetParserService();
+
+    if (!parserService) {
+      NS_ERROR("Can't get parser service");
+      return;
+    }
+
+    nsReadingIterator<PRUnichar> done_reading;
+    aStr.EndReading(done_reading);
+
+    // for each chunk of |aString|...
+    PRUint32 advanceLength = 0;
+    nsReadingIterator<PRUnichar> iter;
+
+    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
+
+    for (aStr.BeginReading(iter);
+          iter != done_reading;
+          iter.advance(PRInt32(advanceLength))) {
+      PRUint32 fragmentLength = iter.size_forward();
+      PRUint32 lengthReplaced = 0; // the number of UTF-16 codepoints
+                                    //  replaced by a particular entity
+      const PRUnichar* c = iter.get();
+      const PRUnichar* fragmentStart = c;
+      const PRUnichar* fragmentEnd = c + fragmentLength;
+      const char* entityText = nsnull;
+      nsCAutoString entityReplacement;
+      char* fullEntityText = nsnull;
+
+      advanceLength = 0;
+      // for each character in this chunk, check if it
+      // needs to be replaced
+      for (; c < fragmentEnd; c++, advanceLength++) {
+        PRUnichar val = *c;
+        if (val == kValNBSP) {
+          entityText = kEntityNBSP;
+          break;
+        }
+        else if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
+          entityText = entityTable[val];
+          break;
+        } else if (val > 127 &&
+                  ((val < 256 &&
+                    mFlags & nsIDocumentEncoder::OutputEncodeLatin1Entities) ||
+                    mFlags & nsIDocumentEncoder::OutputEncodeHTMLEntities)) {
+          parserService->HTMLConvertUnicodeToEntity(val, entityReplacement);
+
+          if (!entityReplacement.IsEmpty()) {
+            entityText = entityReplacement.get();
+            break;
+          }
+        }
+        else if (val > 127 &&
+                  mFlags & nsIDocumentEncoder::OutputEncodeW3CEntities &&
+                  mEntityConverter) {
+          if (NS_IS_HIGH_SURROGATE(val) &&
+              c + 1 < fragmentEnd &&
+              NS_IS_LOW_SURROGATE(*(c + 1))) {
+            PRUint32 valUTF32 = SURROGATE_TO_UCS4(val, *(++c));
+            if (NS_SUCCEEDED(mEntityConverter->ConvertUTF32ToEntity(valUTF32,
+                              nsIEntityConverter::entityW3C, &fullEntityText))) {
+              lengthReplaced = 2;
+              break;
+            }
+            else {
+              advanceLength++;
+            }
+          }
+          else if (NS_SUCCEEDED(mEntityConverter->ConvertToEntity(val,
+                                nsIEntityConverter::entityW3C, 
+                                &fullEntityText))) {
+            lengthReplaced = 1;
+            break;
+          }
+        }
+      }
+
+      aOutputStr.Append(fragmentStart, advanceLength);
+      if (entityText) {
+        aOutputStr.Append(PRUnichar('&'));
+        AppendASCIItoUTF16(entityText, aOutputStr);
+        aOutputStr.Append(PRUnichar(';'));
+        advanceLength++;
+      }
+      // if it comes from nsIEntityConverter, it already has '&' and ';'
+      else if (fullEntityText) {
+        AppendASCIItoUTF16(fullEntityText, aOutputStr);
+        nsMemory::Free(fullEntityText);
+        advanceLength += lengthReplaced;
+      }
+    }
+  } else {
+    nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr);
+  }
+}
+
+PRBool
+nsXHTMLContentSerializer::IsShorthandAttr(const nsIAtom* aAttrName,
+                                          const nsIAtom* aElementName)
+{
+  // checked
+  if ((aAttrName == nsGkAtoms::checked) &&
+      (aElementName == nsGkAtoms::input)) {
+    return PR_TRUE;
+  }
+
+  // compact
+  if ((aAttrName == nsGkAtoms::compact) &&
+      (aElementName == nsGkAtoms::dir || 
+       aElementName == nsGkAtoms::dl ||
+       aElementName == nsGkAtoms::menu ||
+       aElementName == nsGkAtoms::ol ||
+       aElementName == nsGkAtoms::ul)) {
+    return PR_TRUE;
+  }
+
+  // declare
+  if ((aAttrName == nsGkAtoms::declare) &&
+      (aElementName == nsGkAtoms::object)) {
+    return PR_TRUE;
+  }
+
+  // defer
+  if ((aAttrName == nsGkAtoms::defer) &&
+      (aElementName == nsGkAtoms::script)) {
+    return PR_TRUE;
+  }
+
+  // disabled
+  if ((aAttrName == nsGkAtoms::disabled) &&
+      (aElementName == nsGkAtoms::button ||
+       aElementName == nsGkAtoms::input ||
+       aElementName == nsGkAtoms::optgroup ||
+       aElementName == nsGkAtoms::option ||
+       aElementName == nsGkAtoms::select ||
+       aElementName == nsGkAtoms::textarea)) {
+    return PR_TRUE;
+  }
+
+  // ismap
+  if ((aAttrName == nsGkAtoms::ismap) &&
+      (aElementName == nsGkAtoms::img ||
+       aElementName == nsGkAtoms::input)) {
+    return PR_TRUE;
+  }
+
+  // multiple
+  if ((aAttrName == nsGkAtoms::multiple) &&
+      (aElementName == nsGkAtoms::select)) {
+    return PR_TRUE;
+  }
+
+  // noresize
+  if ((aAttrName == nsGkAtoms::noresize) &&
+      (aElementName == nsGkAtoms::frame)) {
+    return PR_TRUE;
+  }
+
+  // noshade
+  if ((aAttrName == nsGkAtoms::noshade) &&
+      (aElementName == nsGkAtoms::hr)) {
+    return PR_TRUE;
+  }
+
+  // nowrap
+  if ((aAttrName == nsGkAtoms::nowrap) &&
+      (aElementName == nsGkAtoms::td ||
+       aElementName == nsGkAtoms::th)) {
+    return PR_TRUE;
+  }
+
+  // readonly
+  if ((aAttrName == nsGkAtoms::readonly) &&
+      (aElementName == nsGkAtoms::input ||
+       aElementName == nsGkAtoms::textarea)) {
+    return PR_TRUE;
+  }
+
+  // selected
+  if ((aAttrName == nsGkAtoms::selected) &&
+      (aElementName == nsGkAtoms::option)) {
+    return PR_TRUE;
+  }
+
+#ifdef MOZ_MEDIA
+  // autoplay and controls
+  if ((aElementName == nsGkAtoms::video || aElementName == nsGkAtoms::audio) &&
+    (aAttrName == nsGkAtoms::autoplay ||
+     aAttrName == nsGkAtoms::controls)) {
+    return PR_TRUE;
+  }
+#endif
+
+  return PR_FALSE;
+}
+
+void
+nsXHTMLContentSerializer::AppendToStringConvertLF(const nsAString& aStr,
+                                                  nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToStringConvertLF(aStr, aOutputStr);
+}
+
+void
+nsXHTMLContentSerializer::AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
+                                                        nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToStringFormatedWrapped(aStr, aOutputStr);
+}
+
+void
+nsXHTMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aStr,
+                                                nsAString& aOutputStr)
+{
+  if (mBodyOnly && !mInBody) {
+    return;
+  }
+  nsXMLContentSerializer::AppendToStringWrapped(aStr, aOutputStr);
+}
+
+
+PRBool
+nsXHTMLContentSerializer::LineBreakBeforeOpen(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+
+  if ((mIsHTMLSerializer && aNamespaceID != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNamespaceID != kNameSpaceID_XHTML)) {
+    return mAddSpace;
+  }
+
+  if (aName == nsGkAtoms::title ||
+      aName == nsGkAtoms::meta  ||
+      aName == nsGkAtoms::link  ||
+      aName == nsGkAtoms::style ||
+      aName == nsGkAtoms::select ||
+      aName == nsGkAtoms::option ||
+      aName == nsGkAtoms::script ||
+      aName == nsGkAtoms::html) {
+    return PR_TRUE;
+  }
+  else {
+    nsIParserService* parserService = nsContentUtils::GetParserService();
+
+    if (parserService) {
+      PRBool res;
+      parserService->IsBlock(parserService->HTMLAtomTagToId(aName), res);
+      return res;
+    }
+  }
+
+  return mAddSpace;
+}
+
+PRBool 
+nsXHTMLContentSerializer::LineBreakAfterOpen(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+
+  if ((mIsHTMLSerializer && aNamespaceID != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNamespaceID != kNameSpaceID_XHTML)) {
+    return PR_FALSE;
+  }
+
+  if ((aName == nsGkAtoms::html) ||
+      (aName == nsGkAtoms::head) ||
+      (aName == nsGkAtoms::body) ||
+      (aName == nsGkAtoms::ul) ||
+      (aName == nsGkAtoms::ol) ||
+      (aName == nsGkAtoms::dl) ||
+      (aName == nsGkAtoms::table) ||
+      (aName == nsGkAtoms::tbody) ||
+      (aName == nsGkAtoms::tr) ||
+      (aName == nsGkAtoms::br) ||
+      (aName == nsGkAtoms::meta) ||
+      (aName == nsGkAtoms::link) ||
+      (aName == nsGkAtoms::script) ||
+      (aName == nsGkAtoms::select) ||
+      (aName == nsGkAtoms::map) ||
+      (aName == nsGkAtoms::area) ||
+      (aName == nsGkAtoms::style)) {
+    return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+
+PRBool 
+nsXHTMLContentSerializer::LineBreakBeforeClose(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+
+  if ((mIsHTMLSerializer && aNamespaceID != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNamespaceID != kNameSpaceID_XHTML)) {
+    return PR_FALSE;
+  }
+
+  if ((aName == nsGkAtoms::html) ||
+      (aName == nsGkAtoms::head) ||
+      (aName == nsGkAtoms::body) ||
+      (aName == nsGkAtoms::ul) ||
+      (aName == nsGkAtoms::ol) ||
+      (aName == nsGkAtoms::dl) ||
+      (aName == nsGkAtoms::select) ||
+      (aName == nsGkAtoms::table) ||
+      (aName == nsGkAtoms::tbody)) {
+    return PR_TRUE;
+  }
+  return PR_FALSE;
+}
+
+PRBool 
+nsXHTMLContentSerializer::LineBreakAfterClose(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+
+  if ((mIsHTMLSerializer && aNamespaceID != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNamespaceID != kNameSpaceID_XHTML)) {
+    return PR_FALSE;
+  }
+
+  if ((aName == nsGkAtoms::html) ||
+      (aName == nsGkAtoms::head) ||
+      (aName == nsGkAtoms::body) ||
+      (aName == nsGkAtoms::tr) ||
+      (aName == nsGkAtoms::th) ||
+      (aName == nsGkAtoms::td) ||
+      (aName == nsGkAtoms::pre) ||
+      (aName == nsGkAtoms::title) ||
+      (aName == nsGkAtoms::li) ||
+      (aName == nsGkAtoms::dt) ||
+      (aName == nsGkAtoms::dd) ||
+      (aName == nsGkAtoms::blockquote) ||
+      (aName == nsGkAtoms::select) ||
+      (aName == nsGkAtoms::option) ||
+      (aName == nsGkAtoms::p) ||
+      (aName == nsGkAtoms::map) ||
+      (aName == nsGkAtoms::div)) {
+    return PR_TRUE;
+  }
+  else {
+    nsIParserService* parserService = nsContentUtils::GetParserService();
+
+    if (parserService) {
+      PRBool res;
+      parserService->IsBlock(parserService->HTMLAtomTagToId(aName), res);
+      return res;
+    }
+  }
+
+  return PR_FALSE;
+}
+
+
+void
+nsXHTMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
+{
+
+  if ((mIsHTMLSerializer && aNode->GetNameSpaceID() != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNode->GetNameSpaceID() != kNameSpaceID_XHTML)) {
+    return;
+  }
+
+  nsIAtom *name = aNode->Tag();
+
+  if (name == nsGkAtoms::pre ||
+      name == nsGkAtoms::script ||
+      name == nsGkAtoms::style ||
+      name == nsGkAtoms::noscript ||
+      name == nsGkAtoms::noframes
+      ) {
+    mPreLevel++;
+  }
+}
+
+void
+nsXHTMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
+{
+  if ((mIsHTMLSerializer && aNode->GetNameSpaceID() != kNameSpaceID_None) ||
+      (!mIsHTMLSerializer && aNode->GetNameSpaceID() != kNameSpaceID_XHTML)) {
+    return;
+  }
+
+  nsIAtom *name = aNode->Tag();
+  if (name == nsGkAtoms::pre ||
+      name == nsGkAtoms::script ||
+      name == nsGkAtoms::style ||
+      name == nsGkAtoms::noscript ||
+      name == nsGkAtoms::noframes
+    ) {
+    --mPreLevel;
+  }
+}
+
+void 
+nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIDOMElement* aElement,
+                                                    nsAString& aStr)
+{
+  // We are copying and we are at the "first" LI node of OL in selected range.
+  // It may not be the first LI child of OL but it's first in the selected range.
+  // Note that we get into this condition only once per a OL.
+  PRBool found = PR_FALSE;
+  nsCOMPtr<nsIDOMNode> currNode = do_QueryInterface(aElement);
+  nsAutoString valueStr;
+
+  olState state (0, PR_FALSE);
+
+  if (!mOLStateStack.IsEmpty()) {
+    state = mOLStateStack[mOLStateStack.Length()-1];
+    // isFirstListItem should be true only before the serialization of the
+    // first item in the list.
+    state.isFirstListItem = PR_FALSE;
+    mOLStateStack[mOLStateStack.Length()-1] = state;
+  }
+
+  PRInt32 startVal = state.startVal;
+  PRInt32 offset = 0;
+
+  // Traverse previous siblings until we find one with "value" attribute.
+  // offset keeps track of how many previous siblings we had tocurrNode traverse.
+  while (currNode && !found) {
+    nsCOMPtr<nsIDOMElement> currElement = do_QueryInterface(currNode);
+    // currElement may be null if it were a text node.
+    if (currElement) {
+      nsAutoString tagName;
+      currElement->GetTagName(tagName);
+      if (tagName.LowerCaseEqualsLiteral("li")) {
+        currElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
+        if (valueStr.IsEmpty())
+          offset++;
+        else {
+          found = PR_TRUE;
+          PRInt32 rv = 0;
+          startVal = valueStr.ToInteger(&rv);
+        }
+      }
+    }
+    nsCOMPtr<nsIDOMNode> tmp;
+    currNode->GetPreviousSibling(getter_AddRefs(tmp));
+    currNode.swap(tmp);
+  }
+  // If LI was not having "value", Set the "value" attribute for it.
+  // Note that We are at the first LI in the selected range of OL.
+  if (offset == 0 && found) {
+    // offset = 0 => LI itself has the value attribute and we did not need to traverse back.
+    // Just serialize value attribute like other tags.
+    SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, PR_FALSE);
+  }
+  else if (offset == 1 && !found) {
+    /*(offset = 1 && !found) means either LI is the first child node of OL
+    and LI is not having "value" attribute.
+    In that case we would not like to set "value" attribute to reduce the changes.
+    */
+    //do nothing...
+  }
+  else if (offset > 0) {
+    // Set value attribute.
+    nsAutoString valueStr;
+
+    //As serializer needs to use this valueAttr we are creating here, 
+    valueStr.AppendInt(startVal + offset);
+    SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, PR_FALSE);
+  }
+}
+
+PRBool
+nsXHTMLContentSerializer::IsFirstChildOfOL(nsIDOMElement* aElement)
+{
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
+  nsAutoString parentName;
+
+  nsCOMPtr<nsIDOMNode> parentNode;
+  node->GetParentNode(getter_AddRefs(parentNode));
+  if (parentNode)
+    parentNode->GetNodeName(parentName);
+  else
+    return PR_FALSE;
+
+  if (parentName.LowerCaseEqualsLiteral("ol")) {
+
+    if (!mOLStateStack.IsEmpty()) {
+      olState state = mOLStateStack[mOLStateStack.Length()-1];
+      if (state.isFirstListItem)
+        return PR_TRUE;
+    }
+
+    return PR_FALSE;
+  }
+  else
+    return PR_FALSE;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsXHTMLContentSerializer.h
@@ -0,0 +1,208 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Laurent Jouanneau <laurent.jouanneau@disruptive-innovations.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * nsIContentSerializer implementation that can be used with an
+ * nsIDocumentEncoder to convert an XHTML (not HTML!) DOM to an XHTML
+ * string that could be parsed into more or less the original DOM.
+ */
+
+#ifndef nsXHTMLContentSerializer_h__
+#define nsXHTMLContentSerializer_h__
+
+#include "nsXMLContentSerializer.h"
+#include "nsIEntityConverter.h"
+#include "nsString.h"
+#include "nsTArray.h"
+
+class nsIContent;
+class nsIAtom;
+
+class nsXHTMLContentSerializer : public nsXMLContentSerializer {
+ public:
+  nsXHTMLContentSerializer();
+  virtual ~nsXHTMLContentSerializer();
+
+  NS_IMETHOD Init(PRUint32 flags, PRUint32 aWrapColumn,
+                  const char* aCharSet, PRBool aIsCopying,
+                  PRBool aIsWholeDocument);
+
+  NS_IMETHOD AppendText(nsIDOMText* aText,
+                        PRInt32 aStartOffset,
+                        PRInt32 aEndOffset,
+                        nsAString& aStr);
+
+  NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument,
+                                 nsAString& aStr);
+
+ protected:
+
+
+  virtual PRBool CheckElementStart(nsIContent * aContent,
+                          PRBool & aForceFormat,
+                          nsAString& aStr);
+
+  virtual void AppendEndOfElementStart(nsIDOMElement *aOriginalElement,
+                               nsIAtom * aName,
+                               PRInt32 aNamespaceID,
+                               nsAString& aStr);
+
+  virtual void AfterElementStart(nsIContent * aContent,
+                         nsIDOMElement *aOriginalElement,
+                         nsAString& aStr);
+
+  virtual PRBool CheckElementEnd(nsIContent * aContent,
+                          PRBool & aForceFormat,
+                          nsAString& aStr);
+
+  virtual void AfterElementEnd(nsIContent * aContent,
+                               nsAString& aStr);
+
+  virtual PRBool LineBreakBeforeOpen(PRInt32 aNamespaceID, nsIAtom* aName);
+  virtual PRBool LineBreakAfterOpen(PRInt32 aNamespaceID, nsIAtom* aName);
+  virtual PRBool LineBreakBeforeClose(PRInt32 aNamespaceID, nsIAtom* aName);
+  virtual PRBool LineBreakAfterClose(PRInt32 aNamespaceID, nsIAtom* aName);
+
+  PRBool HasLongLines(const nsString& text, PRInt32& aLastNewlineOffset);
+
+  // functions to check if we enter in or leave from a preformated content
+  virtual void MaybeEnterInPreContent(nsIContent* aNode);
+  virtual void MaybeLeaveFromPreContent(nsIContent* aNode);
+
+  virtual void SerializeAttributes(nsIContent* aContent,
+                           nsIDOMElement *aOriginalElement,
+                           nsAString& aTagPrefix,
+                           const nsAString& aTagNamespaceURI,
+                           nsIAtom* aTagName,
+                           nsAString& aStr,
+                           PRUint32 aSkipAttr,
+                           PRBool aAddNSAttr);
+
+  PRBool IsFirstChildOfOL(nsIDOMElement* aElement);
+
+  void SerializeLIValueAttribute(nsIDOMElement* aElement,
+                                 nsAString& aStr);
+  PRBool IsShorthandAttr(const nsIAtom* aAttrName,
+                         const nsIAtom* aElementName);
+
+  virtual void AppendToString(const PRUnichar* aStr,
+                              PRInt32 aLength,
+                              nsAString& aOutputStr);
+  virtual void AppendToString(const PRUnichar aChar,
+                              nsAString& aOutputStr);
+  virtual void AppendToString(const nsAString& aStr,
+                              nsAString& aOutputStr);
+  virtual void AppendAndTranslateEntities(const nsAString& aStr,
+                                          nsAString& aOutputStr);
+
+  virtual void AppendToStringConvertLF(const nsAString& aStr,
+                                       nsAString& aOutputStr);
+
+  virtual void AppendToStringWrapped(const nsASingleFragmentString& aStr,
+                                     nsAString& aOutputStr);
+
+  virtual void AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
+                                             nsAString& aOutputStr);
+
+  nsresult EscapeURI(nsIContent* aContent,
+                     const nsAString& aURI,
+                     nsAString& aEscapedURI);
+
+  nsCOMPtr<nsIEntityConverter> mEntityConverter;
+
+  PRInt32  mInBody;
+
+  /*
+   * isHTMLParser should be set to true by the HTML parser which inherits from
+   * this class. It avoids to redefine methods just for few changes.
+   */
+  PRPackedBool  mIsHTMLSerializer;
+
+  PRPackedBool  mDoHeader;
+  PRPackedBool  mBodyOnly;
+  PRPackedBool  mIsCopying; // Set to PR_TRUE only while copying
+
+  /*
+   * mDisableEntityEncoding is higher than 0 while the serializer is serializing
+   * the content of a element whose content is considerd CDATA by the
+   * serializer (such elements are 'script', 'style', 'noscript' and
+   * possibly others in XHTML) This doesn't have anything to do with if the
+   * element is defined as CDATA in the DTD, it simply means we'll
+   * output the content of the element without doing any entity encoding
+   * what so ever.
+   */
+  PRInt32 mDisableEntityEncoding;
+
+  // This is to ensure that we only do meta tag fixups when dealing with
+  // whole documents.
+  PRPackedBool  mIsWholeDocument;
+
+  // To keep track of First LI child of OL in selected range 
+  PRPackedBool  mIsFirstChildOfOL;
+
+  // To keep track of startvalue of OL and first list item for nested lists
+  struct olState {
+    olState(PRInt32 aStart, PRBool aIsFirst)
+      : startVal(aStart),
+        isFirstListItem(aIsFirst)
+    {
+    }
+
+    olState(const olState & aOlState)
+    {
+      startVal = aOlState.startVal;
+      isFirstListItem = aOlState.isFirstListItem;
+    }
+
+    // the value of the start attribute in the OL
+    PRInt32 startVal;
+
+    // is true only before the serialization of the first li of an ol
+    // should be false for other li in the list
+    PRBool isFirstListItem;
+  };
+
+  // Stack to store one olState struct per <OL>.
+  nsAutoTArray<olState, 8> mOLStateStack;
+
+};
+
+nsresult
+NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer);
+
+#endif
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -58,35 +58,51 @@
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsString.h"
 #include "prprf.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsAttrName.h"
+#include "nsILineBreaker.h"
+
+#define kXMLNS "xmlns"
+
+// to be readable, we assume that an indented line contains
+// at least this number of characters (arbitrary value here).
+// This is a limit for the indentation.
+#define MIN_INDENTED_LINE_LENGTH 15
+
+// the string used to indent.
+#define INDENT_STRING "  "
+#define INDENT_STRING_LENGTH 2
 
 nsresult NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsXMLContentSerializer* it = new nsXMLContentSerializer();
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return CallQueryInterface(it, aSerializer);
 }
 
 nsXMLContentSerializer::nsXMLContentSerializer()
   : mPrefixIndex(0),
     mColPos(0),
+    mIndentOverflow(0),
+    mIsIndentationAddedOnCurrentLine(PR_FALSE),
     mInAttribute(PR_FALSE),
-    mAddNewline(PR_FALSE)
+    mAddNewlineForRootNode(PR_FALSE),
+    mAddSpace(PR_FALSE),
+    mMayIgnoreLineBreakSequence(PR_FALSE)
 {
 }
- 
+
 nsXMLContentSerializer::~nsXMLContentSerializer()
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsXMLContentSerializer, nsIContentSerializer)
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
@@ -105,26 +121,41 @@ nsXMLContentSerializer::Init(PRUint32 aF
     mLineBreak.AssignLiteral("\r");
   }
   else if (mFlags & nsIDocumentEncoder::OutputLFLineBreak) { // Unix/DOM
     mLineBreak.AssignLiteral("\n");
   }
   else {
     mLineBreak.AssignLiteral(NS_LINEBREAK);         // Platform/default
   }
+
+  mDoRaw = !!(mFlags & nsIDocumentEncoder::OutputRaw);
+
+  mDoFormat = (mFlags & nsIDocumentEncoder::OutputFormatted && !mDoRaw);
+
+  mDoWrap = (mFlags & nsIDocumentEncoder::OutputWrap && !mDoRaw);
+
+  if (!aWrapColumn) {
+    mMaxColumn = 72;
+  }
+  else {
+    mMaxColumn = aWrapColumn;
+  }
+
+  mPreLevel = 0;
+  mIsIndentationAddedOnCurrentLine = PR_FALSE;
   return NS_OK;
 }
 
 nsresult
-nsXMLContentSerializer::AppendTextData(nsIDOMNode* aNode, 
+nsXMLContentSerializer::AppendTextData(nsIDOMNode* aNode,
                                        PRInt32 aStartOffset,
                                        PRInt32 aEndOffset,
                                        nsAString& aStr,
-                                       PRBool aTranslateEntities,
-                                       PRBool aIncrColumn)
+                                       PRBool aTranslateEntities)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   const nsTextFragment* frag;
   if (!content || !(frag = content->GetText())) {
     return NS_ERROR_FAILURE;
   }
 
   PRInt32 endoffset = (aEndOffset == -1) ? frag->GetLength() : aEndOffset;
@@ -136,124 +167,198 @@ nsXMLContentSerializer::AppendTextData(n
   if (length <= 0) {
     // XXX Zero is a legal value, maybe non-zero values should be an
     // error.
     return NS_OK;
   }
     
   if (frag->Is2b()) {
     const PRUnichar *strStart = frag->Get2b() + aStartOffset;
-    AppendToString(Substring(strStart, strStart + length), aStr,
-                   aTranslateEntities, aIncrColumn);
+    if (aTranslateEntities) {
+      AppendAndTranslateEntities(Substring(strStart, strStart + length), aStr);
+    }
+    else {
+      aStr.Append(Substring(strStart, strStart + length));
+    }
   }
   else {
-    AppendToString(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length),
-                   aStr, aTranslateEntities, aIncrColumn);
+    if (aTranslateEntities) {
+      AppendAndTranslateEntities(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length), aStr);
+    }
+    else {
+      aStr.Append(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length));
+    }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsXMLContentSerializer::AppendText(nsIDOMText* aText, 
+nsXMLContentSerializer::AppendText(nsIDOMText* aText,
                                    PRInt32 aStartOffset,
                                    PRInt32 aEndOffset,
                                    nsAString& aStr)
 {
   NS_ENSURE_ARG(aText);
 
   nsAutoString data;
   nsresult rv;
 
-  rv = AppendTextData(aText, aStartOffset, aEndOffset, data, PR_TRUE, PR_TRUE);
+  rv = AppendTextData(aText, aStartOffset, aEndOffset, data, PR_TRUE);
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
-  AppendToStringConvertLF(data, aStr);
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToStringConvertLF(data, aStr);
+  }
+  else if (mDoFormat) {
+    AppendToStringFormatedWrapped(data, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(data, aStr);
+  }
+  else {
+    AppendToStringConvertLF(data, aStr);
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::AppendCDATASection(nsIDOMCDATASection* aCDATASection,
                                            PRInt32 aStartOffset,
                                            PRInt32 aEndOffset,
                                            nsAString& aStr)
 {
   NS_ENSURE_ARG(aCDATASection);
   nsresult rv;
 
-  AppendToString(NS_LITERAL_STRING("<![CDATA["), aStr);
-  rv = AppendTextData(aCDATASection, aStartOffset, aEndOffset, aStr, PR_FALSE, PR_TRUE);
-  if (NS_FAILED(rv)) return NS_ERROR_FAILURE;  
+  NS_NAMED_LITERAL_STRING(cdata , "<![CDATA[");
+
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToString(cdata, aStr);
+  }
+  else if (mDoFormat) {
+    AppendToStringFormatedWrapped(cdata, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(cdata, aStr);
+  }
+  else {
+    AppendToString(cdata, aStr);
+  }
+
+  nsAutoString data;
+  rv = AppendTextData(aCDATASection, aStartOffset, aEndOffset, data, PR_FALSE);
+  if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
+
+  AppendToStringConvertLF(data, aStr);
+
   AppendToString(NS_LITERAL_STRING("]]>"), aStr);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::AppendProcessingInstruction(nsIDOMProcessingInstruction* aPI,
                                                     PRInt32 aStartOffset,
                                                     PRInt32 aEndOffset,
                                                     nsAString& aStr)
 {
   NS_ENSURE_ARG(aPI);
   nsresult rv;
-  nsAutoString target, data;
+  nsAutoString target, data, start;
 
-  MaybeAddNewline(aStr);
+  MaybeAddNewlineForRootNode(aStr);
 
   rv = aPI->GetTarget(target);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
   rv = aPI->GetData(data);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
-  AppendToString(NS_LITERAL_STRING("<?"), aStr);
-  AppendToString(target, aStr);
+  start.AppendLiteral("<?");
+  start.Append(target);
+
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToString(start, aStr);
+  }
+  else if (mDoFormat) {
+    if (mAddSpace) {
+      AppendNewLineToString(aStr);
+    }
+    AppendToStringFormatedWrapped(start, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(start, aStr);
+  }
+  else {
+    AppendToString(start, aStr);
+  }
+
   if (!data.IsEmpty()) {
-    AppendToString(NS_LITERAL_STRING(" "), aStr);
+    AppendToString(PRUnichar(' '), aStr);
     AppendToStringConvertLF(data, aStr);
   }
   AppendToString(NS_LITERAL_STRING("?>"), aStr);
-  MaybeFlagNewline(aPI);
-  
+
+  MaybeFlagNewlineForRootNode(aPI);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::AppendComment(nsIDOMComment* aComment,
                                       PRInt32 aStartOffset,
                                       PRInt32 aEndOffset,
                                       nsAString& aStr)
 {
   NS_ENSURE_ARG(aComment);
   nsresult rv;
   nsAutoString data;
 
   rv = aComment->GetData(data);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
-  MaybeAddNewline(aStr);
-
-  AppendToString(NS_LITERAL_STRING("<!--"), aStr);
   if (aStartOffset || (aEndOffset != -1)) {
     PRInt32 length = (aEndOffset == -1) ? data.Length() : aEndOffset;
     length -= aStartOffset;
 
     nsAutoString frag;
     data.Mid(frag, aStartOffset, length);
-    AppendToStringConvertLF(frag, aStr);
+    data.Assign(frag);
+  }
+
+  MaybeAddNewlineForRootNode(aStr);
+
+  NS_NAMED_LITERAL_STRING(startComment, "<!--");
+
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToString(startComment, aStr);
+  }
+  else if (mDoFormat) {
+    if (mAddSpace) {
+      AppendNewLineToString(aStr);
+    }
+    AppendToStringFormatedWrapped(startComment, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(startComment, aStr);
   }
   else {
-    AppendToStringConvertLF(data, aStr);
+    AppendToString(startComment, aStr);
   }
+
+  // Even if mDoformat, we don't format the content because it
+  // could have been preformated by the author
+  AppendToStringConvertLF(data, aStr);
   AppendToString(NS_LITERAL_STRING("-->"), aStr);
-  MaybeFlagNewline(aComment);
-  
+
+  MaybeFlagNewlineForRootNode(aComment);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::AppendDoctype(nsIDOMDocumentType *aDoctype,
                                       nsAString& aStr)
 {
   NS_ENSURE_ARG(aDoctype);
@@ -264,20 +369,21 @@ nsXMLContentSerializer::AppendDoctype(ns
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
   rv = aDoctype->GetPublicId(publicId);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
   rv = aDoctype->GetSystemId(systemId);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
   rv = aDoctype->GetInternalSubset(internalSubset);
   if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
 
-  MaybeAddNewline(aStr);
+  MaybeAddNewlineForRootNode(aStr);
 
   AppendToString(NS_LITERAL_STRING("<!DOCTYPE "), aStr);
   AppendToString(name, aStr);
+
   PRUnichar quote;
   if (!publicId.IsEmpty()) {
     AppendToString(NS_LITERAL_STRING(" PUBLIC "), aStr);
     if (publicId.FindChar(PRUnichar('"')) == -1) {
       quote = PRUnichar('"');
     }
     else {
       quote = PRUnichar('\'');
@@ -313,24 +419,22 @@ nsXMLContentSerializer::AppendDoctype(ns
   }
   
   if (!internalSubset.IsEmpty()) {
     AppendToString(NS_LITERAL_STRING(" ["), aStr);
     AppendToString(internalSubset, aStr);
     AppendToString(PRUnichar(']'), aStr);
   }
     
-  AppendToString(PRUnichar('>'), aStr);
-  MaybeFlagNewline(aDoctype);
+  AppendToString(kGreaterThan, aStr);
+  MaybeFlagNewlineForRootNode(aDoctype);
 
   return NS_OK;
 }
 
-#define kXMLNS "xmlns"
-
 nsresult
 nsXMLContentSerializer::PushNameSpaceDecl(const nsAString& aPrefix,
                                           const nsAString& aURI,
                                           nsIDOMElement* aOwner)
 {
   NameSpaceDecl* decl = mNameSpaceStack.AppendElement();
   if (!decl) return NS_ERROR_OUT_OF_MEMORY;
 
@@ -516,33 +620,35 @@ nsXMLContentSerializer::GenerateNewPrefi
 
 void
 nsXMLContentSerializer::SerializeAttr(const nsAString& aPrefix,
                                       const nsAString& aName,
                                       const nsAString& aValue,
                                       nsAString& aStr,
                                       PRBool aDoEscapeEntities)
 {
-  AppendToString(PRUnichar(' '), aStr);
+  nsAutoString attrString;
+
+  attrString.Append(PRUnichar(' '));
   if (!aPrefix.IsEmpty()) {
-    AppendToString(aPrefix, aStr);
-    AppendToString(PRUnichar(':'), aStr);
+    attrString.Append(aPrefix);
+    attrString.Append(PRUnichar(':'));
   }
-  AppendToString(aName, aStr);
-  
-  if ( aDoEscapeEntities ) {
+  attrString.Append(aName);
+
+  if (aDoEscapeEntities) {
     // if problem characters are turned into character entity references
     // then there will be no problem with the value delimiter characters
-    AppendToString(NS_LITERAL_STRING("=\""), aStr);
+    attrString.AppendLiteral("=\"");
 
     mInAttribute = PR_TRUE;
-    AppendToString(aValue, aStr, PR_TRUE);
+    AppendAndTranslateEntities(aValue, attrString);
     mInAttribute = PR_FALSE;
 
-    AppendToString(PRUnichar('"'), aStr);
+    attrString.Append(PRUnichar('"'));
   }
   else {
     // Depending on whether the attribute value contains quotes or apostrophes we
     // need to select the delimiter character and escape characters using
     // character entity references, ignoring the value of aDoEscapeEntities.
     // See http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2.2 for
     // the standard on character entity references in values.  We also have to
     // make sure to escape any '&' characters.
@@ -575,75 +681,72 @@ nsXMLContentSerializer::SerializeAttr(co
     // Delimiter and escaping is according to the following table
     //    bIncludesDouble     bIncludesSingle     Delimiter       Escape Double Quote
     //    FALSE               FALSE               "               FALSE
     //    FALSE               TRUE                "               FALSE
     //    TRUE                FALSE               '               FALSE
     //    TRUE                TRUE                "               TRUE
     PRUnichar cDelimiter = 
         (bIncludesDouble && !bIncludesSingle) ? PRUnichar('\'') : PRUnichar('"');
-    AppendToString(PRUnichar('='), aStr);
-    AppendToString(cDelimiter, aStr);
+    attrString.Append(PRUnichar('='));
+    attrString.Append(cDelimiter);
     nsAutoString sValue(aValue);
     sValue.ReplaceSubstring(NS_LITERAL_STRING("&"),
                             NS_LITERAL_STRING("&amp;"));
     if (bIncludesDouble && bIncludesSingle) {
       sValue.ReplaceSubstring(NS_LITERAL_STRING("\""),
                               NS_LITERAL_STRING("&quot;"));
     }
-    mInAttribute = PR_TRUE;
-    AppendToString(sValue, aStr, PR_FALSE);
-    mInAttribute = PR_FALSE;
-    AppendToString(cDelimiter, aStr);
+    attrString.Append(sValue);
+    attrString.Append(cDelimiter);
+  }
+  if (mPreLevel > 0 || mDoRaw) {
+    AppendToStringConvertLF(attrString, aStr);
+  }
+  else if (mDoFormat) {
+    AppendToStringFormatedWrapped(attrString, aStr);
+  }
+  else if (mDoWrap) {
+    AppendToStringWrapped(attrString, aStr);
+  }
+  else {
+    AppendToStringConvertLF(attrString, aStr);
   }
 }
 
-NS_IMETHODIMP 
-nsXMLContentSerializer::AppendElementStart(nsIDOMElement *aElement,
-                                           nsIDOMElement *aOriginalElement,
-                                           nsAString& aStr)
+PRUint32 
+nsXMLContentSerializer::ScanNamespaceDeclarations(nsIContent* aContent,
+                                                  nsIDOMElement *aOriginalElement,
+                                                  const nsAString& aTagNamespaceURI)
 {
-  NS_ENSURE_ARG(aElement);
-
-  nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
-  nsAutoString xmlnsStr;
-  xmlnsStr.AssignLiteral(kXMLNS);
-
-  nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
-  if (!content) return NS_ERROR_FAILURE;
-
-  aElement->GetPrefix(tagPrefix);
-  aElement->GetLocalName(tagLocalName);
-  aElement->GetNamespaceURI(tagNamespaceURI);
-
   PRUint32 index, count;
   nsAutoString nameStr, prefixStr, uriStr, valueStr;
 
-  count = content->GetAttrCount();
+  count = aContent->GetAttrCount();
 
   // First scan for namespace declarations, pushing each on the stack
   PRUint32 skipAttr = count;
   for (index = 0; index < count; index++) {
     
-    const nsAttrName* name = content->GetAttrNameAt(index);
+    const nsAttrName* name = aContent->GetAttrNameAt(index);
     PRInt32 namespaceID = name->NamespaceID();
     nsIAtom *attrName = name->LocalName();
     
     if (namespaceID == kNameSpaceID_XMLNS ||
         // Also push on the stack attrs named "xmlns" in the null
         // namespace... because once we serialize those out they'll look like
         // namespace decls.  :(
         // XXXbz what if we have both "xmlns" in the null namespace and "xmlns"
         // in the xmlns namespace?
         (namespaceID == kNameSpaceID_None &&
          attrName == nsGkAtoms::xmlns)) {
-      content->GetAttr(namespaceID, attrName, uriStr);
+      aContent->GetAttr(namespaceID, attrName, uriStr);
 
       if (!name->GetPrefix()) {
-        if (tagNamespaceURI.IsEmpty() && !uriStr.IsEmpty()) {
+        if (aTagNamespaceURI.IsEmpty() && !uriStr.IsEmpty()) {
           // If the element is in no namespace we need to add a xmlns
           // attribute to declare that. That xmlns attribute must not have a
           // prefix (see http://www.w3.org/TR/REC-xml-names/#dt-prefix), ie it
           // must declare the default namespace. We just found an xmlns
           // attribute that declares the default namespace to something
           // non-empty. We're going to ignore this attribute, for children we
           // will detect that we need to add it again and attributes aren't
           // affected by the default namespace.
@@ -655,351 +758,324 @@ nsXMLContentSerializer::AppendElementSta
         }
       }
       else {
         attrName->ToString(nameStr);
         PushNameSpaceDecl(nameStr, uriStr, aOriginalElement);
       }
     }
   }
+  return skipAttr;
+}
 
-  PRBool addNSAttr;
-    
-  MaybeAddNewline(aStr);
+
+PRBool
+nsXMLContentSerializer::IsJavaScript(nsIContent * aContent, nsIAtom* aAttrNameAtom,
+                                     PRInt32 aAttrNamespaceID, const nsAString& aValueString)
+{
+  PRInt32 namespaceID = aContent->GetNameSpaceID();
+  PRBool isHtml = aContent->IsNodeOfType(nsINode::eHTML);
+
+  if (aAttrNamespaceID == kNameSpaceID_None &&
+      (isHtml ||
+       namespaceID == kNameSpaceID_XUL ||
+       namespaceID == kNameSpaceID_SVG) &&
+      (aAttrNameAtom == nsGkAtoms::href ||
+       aAttrNameAtom == nsGkAtoms::src)) {
+
+    static const char kJavaScript[] = "javascript";
+    PRInt32 pos = aValueString.FindChar(':');
+    if (pos < (PRInt32)(sizeof kJavaScript - 1))
+        return PR_FALSE;
+    nsAutoString scheme(Substring(aValueString, 0, pos));
+    scheme.StripWhitespace();
+    if ((scheme.Length() == (sizeof kJavaScript - 1)) &&
+        scheme.EqualsIgnoreCase(kJavaScript))
+      return PR_TRUE;
+    else
+      return PR_FALSE;
+  }
 
-  addNSAttr = ConfirmPrefix(tagPrefix, tagNamespaceURI, aOriginalElement,
-                            PR_FALSE);
-  // Serialize the qualified name of the element
-  AppendToString(NS_LITERAL_STRING("<"), aStr);
-  if (!tagPrefix.IsEmpty()) {
-    AppendToString(tagPrefix, aStr);
-    AppendToString(NS_LITERAL_STRING(":"), aStr);
+  if (isHtml) {
+    return nsContentUtils::IsEventAttributeName(aAttrNameAtom, EventNameType_HTML);
+  }
+  else if (namespaceID == kNameSpaceID_XUL) {
+    return nsContentUtils::IsEventAttributeName(aAttrNameAtom, EventNameType_XUL);
+  }
+  else if (namespaceID == kNameSpaceID_SVG) {
+    return nsContentUtils::IsEventAttributeName(aAttrNameAtom,
+                                                EventNameType_SVGGraphic | EventNameType_SVGSVG);
   }
-  AppendToString(tagLocalName, aStr);
-    
+  return PR_FALSE;
+}
+
+
+void 
+nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
+                                            nsIDOMElement *aOriginalElement,
+                                            nsAString& aTagPrefix,
+                                            const nsAString& aTagNamespaceURI,
+                                            nsIAtom* aTagName,
+                                            nsAString& aStr,
+                                            PRUint32 aSkipAttr,
+                                            PRBool aAddNSAttr)
+{
+
+  nsAutoString nameStr, prefixStr, uriStr, valueStr;
+  nsAutoString xmlnsStr;
+  xmlnsStr.AssignLiteral(kXMLNS);
+  PRUint32 index, count;
+
   // If we had to add a new namespace declaration, serialize
   // and push it on the namespace stack
-  if (addNSAttr) {
-    if (tagPrefix.IsEmpty()) {
+  if (aAddNSAttr) {
+    if (aTagPrefix.IsEmpty()) {
       // Serialize default namespace decl
-      SerializeAttr(EmptyString(), xmlnsStr, tagNamespaceURI, aStr, PR_TRUE);
-    } else {
+      SerializeAttr(EmptyString(), xmlnsStr, aTagNamespaceURI, aStr, PR_TRUE);
+    }
+    else {
       // Serialize namespace decl
-      SerializeAttr(xmlnsStr, tagPrefix, tagNamespaceURI, aStr, PR_TRUE);
+      SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, PR_TRUE);
     }
-    PushNameSpaceDecl(tagPrefix, tagNamespaceURI, aOriginalElement);
+    PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
   }
 
+  count = aContent->GetAttrCount();
+
   // Now serialize each of the attributes
   // XXX Unfortunately we need a namespace manager to get
   // attribute URIs.
   for (index = 0; index < count; index++) {
-    if (skipAttr == index) {
+    if (aSkipAttr == index) {
         continue;
     }
 
-    const nsAttrName* name = content->GetAttrNameAt(index);
+    const nsAttrName* name = aContent->GetAttrNameAt(index);
     PRInt32 namespaceID = name->NamespaceID();
     nsIAtom* attrName = name->LocalName();
     nsIAtom* attrPrefix = name->GetPrefix();
 
     if (attrPrefix) {
       attrPrefix->ToString(prefixStr);
     }
     else {
       prefixStr.Truncate();
     }
 
-    addNSAttr = PR_FALSE;
+    PRBool addNSAttr = PR_FALSE;
     if (kNameSpaceID_XMLNS != namespaceID) {
       nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID, uriStr);
       addNSAttr = ConfirmPrefix(prefixStr, uriStr, aOriginalElement, PR_TRUE);
     }
     
-    content->GetAttr(namespaceID, attrName, valueStr);
+    aContent->GetAttr(namespaceID, attrName, valueStr);
     attrName->ToString(nameStr);
 
     // XXX Hack to get around the fact that MathML can add
     //     attributes starting with '-', which makes them
-    //     invalid XML.
+    //     invalid XML. see Bug 475518
     if (!nameStr.IsEmpty() && nameStr.First() == '-')
       continue;
 
-    if (namespaceID == kNameSpaceID_None) {
-      if (content->GetNameSpaceID() == kNameSpaceID_XHTML) {
-        if (IsShorthandAttr(attrName, content->Tag()) &&
-            valueStr.IsEmpty()) {
-          valueStr = nameStr;
-        }
-      }
-    }
-    SerializeAttr(prefixStr, nameStr, valueStr, aStr, PR_TRUE);
+    PRBool isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
+
+    SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS);
     
     if (addNSAttr) {
       NS_ASSERTION(!prefixStr.IsEmpty(),
                    "Namespaced attributes must have a prefix");
       SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, PR_TRUE);
       PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
     }
   }
+}
 
-  // We don't output a separate end tag for empty element
-  PRBool hasChildren;
+NS_IMETHODIMP 
+nsXMLContentSerializer::AppendElementStart(nsIDOMElement *aElement,
+                                           nsIDOMElement *aOriginalElement,
+                                           nsAString& aStr)
+{
+  NS_ENSURE_ARG(aElement);
+
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
+  if (!content) return NS_ERROR_FAILURE;
+
+  PRBool forceFormat;
+  if (!CheckElementStart(content, forceFormat, aStr)) {
+    return NS_OK;
+  }
+
+  nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
+  aElement->GetPrefix(tagPrefix);
+  aElement->GetLocalName(tagLocalName);
+  aElement->GetNamespaceURI(tagNamespaceURI);
+
+  PRUint32 skipAttr = ScanNamespaceDeclarations(content,
+                          aOriginalElement, tagNamespaceURI);
+
+  nsIAtom *name = content->Tag();
+  PRBool lineBreakBeforeOpen = LineBreakBeforeOpen(content->GetNameSpaceID(), name);
+
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+    if (mColPos && lineBreakBeforeOpen) {
+      AppendNewLineToString(aStr);
+    }
+    else {
+      MaybeAddNewlineForRootNode(aStr);
+    }
+    if (!mColPos) {
+      AppendIndentation(aStr);
+    }
+    else if (mAddSpace) {
+      AppendToString(PRUnichar(' '), aStr);
+      mAddSpace = PR_FALSE;
+    }
+  }
+  else if (mAddSpace) {
+    AppendToString(PRUnichar(' '), aStr);
+    mAddSpace = PR_FALSE;
+  }
+  else {
+    MaybeAddNewlineForRootNode(aStr);
+  }
+
+  // Always reset to avoid false newlines in case MaybeAddNewlineForRootNode wasn't
+  // called
+  mAddNewlineForRootNode = PR_FALSE;
+
+  PRBool addNSAttr;
+  addNSAttr = ConfirmPrefix(tagPrefix, tagNamespaceURI, aOriginalElement,
+                            PR_FALSE);
+
+  // Serialize the qualified name of the element
+  AppendToString(kLessThan, aStr);
+  if (!tagPrefix.IsEmpty()) {
+    AppendToString(tagPrefix, aStr);
+    AppendToString(NS_LITERAL_STRING(":"), aStr);
+  }
+  AppendToString(tagLocalName, aStr);
+
+  MaybeEnterInPreContent(content);
+
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+    IncrIndentation(name);
+  }
+
+  SerializeAttributes(content, aOriginalElement, tagPrefix, tagNamespaceURI,
+                      name, aStr, skipAttr, addNSAttr);
+
+  AppendEndOfElementStart(aOriginalElement, name, content->GetNameSpaceID(),
+                          aStr);
+
+  if ((mDoFormat || forceFormat) && !mPreLevel 
+    && !mDoRaw && LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
+    AppendNewLineToString(aStr);
+  }
+
+  AfterElementStart(content, aOriginalElement, aStr);
+
+  return NS_OK;
+}
+
+void 
+nsXMLContentSerializer::AppendEndOfElementStart(nsIDOMElement *aOriginalElement,
+                                                nsIAtom * aName,
+                                                PRInt32 aNamespaceID,
+                                                nsAString& aStr)
+{
+  // We don't output a separate end tag for empty elements
+  PRBool hasChildren = PR_FALSE;
   if (NS_FAILED(aOriginalElement->HasChildNodes(&hasChildren)) ||
       !hasChildren) {
-    AppendToString(NS_LITERAL_STRING("/>"), aStr);    
-    MaybeFlagNewline(aElement);
-  } else {
-    AppendToString(NS_LITERAL_STRING(">"), aStr);    
+    AppendToString(NS_LITERAL_STRING("/>"), aStr);
   }
-  
-  return NS_OK;
+  else {
+    AppendToString(kGreaterThan, aStr);
+  }
 }
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::AppendElementEnd(nsIDOMElement *aElement,
                                          nsAString& aStr)
 {
   NS_ENSURE_ARG(aElement);
 
-  // We don't output a separate end tag for empty element
-  nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aElement));
-  PRBool hasChildren;
-  if (NS_SUCCEEDED(node->HasChildNodes(&hasChildren)) && !hasChildren) {
+  nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
+  if (!content) return NS_ERROR_FAILURE;
+
+  PRBool forceFormat, outputElementEnd;
+  outputElementEnd = CheckElementEnd(content, forceFormat, aStr);
+
+  nsIAtom *name = content->Tag();
+
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+    DecrIndentation(name);
+  }
+
+  if (!outputElementEnd) {
     PopNameSpaceDeclsFor(aElement);
-  
+    MaybeFlagNewlineForRootNode(aElement);
     return NS_OK;
   }
-  
-  nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));
-  if (!content) return NS_ERROR_FAILURE;
 
   nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
   
   aElement->GetPrefix(tagPrefix);
   aElement->GetLocalName(tagLocalName);
   aElement->GetNamespaceURI(tagNamespaceURI);
 
 #ifdef DEBUG
   PRBool debugNeedToPushNamespace =
 #endif
   ConfirmPrefix(tagPrefix, tagNamespaceURI, aElement, PR_FALSE);
   NS_ASSERTION(!debugNeedToPushNamespace, "Can't push namespaces in closing tag!");
 
-  AppendToString(NS_LITERAL_STRING("</"), aStr);
+  if ((mDoFormat || forceFormat) && !mPreLevel && !mDoRaw) {
+
+    PRBool lineBreakBeforeClose = LineBreakBeforeClose(content->GetNameSpaceID(), name);
+
+    if (mColPos && lineBreakBeforeClose) {
+      AppendNewLineToString(aStr);
+    }
+    if (!mColPos) {
+      AppendIndentation(aStr);
+    }
+    else if (mAddSpace) {
+      AppendToString(PRUnichar(' '), aStr);
+      mAddSpace = PR_FALSE;
+    }
+  }
+  else if (mAddSpace) {
+    AppendToString(PRUnichar(' '), aStr);
+    mAddSpace = PR_FALSE;
+  }
+
+  AppendToString(kEndTag, aStr);
   if (!tagPrefix.IsEmpty()) {
     AppendToString(tagPrefix, aStr);
     AppendToString(NS_LITERAL_STRING(":"), aStr);
   }
   AppendToString(tagLocalName, aStr);
-  AppendToString(NS_LITERAL_STRING(">"), aStr);
-  MaybeFlagNewline(aElement);
-  
-  PopNameSpaceDeclsFor(aElement);
-  
-  return NS_OK;
-}
-
-void
-nsXMLContentSerializer::AppendToString(const PRUnichar* aStr,
-                                       PRInt32 aLength,
-                                       nsAString& aOutputStr)
-{
-  PRInt32 length = (aLength == -1) ? nsCRT::strlen(aStr) : aLength;
-  
-  aOutputStr.Append(aStr, length);
-}
+  AppendToString(kGreaterThan, aStr);
 
-void 
-nsXMLContentSerializer::AppendToString(const PRUnichar aChar,
-                                       nsAString& aOutputStr)
-{
-  aOutputStr.Append(aChar);
-}
+  PopNameSpaceDeclsFor(aElement);
 
-static const PRUint16 kGTVal = 62;
-static const char* kEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "&amp;", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "&lt;", "", "&gt;"
-};
-
-static const char* kAttrEntities[] = {
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "&quot;", "", "", "", "&amp;", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "", "", "",
-  "&lt;", "", "&gt;"
-};
+  MaybeLeaveFromPreContent(content);
 
-void
-nsXMLContentSerializer::AppendToString(const nsAString& aStr,
-                                       nsAString& aOutputStr,
-                                       PRBool aTranslateEntities,
-                                       PRBool aIncrColumn)
-{
-  if (aTranslateEntities) {
-    nsReadingIterator<PRUnichar> done_reading;
-    aStr.EndReading(done_reading);
-
-    // for each chunk of |aString|...
-    PRUint32 advanceLength = 0;
-    nsReadingIterator<PRUnichar> iter;
-
-    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
-
-    for (aStr.BeginReading(iter); 
-         iter != done_reading; 
-         iter.advance(PRInt32(advanceLength))) {
-      PRUint32 fragmentLength = iter.size_forward();
-      const PRUnichar* c = iter.get();
-      const PRUnichar* fragmentStart = c;
-      const PRUnichar* fragmentEnd = c + fragmentLength;
-      const char* entityText = nsnull;
-
-      advanceLength = 0;
-      // for each character in this chunk, check if it
-      // needs to be replaced
-      for (; c < fragmentEnd; c++, advanceLength++) {
-        PRUnichar val = *c;
-        if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
-          entityText = entityTable[val];
-          break;
-        }
-      }
-
-      aOutputStr.Append(fragmentStart, advanceLength);
-      if (entityText) {
-        AppendASCIItoUTF16(entityText, aOutputStr);
-        advanceLength++;
-      }
-    }
-
-    return;
+  if ((mDoFormat || forceFormat) && !mPreLevel
+      && !mDoRaw && LineBreakAfterClose(content->GetNameSpaceID(), name)) {
+    AppendNewLineToString(aStr);
   }
-  
-  aOutputStr.Append(aStr);
-}
-
-PRBool
-nsXMLContentSerializer::IsShorthandAttr(const nsIAtom* aAttrName,
-                                        const nsIAtom* aElementName)
-{
-  // checked
-  if ((aAttrName == nsGkAtoms::checked) &&
-      (aElementName == nsGkAtoms::input)) {
-    return PR_TRUE;
+  else {
+    MaybeFlagNewlineForRootNode(aElement);
   }
 
-  // compact
-  if ((aAttrName == nsGkAtoms::compact) &&
-      (aElementName == nsGkAtoms::dir || 
-       aElementName == nsGkAtoms::dl ||
-       aElementName == nsGkAtoms::menu ||
-       aElementName == nsGkAtoms::ol ||
-       aElementName == nsGkAtoms::ul)) {
-    return PR_TRUE;
-  }
-
-  // declare
-  if ((aAttrName == nsGkAtoms::declare) &&
-      (aElementName == nsGkAtoms::object)) {
-    return PR_TRUE;
-  }
-
-  // defer
-  if ((aAttrName == nsGkAtoms::defer) &&
-      (aElementName == nsGkAtoms::script)) {
-    return PR_TRUE;
-  }
-
-  // disabled
-  if ((aAttrName == nsGkAtoms::disabled) &&
-      (aElementName == nsGkAtoms::button ||
-       aElementName == nsGkAtoms::input ||
-       aElementName == nsGkAtoms::optgroup ||
-       aElementName == nsGkAtoms::option ||
-       aElementName == nsGkAtoms::select ||
-       aElementName == nsGkAtoms::textarea)) {
-    return PR_TRUE;
-  }
-
-  // ismap
-  if ((aAttrName == nsGkAtoms::ismap) &&
-      (aElementName == nsGkAtoms::img ||
-       aElementName == nsGkAtoms::input)) {
-    return PR_TRUE;
-  }
-
-  // multiple
-  if ((aAttrName == nsGkAtoms::multiple) &&
-      (aElementName == nsGkAtoms::select)) {
-    return PR_TRUE;
-  }
+  AfterElementEnd(content, aStr);
 
-  // noresize
-  if ((aAttrName == nsGkAtoms::noresize) &&
-      (aElementName == nsGkAtoms::frame)) {
-    return PR_TRUE;
-  }
-
-  // noshade
-  if ((aAttrName == nsGkAtoms::noshade) &&
-      (aElementName == nsGkAtoms::hr)) {
-    return PR_TRUE;
-  }
-
-  // nowrap
-  if ((aAttrName == nsGkAtoms::nowrap) &&
-      (aElementName == nsGkAtoms::td ||
-       aElementName == nsGkAtoms::th)) {
-    return PR_TRUE;
-  }
-
-  // readonly
-  if ((aAttrName == nsGkAtoms::readonly) &&
-      (aElementName == nsGkAtoms::input ||
-       aElementName == nsGkAtoms::textarea)) {
-    return PR_TRUE;
-  }
-
-  // selected
-  if ((aAttrName == nsGkAtoms::selected) &&
-      (aElementName == nsGkAtoms::option)) {
-    return PR_TRUE;
-  }
-
-  return PR_FALSE;
-}
-
-void
-nsXMLContentSerializer::MaybeAddNewline(nsAString& aStr)
-{
-  if (mAddNewline) {
-    aStr.Append(mLineBreak);
-    mAddNewline = PR_FALSE;
-  }
-}
-
-void
-nsXMLContentSerializer::MaybeFlagNewline(nsIDOMNode* aNode)
-{
-  nsCOMPtr<nsIDOMNode> parent;
-  aNode->GetParentNode(getter_AddRefs(parent));
-  if (parent) {
-    PRUint16 type;
-    parent->GetNodeType(&type);
-    mAddNewline = type == nsIDOMNode::DOCUMENT_NODE;
-  }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument,
                                             nsAString& aStr)
 {
   NS_ENSURE_ARG_POINTER(aDocument);
 
@@ -1030,37 +1106,647 @@ nsXMLContentSerializer::AppendDocumentSt
   }
 #endif
 
   if (!standalone.IsEmpty()) {
     aStr += NS_LITERAL_STRING(" standalone=\"") + standalone + endQuote;
   }
 
   aStr.AppendLiteral("?>");
-  mAddNewline = PR_TRUE;
+  mAddNewlineForRootNode = PR_TRUE;
 
   return NS_OK;
 }
 
+PRBool
+nsXMLContentSerializer::CheckElementStart(nsIContent * aContent,
+                                          PRBool & aForceFormat,
+                                          nsAString& aStr)
+{
+  aForceFormat = PR_FALSE;
+  return PR_TRUE;
+}
+
+PRBool
+nsXMLContentSerializer::CheckElementEnd(nsIContent * aContent,
+                                        PRBool & aForceFormat,
+                                        nsAString& aStr)
+{
+  // We don't output a separate end tag for empty element
+  nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
+  PRBool hasChildren;
+  if (NS_SUCCEEDED(node->HasChildNodes(&hasChildren)) && !hasChildren) {
+    return PR_FALSE;
+  }
+
+  aForceFormat = PR_FALSE;
+  return PR_TRUE;
+}
+
+
+void
+nsXMLContentSerializer::AppendToString(const PRUnichar* aStr,
+                                       PRInt32 aLength,
+                                       nsAString& aOutputStr)
+{
+  PRInt32 length = (aLength == -1) ? nsCRT::strlen(aStr) : aLength;
+
+  mColPos += length;
+
+  aOutputStr.Append(aStr, length);
+}
+
+void 
+nsXMLContentSerializer::AppendToString(const PRUnichar aChar,
+                                       nsAString& aOutputStr)
+{
+  mColPos += 1;
+  aOutputStr.Append(aChar);
+}
+
+void
+nsXMLContentSerializer::AppendToString(const nsAString& aStr,
+                                       nsAString& aOutputStr)
+{
+  mColPos += aStr.Length();
+  aOutputStr.Append(aStr);
+}
+
+
+static const PRUint16 kGTVal = 62;
+static const char* kEntities[] = {
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "&amp;", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "&lt;", "", "&gt;"
+};
+
+static const char* kAttrEntities[] = {
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "&quot;", "", "", "", "&amp;", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "", "", "",
+  "&lt;", "", "&gt;"
+};
+
+void
+nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
+                                                   nsAString& aOutputStr)
+{
+  nsReadingIterator<PRUnichar> done_reading;
+  aStr.EndReading(done_reading);
+
+  // for each chunk of |aString|...
+  PRUint32 advanceLength = 0;
+  nsReadingIterator<PRUnichar> iter;
+
+  const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
+
+  for (aStr.BeginReading(iter);
+       iter != done_reading;
+       iter.advance(PRInt32(advanceLength))) {
+    PRUint32 fragmentLength = iter.size_forward();
+    const PRUnichar* c = iter.get();
+    const PRUnichar* fragmentStart = c;
+    const PRUnichar* fragmentEnd = c + fragmentLength;
+    const char* entityText = nsnull;
+
+    advanceLength = 0;
+    // for each character in this chunk, check if it
+    // needs to be replaced
+    for (; c < fragmentEnd; c++, advanceLength++) {
+      PRUnichar val = *c;
+      if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
+        entityText = entityTable[val];
+        break;
+      }
+    }
+
+    aOutputStr.Append(fragmentStart, advanceLength);
+    if (entityText) {
+      AppendASCIItoUTF16(entityText, aOutputStr);
+      advanceLength++;
+    }
+  }
+}
+
+void
+nsXMLContentSerializer::MaybeAddNewlineForRootNode(nsAString& aStr)
+{
+  if (mAddNewlineForRootNode) {
+    AppendNewLineToString(aStr);
+  }
+}
+
+void
+nsXMLContentSerializer::MaybeFlagNewlineForRootNode(nsIDOMNode* aNode)
+{
+  nsCOMPtr<nsIDOMNode> parent;
+  aNode->GetParentNode(getter_AddRefs(parent));
+  if (parent) {
+    PRUint16 type;
+    parent->GetNodeType(&type);
+    mAddNewlineForRootNode = type == nsIDOMNode::DOCUMENT_NODE;
+  }
+}
+
+void
+nsXMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
+{
+  // support of the xml:space attribute
+  if (aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
+    nsAutoString space;
+    aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
+    if (space.EqualsLiteral("preserve"))
+      ++mPreLevel;
+  }
+}
+
+void
+nsXMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
+{
+  // support of the xml:space attribute
+  if (aNode->HasAttr(kNameSpaceID_XML, nsGkAtoms::space)) {
+    nsAutoString space;
+    aNode->GetAttr(kNameSpaceID_XML, nsGkAtoms::space, space);
+    if (space.EqualsLiteral("preserve"))
+      --mPreLevel;
+  }
+}
+
+void
+nsXMLContentSerializer::AppendNewLineToString(nsAString& aStr)
+{
+  AppendToString(mLineBreak, aStr);
+  mMayIgnoreLineBreakSequence = PR_TRUE;
+  mColPos = 0;
+  mAddSpace = PR_FALSE;
+  mIsIndentationAddedOnCurrentLine = PR_FALSE;
+}
+
+void
+nsXMLContentSerializer::AppendIndentation(nsAString& aStr)
+{
+  mIsIndentationAddedOnCurrentLine = PR_TRUE;
+  AppendToString(mIndent, aStr);
+  mAddSpace = PR_FALSE;
+  mMayIgnoreLineBreakSequence = PR_FALSE;
+}
+
+void
+nsXMLContentSerializer::IncrIndentation(nsIAtom* aName)
+{
+  // we want to keep the source readable
+  if(mDoWrap && mIndent.Length() >= mMaxColumn - MIN_INDENTED_LINE_LENGTH) {
+    ++mIndentOverflow;
+  }
+  else {
+    mIndent.AppendLiteral(INDENT_STRING);
+  }
+}
+
+void
+nsXMLContentSerializer::DecrIndentation(nsIAtom* aName)
+{
+  if(mIndentOverflow)
+    --mIndentOverflow;
+  else
+    mIndent.Cut(0, INDENT_STRING_LENGTH);
+}
+
+PRBool
+nsXMLContentSerializer::LineBreakBeforeOpen(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+  return mAddSpace;
+}
+
+PRBool 
+nsXMLContentSerializer::LineBreakAfterOpen(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+  return PR_FALSE;
+}
+
+PRBool 
+nsXMLContentSerializer::LineBreakBeforeClose(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+  return mAddSpace;
+}
+
+PRBool 
+nsXMLContentSerializer::LineBreakAfterClose(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+  return PR_FALSE;
+}
+
 void
 nsXMLContentSerializer::AppendToStringConvertLF(const nsAString& aStr,
-                                                 nsAString& aOutputStr)
+                                                nsAString& aOutputStr)
+{
+  if (mDoRaw) {
+    nsAutoString str (aStr);
+    PRInt32 lastNewlineOffset = str.RFindChar('\n');
+    AppendToString(aStr, aOutputStr);
+
+    if (lastNewlineOffset != kNotFound) {
+      // the string contains at least a line break,
+      // so we should update the mColPos property with
+      // the number of characters between the last line
+      // break and the end of the string
+      mColPos = aStr.Length() - lastNewlineOffset;
+    }
+
+    mIsIndentationAddedOnCurrentLine = (mColPos != 0);
+  }
+  else {
+    // Convert line-endings to mLineBreak
+    PRUint32 start = 0;
+    PRUint32 theLen = aStr.Length();
+    while (start < theLen) {
+      PRInt32 eol = aStr.FindChar('\n', start);
+      if (eol == kNotFound) {
+        nsDependentSubstring dataSubstring(aStr, start, theLen - start);
+        AppendToString(dataSubstring, aOutputStr);
+        start = theLen;
+        // if there was a line break before this substring
+        // AppendNewLineToString was called, so we should reverse
+        // this flag
+        mMayIgnoreLineBreakSequence = PR_FALSE;
+      }
+      else {
+        nsDependentSubstring dataSubstring(aStr, start, eol - start);
+        AppendToString(dataSubstring, aOutputStr);
+        AppendNewLineToString(aOutputStr);
+        start = eol + 1;
+      }
+    }
+  }
+}
+
+void
+nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
+                        nsASingleFragmentString::const_char_iterator &aPos,
+                        const nsASingleFragmentString::const_char_iterator aEnd,
+                        const nsASingleFragmentString::const_char_iterator aSequenceStart,
+                        PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
+                        nsAString &aOutputStr)
 {
-  // Convert line-endings to mLineBreak
-  PRUint32 start = 0;
-  PRUint32 theLen = aStr.Length();
-  while (start < theLen) {
-    PRInt32 eol = aStr.FindChar('\n', start);
-    if (eol == kNotFound) {
-      nsDependentSubstring dataSubstring(aStr, start, theLen - start);
-      AppendToString(dataSubstring, aOutputStr);
-      start = theLen;
+  // Handle the complete sequence of whitespace.
+  // Continue to iterate until we find the first non-whitespace char.
+  // Updates "aPos" to point to the first unhandled char.
+  // Also updates the aMayIgnoreStartOfLineWhitespaceSequence flag,
+  // as well as the other "global" state flags.
+
+  PRBool sawBlankOrTab = PR_FALSE;
+  PRBool leaveLoop = PR_FALSE;
+
+  do {
+    switch (*aPos) {
+      case ' ':
+      case '\t':
+        sawBlankOrTab = PR_TRUE;
+        // no break
+      case '\n':
+        ++aPos;
+        // do not increase mColPos,
+        // because we will reduce the whitespace to a single char
+        break;
+      default:
+        leaveLoop = PR_TRUE;
+        break;
+    }
+  } while (!leaveLoop && aPos < aEnd);
+
+  if (mAddSpace) {
+    // if we had previously been asked to add space,
+    // our situation has not changed
+  }
+  else if (!sawBlankOrTab && mMayIgnoreLineBreakSequence) {
+    // nothing to do in the case where line breaks have already been added
+    // before the call of AppendToStringWrapped
+    // and only if we found line break in the sequence
+    mMayIgnoreLineBreakSequence = PR_FALSE;
+  }
+  else if (aMayIgnoreStartOfLineWhitespaceSequence) {
+    // nothing to do
+    aMayIgnoreStartOfLineWhitespaceSequence = PR_FALSE;
+  }
+  else {
+    if (sawBlankOrTab) {
+      if (mDoWrap && mColPos + 1 >= mMaxColumn) {
+        // no much sense in delaying, we only have one slot left,
+        // let's write a break now
+        aOutputStr.Append(mLineBreak);
+        mColPos = 0;
+        mIsIndentationAddedOnCurrentLine = PR_FALSE;
+        mMayIgnoreLineBreakSequence = PR_TRUE;
+      }
+      else {
+        // do not write out yet, we may write out either a space or a linebreak
+        // let's delay writing it out until we know more
+        mAddSpace = PR_TRUE;
+        ++mColPos; // eat a slot of available space
+      }
     }
     else {
-      nsDependentSubstring dataSubstring(aStr, start, eol - start);
-      AppendToString(dataSubstring, aOutputStr);
-      AppendToString(mLineBreak, aOutputStr);
-      start = eol + 1;
-      if (start == theLen)
-        mColPos = 0;
+      // Asian text usually does not contain spaces, therefore we should not
+      // transform a linebreak into a space.
+      // Since we only saw linebreaks, but no spaces or tabs,
+      // let's write a linebreak now.
+      AppendNewLineToString(aOutputStr);
     }
   }
 }
+
+void
+nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
+                        nsASingleFragmentString::const_char_iterator &aPos,
+                        const nsASingleFragmentString::const_char_iterator aEnd,
+                        const nsASingleFragmentString::const_char_iterator aSequenceStart,
+                        PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
+                        PRBool &aSequenceStartAfterAWhiteSpace,
+                        nsAString& aOutputStr)
+{
+  mMayIgnoreLineBreakSequence = PR_FALSE;
+  aMayIgnoreStartOfLineWhitespaceSequence = PR_FALSE;
+
+  // Handle the complete sequence of non-whitespace in this block
+  // Iterate until we find the first whitespace char or an aEnd condition
+  // Updates "aPos" to point to the first unhandled char.
+  // Also updates the aMayIgnoreStartOfLineWhitespaceSequence flag,
+  // as well as the other "global" state flags.
+
+  PRBool thisSequenceStartsAtBeginningOfLine = !mColPos;
+  PRBool onceAgainBecauseWeAddedBreakInFront = PR_FALSE;
+  PRBool foundWhitespaceInLoop;
+  PRInt32 length, colPos;
+
+  do {
+
+    if (mColPos) {
+      colPos = mColPos;
+    }
+    else {
+      if (mDoFormat && !mPreLevel && !onceAgainBecauseWeAddedBreakInFront) {
+        colPos = mIndent.Length();
+      }
+      else
+        colPos = 0;
+    }
+    foundWhitespaceInLoop = PR_FALSE;
+    length = 0;
+    // we iterate until the next whitespace character
+    // or until we reach the maximum of character per line
+    // or until the end of the string to add.
+    do {
+      if (*aPos == ' ' || *aPos == '\t' || *aPos == '\n') {
+        foundWhitespaceInLoop = PR_TRUE;
+        break;
+      }
+
+      ++aPos;
+      ++length;
+    } while ( (!mDoWrap || colPos + length < mMaxColumn) && aPos < aEnd);
+
+    // in the case we don't reached the end of the string, but we reached the maxcolumn,
+    // we see if there is a whitespace after the maxcolumn
+    // if yes, then we can append directly the string instead of
+    // appending a new line etc.
+    if (*aPos == ' ' || *aPos == '\t' || *aPos == '\n') {
+      foundWhitespaceInLoop = PR_TRUE;
+    }
+
+    if (aPos == aEnd || foundWhitespaceInLoop) {
+      // there is enough room for the complete block we found
+      if (mDoFormat && !mColPos) {
+        AppendIndentation(aOutputStr);
+      }
+      else if (mAddSpace) {
+        aOutputStr.Append(PRUnichar(' '));
+        mAddSpace = PR_FALSE;
+      }
+
+      mColPos += length;
+      aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
+
+      // We have not yet reached the max column, we will continue to
+      // fill the current line in the next outer loop iteration
+      // (this one in AppendToStringWrapped)
+      // make sure we return in this outer loop
+      onceAgainBecauseWeAddedBreakInFront = PR_FALSE;
+    }
+    else { // we reach the max column
+      if (!thisSequenceStartsAtBeginningOfLine &&
+          (mAddSpace || (!mDoFormat && aSequenceStartAfterAWhiteSpace))) { 
+          // when !mDoFormat, mAddSpace is not used, mAddSpace is always false
+          // so, in the case where mDoWrap && !mDoFormat, if we want to enter in this condition...
+
+        // We can avoid to wrap. We try to add the whole block 
+        // in an empty new line
+
+        AppendNewLineToString(aOutputStr);
+        aPos = aSequenceStart;
+        thisSequenceStartsAtBeginningOfLine = PR_TRUE;
+        onceAgainBecauseWeAddedBreakInFront = PR_TRUE;
+      }
+      else {
+        // we must wrap
+        onceAgainBecauseWeAddedBreakInFront = PR_FALSE;
+        PRBool foundWrapPosition = PR_FALSE;
+        PRInt32 wrapPosition;
+
+        nsILineBreaker *lineBreaker = nsContentUtils::LineBreaker();
+
+        wrapPosition = lineBreaker->Prev(aSequenceStart,
+                                         (aEnd - aSequenceStart),
+                                         (aPos - aSequenceStart) + 1);
+        if (wrapPosition != NS_LINEBREAKER_NEED_MORE_TEXT) {
+          foundWrapPosition = PR_TRUE;
+        }
+        else {
+          wrapPosition = lineBreaker->Next(aSequenceStart,
+                                           (aEnd - aSequenceStart),
+                                           (aPos - aSequenceStart));
+          if (wrapPosition != NS_LINEBREAKER_NEED_MORE_TEXT) {
+            foundWrapPosition = PR_TRUE;
+          }
+        }
+
+        if (foundWrapPosition) {
+          if (!mColPos && mDoFormat) {
+            AppendIndentation(aOutputStr);
+          }
+          else if (mAddSpace) {
+            aOutputStr.Append(PRUnichar(' '));
+            mAddSpace = PR_FALSE;
+          }
+          aOutputStr.Append(aSequenceStart, wrapPosition);
+
+          AppendNewLineToString(aOutputStr);
+          aPos = aSequenceStart + wrapPosition;
+          aMayIgnoreStartOfLineWhitespaceSequence = PR_TRUE;
+        }
+        else {
+          // try some simple fallback logic
+          // go forward up to the next whitespace position,
+          // in the worst case this will be all the rest of the data
+
+          // we update the mColPos variable with the length of
+          // the part already parsed.
+          mColPos += length;
+
+          // now try to find the next whitespace
+          do {
+            if (*aPos == ' ' || *aPos == '\t' || *aPos == '\n') {
+              break;
+            }
+
+            ++aPos;
+            ++mColPos;
+          } while (aPos < aEnd);
+
+          if (mAddSpace) {
+            aOutputStr.Append(PRUnichar(' '));
+            mAddSpace = PR_FALSE;
+          }
+          aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
+        }
+      }
+      aSequenceStartAfterAWhiteSpace = PR_FALSE;
+    }
+  } while (onceAgainBecauseWeAddedBreakInFront);
+}
+
+void 
+nsXMLContentSerializer::AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
+                                               nsAString& aOutputStr)
+{
+  nsASingleFragmentString::const_char_iterator pos, end, sequenceStart;
+
+  aStr.BeginReading(pos);
+  aStr.EndReading(end);
+
+  PRBool sequenceStartAfterAWhitespace = PR_FALSE;
+  if (pos < end) {
+    nsAString::const_char_iterator end2;
+    aOutputStr.EndReading(end2);
+    --end2;
+    if (*end2 == ' ' || *end2 == '\n' || *end2 == '\t') {
+      sequenceStartAfterAWhitespace = PR_TRUE;
+    }
+  }
+
+  // if the current line already has text on it, such as a tag,
+  // leading whitespace is significant
+  PRBool mayIgnoreStartOfLineWhitespaceSequence =
+    (!mColPos || (mIsIndentationAddedOnCurrentLine &&
+                  sequenceStartAfterAWhitespace &&
+                  mColPos == mIndent.Length()));
+
+  while (pos < end) {
+    sequenceStart = pos;
+
+    // if beginning of a whitespace sequence
+    if (*pos == ' ' || *pos == '\n' || *pos == '\t') {
+      AppendFormatedWrapped_WhitespaceSequence(pos, end, sequenceStart,
+        mayIgnoreStartOfLineWhitespaceSequence, aOutputStr);
+    }
+    else { // any other non-whitespace char
+      AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
+        mayIgnoreStartOfLineWhitespaceSequence, sequenceStartAfterAWhitespace, aOutputStr);
+    }
+  }
+}
+
+void
+nsXMLContentSerializer::AppendWrapped_WhitespaceSequence(
+                        nsASingleFragmentString::const_char_iterator &aPos,
+                        const nsASingleFragmentString::const_char_iterator aEnd,
+                        const nsASingleFragmentString::const_char_iterator aSequenceStart,
+                        nsAString &aOutputStr)
+{
+  // Handle the complete sequence of whitespace.
+  // Continue to iterate until we find the first non-whitespace char.
+  // Updates "aPos" to point to the first unhandled char.
+  mAddSpace = PR_FALSE;
+  mIsIndentationAddedOnCurrentLine = PR_FALSE;
+
+  PRBool leaveLoop = PR_FALSE;
+  nsASingleFragmentString::const_char_iterator lastPos = aPos;
+
+  do {
+    switch (*aPos) {
+      case ' ':
+      case '\t':
+        // if there are too many spaces on a line, we wrap
+        if (mColPos >= mMaxColumn) {
+          if (lastPos != aPos) {
+            aOutputStr.Append(lastPos, aPos - lastPos);
+          }
+          AppendToString(mLineBreak, aOutputStr);
+          mColPos = 0;
+          lastPos = aPos;
+        }
+
+        ++mColPos;
+        ++aPos;
+        break;
+      case '\n':
+        if (lastPos != aPos) {
+          aOutputStr.Append(lastPos, aPos - lastPos);
+        }
+        AppendToString(mLineBreak, aOutputStr);
+        mColPos = 0;
+        ++aPos;
+        lastPos = aPos;
+        break;
+      default:
+        leaveLoop = PR_TRUE;
+        break;
+    }
+  } while (!leaveLoop && aPos < aEnd);
+
+  if (lastPos != aPos) {
+    aOutputStr.Append(lastPos, aPos - lastPos);
+  }
+}
+
+void 
+nsXMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aStr,
+                                               nsAString& aOutputStr)
+{
+  nsASingleFragmentString::const_char_iterator pos, end, sequenceStart;
+
+  aStr.BeginReading(pos);
+  aStr.EndReading(end);
+
+  // not used in this case, but needed by AppendWrapped_NonWhitespaceSequence
+  PRBool mayIgnoreStartOfLineWhitespaceSequence = PR_FALSE;
+  mMayIgnoreLineBreakSequence = PR_FALSE;
+
+  PRBool sequenceStartAfterAWhitespace = PR_FALSE;
+  if (pos < end) {
+    nsAString::const_char_iterator end2;
+    aOutputStr.EndReading(end2);
+    --end2;
+    if (*end2 == ' ' || *end2 == '\n' || *end2 == '\t') {
+      sequenceStartAfterAWhitespace = PR_TRUE;
+    }
+  }
+
+  while (pos < end) {
+    sequenceStart = pos;
+
+    // if beginning of a whitespace sequence
+    if (*pos == ' ' || *pos == '\n' || *pos == '\t') {
+      sequenceStartAfterAWhitespace = PR_TRUE;
+      AppendWrapped_WhitespaceSequence(pos, end, sequenceStart, aOutputStr);
+    }
+    else { // any other non-whitespace char
+      AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
+        mayIgnoreStartOfLineWhitespaceSequence, sequenceStartAfterAWhitespace, aOutputStr);
+    }
+  }
+}
--- a/content/base/src/nsXMLContentSerializer.h
+++ b/content/base/src/nsXMLContentSerializer.h
@@ -15,16 +15,17 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Laurent Jouanneau <laurent.jouanneau@disruptive-innovations.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -39,21 +40,26 @@
  * nsIContentSerializer implementation that can be used with an
  * nsIDocumentEncoder to convert an XML DOM to an XML string that
  * could be parsed into more or less the original DOM.
  */
 
 #ifndef nsXMLContentSerializer_h__
 #define nsXMLContentSerializer_h__
 
+#include "nsIContent.h"
 #include "nsIContentSerializer.h"
 #include "nsISupportsUtils.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsString.h"
+#include "nsIParser.h"
+
+#define kIndentStr NS_LITERAL_STRING("  ")
+#define kEndTag NS_LITERAL_STRING("</")
 
 class nsIDOMNode;
 class nsIAtom;
 
 class nsXMLContentSerializer : public nsIContentSerializer {
  public:
   nsXMLContentSerializer();
   virtual ~nsXMLContentSerializer();
@@ -90,30 +96,106 @@ class nsXMLContentSerializer : public ns
                               nsAString& aStr);
 
   NS_IMETHOD Flush(nsAString& aStr) { return NS_OK; }
 
   NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument,
                                  nsAString& aStr);
 
  protected:
+
+  /**
+   * Appends a PRUnichar string and increments the column position
+   */
   virtual void AppendToString(const PRUnichar* aStr,
                               PRInt32 aLength,
                               nsAString& aOutputStr);
-  virtual void AppendToString(const PRUnichar aChar, nsAString& aOutputStr);
+
+  /**
+   * Appends a PRUnichar character and increments the column position
+   */
+  virtual void AppendToString(const PRUnichar aChar,
+                              nsAString& aOutputStr);
+
+  /**
+   * Appends a nsAString string and increments the column position
+   */
   virtual void AppendToString(const nsAString& aStr,
-                              nsAString& aOutputStr,
-                              PRBool aTranslateEntities = PR_FALSE,
-                              PRBool aIncrColumn = PR_TRUE);
-  nsresult AppendTextData(nsIDOMNode* aNode, 
+                              nsAString& aOutputStr);
+
+  /**
+   * Appends a string by replacing all line-endings
+   * by mLineBreak, except in the case of raw output.
+   * It increments the column position.
+   */
+  virtual void AppendToStringConvertLF(const nsAString& aStr,
+                                       nsAString& aOutputStr);
+
+  /**
+   * Appends a string by wrapping it when necessary.
+   * It updates the column position.
+   */
+  virtual void AppendToStringWrapped(const nsASingleFragmentString& aStr,
+                                     nsAString& aOutputStr);
+
+  /**
+   * Appends a string by formating and wrapping it when necessary
+   * It updates the column position.
+   */
+  virtual void AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
+                                             nsAString& aOutputStr);
+
+  // used by AppendToStringWrapped
+  void AppendWrapped_WhitespaceSequence(
+          nsASingleFragmentString::const_char_iterator &aPos,
+          const nsASingleFragmentString::const_char_iterator aEnd,
+          const nsASingleFragmentString::const_char_iterator aSequenceStart,
+          nsAString &aOutputStr);
+
+  // used by AppendToStringFormatedWrapped
+  void AppendFormatedWrapped_WhitespaceSequence(
+          nsASingleFragmentString::const_char_iterator &aPos,
+          const nsASingleFragmentString::const_char_iterator aEnd,
+          const nsASingleFragmentString::const_char_iterator aSequenceStart,
+          PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
+          nsAString &aOutputStr);
+
+  // used by AppendToStringWrapped and AppendToStringFormatedWrapped
+  void AppendWrapped_NonWhitespaceSequence(
+          nsASingleFragmentString::const_char_iterator &aPos,
+          const nsASingleFragmentString::const_char_iterator aEnd,
+          const nsASingleFragmentString::const_char_iterator aSequenceStart,
+          PRBool &aMayIgnoreStartOfLineWhitespaceSequence,
+          PRBool &aSequenceStartAfterAWhiteSpace,
+          nsAString &aOutputStr);
+
+  /**
+   * add mLineBreak to the string
+   * It updates the column position and other flags.
+   */
+  virtual void AppendNewLineToString(nsAString& aOutputStr);
+
+
+  /**
+   * Appends a string by translating entities
+   * It doesn't increment the column position
+   */
+  virtual void AppendAndTranslateEntities(const nsAString& aStr,
+                                          nsAString& aOutputStr);
+
+  /**
+   * retrieve the text content of the node and append it to the given string
+   * It doesn't increment the column position
+   */
+  nsresult AppendTextData(nsIDOMNode* aNode,
                           PRInt32 aStartOffset,
                           PRInt32 aEndOffset,
                           nsAString& aStr,
-                          PRBool aTranslateEntities,
-                          PRBool aIncrColumn);
+                          PRBool aTranslateEntities);
+
   virtual nsresult PushNameSpaceDecl(const nsAString& aPrefix,
                                      const nsAString& aURI,
                                      nsIDOMElement* aOwner);
   void PopNameSpaceDeclsFor(nsIDOMElement* aOwner);
 
   /**
    * The problem that ConfirmPrefix fixes is that anyone can insert nodes
    * through the DOM that have a namespace URI and a random or empty or
@@ -135,34 +217,130 @@ class nsXMLContentSerializer : public ns
   PRBool ConfirmPrefix(nsAString& aPrefix,
                        const nsAString& aURI,
                        nsIDOMElement* aElement,
                        PRBool aIsAttribute);
   /**
    * GenerateNewPrefix generates a new prefix and writes it to aPrefix
    */
   void GenerateNewPrefix(nsAString& aPrefix);
+
+  PRUint32 ScanNamespaceDeclarations(nsIContent* aContent,
+                                     nsIDOMElement *aOriginalElement,
+                                     const nsAString& aTagNamespaceURI);
+
+  virtual void SerializeAttributes(nsIContent* aContent,
+                                   nsIDOMElement *aOriginalElement,
+                                   nsAString& aTagPrefix,
+                                   const nsAString& aTagNamespaceURI,
+                                   nsIAtom* aTagName,
+                                   nsAString& aStr,
+                                   PRUint32 aSkipAttr,
+                                   PRBool aAddNSAttr);
+
   void SerializeAttr(const nsAString& aPrefix,
                      const nsAString& aName,
                      const nsAString& aValue,
                      nsAString& aStr,
                      PRBool aDoEscapeEntities);
-  PRBool IsShorthandAttr(const nsIAtom* aAttrName,
-                         const nsIAtom* aElementName);
+
+  virtual PRBool IsJavaScript(nsIContent * aContent,
+                              nsIAtom* aAttrNameAtom,
+                              PRInt32 aAttrNamespaceID,
+                              const nsAString& aValueString);
+
+  /**
+   * This method can be redefined to check if the element can be serialized.
+   * It is called when the serialization of the start tag is asked 
+   * (AppendElementStart)
+   * In this method you can also force the formating
+   * by setting aForceFormat to PR_TRUE.
+   * @return boolean  PR_TRUE if the element can be output
+   */
+  virtual PRBool CheckElementStart(nsIContent * aContent,
+                                   PRBool & aForceFormat,
+                                   nsAString& aStr);
+
+  /**
+   * this method is responsible to finish the start tag,
+   * in particulary to append the "greater than" sign
+   */
+  virtual void AppendEndOfElementStart(nsIDOMElement *aOriginalElement,
+                                       nsIAtom * aName,
+                                       PRInt32 aNamespaceID,
+                                       nsAString& aStr);
+
+  /**
+   * This method can be redefine to serialize additional things just after
+   * after the serialization ot the start tag.
+   * (called at the end of AppendElementStart)
+   */
+  virtual void AfterElementStart(nsIContent * aContent,
+                                 nsIDOMElement *aOriginalElement,
+                                 nsAString& aStr) { };
 
-  virtual void AppendToStringConvertLF(const nsAString& aStr,
-                                       nsAString& aOutputStr);
+  /**
+   * This method can be redefined to check if the element can be serialized.
+   * It is called when the serialization of the end tag is asked 
+   * (AppendElementEnd)
+   * In this method you can also force the formating
+   * by setting aForceFormat to PR_TRUE.
+   * @return boolean  PR_TRUE if the element can be output
+   */
+  virtual PRBool CheckElementEnd(nsIContent * aContent,
+                                 PRBool & aForceFormat,
+                                 nsAString& aStr);
+
+  /**
+   * This method can be redefine to serialize additional things just after
+   * after the serialization ot the end tag.
+   * (called at the end of AppendElementStart)
+   */
+  virtual void AfterElementEnd(nsIContent * aContent,
+                               nsAString& aStr) { };
+
+  /**
+   * Returns PR_TRUE if a line break should be inserted before an element open tag
+   */
+  virtual PRBool LineBreakBeforeOpen(PRInt32 aNamespaceID, nsIAtom* aName);
+
+  /**
+   * Returns PR_TRUE if a line break should be inserted after an element open tag
+   */
+  virtual PRBool LineBreakAfterOpen(PRInt32 aNamespaceID, nsIAtom* aName);
+
+  /**
+   * Returns PR_TRUE if a line break should be inserted after an element close tag
+   */
+  virtual PRBool LineBreakBeforeClose(PRInt32 aNamespaceID, nsIAtom* aName);
+
+  /**
+   * Returns PR_TRUE if a line break should be inserted after an element close tag
+   */
+  virtual PRBool LineBreakAfterClose(PRInt32 aNamespaceID, nsIAtom* aName);
+
+  /**
+   * add intendation. Call only in the case of formating and if the current
+   * position is at 0. It updates the column position.
+   */
+  void AppendIndentation(nsAString& aStr);
+  virtual void IncrIndentation(nsIAtom* aName);
+  virtual void DecrIndentation(nsIAtom* aName);
 
   // Functions to check for newlines that needs to be added between nodes in
-  // the root of a document.
-  void MaybeAddNewline(nsAString& aStr);
-  void MaybeFlagNewline(nsIDOMNode* aNode);
+  // the root of a document. See mAddNewlineForRootNode
+  void MaybeAddNewlineForRootNode(nsAString& aStr);
+  void MaybeFlagNewlineForRootNode(nsIDOMNode* aNode);
+
+  // Functions to check if we enter in or leave from a preformated content
+  virtual void MaybeEnterInPreContent(nsIContent* aNode);
+  virtual void MaybeLeaveFromPreContent(nsIContent* aNode);
 
   PRInt32 mPrefixIndex;
-  
+
   struct NameSpaceDecl {
     nsString mPrefix;
     nsString mURI;
     nsIDOMElement* mOwner;
   };
 
   nsTArray<NameSpaceDecl> mNameSpaceStack;
 
@@ -170,19 +348,61 @@ class nsXMLContentSerializer : public ns
   PRUint32  mFlags;
 
   // characters to use for line break
   nsString  mLineBreak;
 
   // The charset that was passed to Init()
   nsCString mCharset;
   
-  // current column position
+  // current column position on the current line
   PRInt32   mColPos;
 
+  // true = pretty formating should be done (OutputFormated flag)
+  PRPackedBool mDoFormat;
+
+  // true = no formatting,(OutputRaw flag)
+  // no newline convertion and no rewrap long lines even if OutputWrap is set.
+  PRPackedBool mDoRaw;
+
+  // true = wrapping should be done (OutputWrap flag)
+  PRPackedBool mDoWrap;
+
+  // number of maximum column in a line, in the wrap mode
+  PRInt32   mMaxColumn;
+
+  // current indent value
+  nsString   mIndent;
+
+  // this is the indentation level after the indentation reached
+  // the maximum length of indentation
+  PRInt32    mIndentOverflow;
+
+  // says if the indentation has been already added on the current line
+  PRPackedBool mIsIndentationAddedOnCurrentLine;
+
+  // the string which is currently added is in an attribute
   PRPackedBool mInAttribute;
-  PRPackedBool mAddNewline;
+
+  // true = a newline character should be added. It's only
+  // useful when serializing root nodes. see MaybeAddNewlineForRootNode and
+  // MaybeFlagNewlineForRootNode
+  PRPackedBool mAddNewlineForRootNode;
+
+  // Indicates that a space will be added if and only if content is
+  // continued on the same line while serializing source.  Otherwise,
+  // the newline character acts as the whitespace and no space is needed.
+  // used when mDoFormat = true
+  PRPackedBool  mAddSpace;
+
+  // says that if the next string to add contains a newline character at the
+  // begining, then this newline character should be ignored, because a
+  // such character has already been added into the output string
+  PRPackedBool  mMayIgnoreLineBreakSequence;
+
+  // number of nested elements which have preformated content
+  PRInt32       mPreLevel;
 };
 
 nsresult
 NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer);
 
 #endif 
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -264,16 +264,38 @@ include $(topsrcdir)/config/rules.mk
 		test_bug459424.html \
 		bug461735-redirect1.sjs \
 		bug461735-redirect2.sjs \
 		bug461735-post-redirect.js \
 		test_bug461735.html \
 		test_bug380418.html \
 		test_bug465767.html \
 		test_bug380418.html^headers^ \
+		test_bug422403-1.html \
+		file_xhtmlserializer_1.xhtml \
+		file_xhtmlserializer_1_bodyonly.xhtml \
+		file_xhtmlserializer_1_format.xhtml \
+		file_xhtmlserializer_1_linebreak.xhtml \
+		file_xhtmlserializer_1_links.xhtml \
+		file_xhtmlserializer_1_noflag.xhtml \
+		file_xhtmlserializer_1_noformatpre.xhtml \
+		file_xhtmlserializer_1_raw.xhtml \
+		file_xhtmlserializer_1_nested_body.xhtml \
+		file_xhtmlserializer_1_sibling_body.xhtml \
+		file_xhtmlserializer_1_sibling_body_only_body.xhtml \
+		file_xhtmlserializer_1_no_body.xhtml \
+		test_bug422403-2.xhtml \
+		file_xhtmlserializer_2.xhtml \
+		file_xhtmlserializer_2_basic.xhtml \
+		file_xhtmlserializer_2_enthtml.xhtml \
+		file_xhtmlserializer_2_entw3c.xhtml \
+		file_xhtmlserializer_2_latin1.xhtml \
+		test_htmlcopyencoder.html \
+		test_htmlcopyencoder.xhtml \
+		test_bug270145.xhtml \
 		test_elementTraversal.html \
 		test_w3element_traversal.html \
 		test_w3element_traversal.xhtml \
 		test_bug469020.html \
 		test_w3element_traversal_svg.html \
 		w3element_traversal.svg \
 		test_bug444322.html \
 		bug444322.txt \
--- a/content/base/test/file_htmlserializer_1.html
+++ b/content/base/test/file_htmlserializer_1.html
@@ -20,24 +20,31 @@ aliquam,</li><li> fermentum sit amet,</l
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
  a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body>
 </html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_bodyonly.html
+++ b/content/base/test/file_htmlserializer_1_bodyonly.html
@@ -1,38 +1,48 @@
-
 <body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_format.html
+++ b/content/base/test/file_htmlserializer_1_format.html
@@ -1,47 +1,57 @@
 <!DOCTYPE HTML>
 <html>
-<head>
-  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
-  <title>Test for html serializer</title>
-</head>
-<body>
-<p>Hello world</p>
-<p> Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
-ad litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
-conubia</a> nostra, per inceptos hymenaeos. </p>
-<ul>
-  <li>Nam tellus massa,éàèçù</li>
-  <li> fringilla aliquam,</li>
-  <li> fermentum sit amet,</li>
-  <li>posuere ac,</li>
-  <li> est.</li>
-</ul>
-<div> Duis tristique egestas ligula. Mauris quis felis. </div>
-<script type="text/javascript">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <title>Test for html serializer</title>
+  </head>
+  <body>
+    <p>Hello world</p>
+    <p> Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
+      adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis
+      ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent
+      taciti <span>sociosqu ad litora</span> torquent <a
+        href="file_htmlserializer_1_result1.html">per conubia</a>
+      nostra, per inceptos hymenaeos. </p>
+    <ul>
+      <li>Nam tellus massa,éàèçù</li>
+      <li> fringilla aliquam,</li>
+      <li> fermentum sit amet,</li>
+      <li>posuere ac,</li>
+      <li> est.</li>
+    </ul>
+    <div> Duis tristique egestas ligula. Mauris quis felis. </div>
+    <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
-<ol>
-  <li>Fusce a ipsum</li>
-  <li> non lacus posuere aliquet.</li>
-  <li> Sed fermentum posuere nulla</li>
-  <li> Donec tempor.</li>
-</ol>
-Donec sollicitudin tortor<!-- test on 
+    <ol>
+      <li>Fusce a ipsum</li>
+      <li> non lacus posuere aliquet.</li>
+      <li> Sed fermentum posuere nulla</li>
+      <li> Donec tempor.</li>
+    </ol>
+    Donec sollicitudin tortor
+    <!-- test on 
 comments -->
-<pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
+    <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
-ut gravida eros leo ut libero
-</body>
+    ut gravida eros leo ut libero
+    <p></p>
+    <noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+    <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus
+      aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+  </body>
 </html>
--- a/content/base/test/file_htmlserializer_1_linebreak.html
+++ b/content/base/test/file_htmlserializer_1_linebreak.html
@@ -3,42 +3,53 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_links.html
+++ b/content/base/test/file_htmlserializer_1_links.html
@@ -3,42 +3,54 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="http://localhost:8888/tests/content/base/test/file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a 
+href="http://localhost:8888/tests/content/base/test/file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_nested_body.html
+++ b/content/base/test/file_htmlserializer_1_nested_body.html
@@ -3,42 +3,53 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 <body><p>this is an other body element</p></body></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_noflag.html
+++ b/content/base/test/file_htmlserializer_1_noflag.html
@@ -3,42 +3,53 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_noformatpre.html
+++ b/content/base/test/file_htmlserializer_1_noformatpre.html
@@ -3,46 +3,57 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.
 
  Cras quis
 
  nisi at odio
 
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, 
 
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_raw.html
+++ b/content/base/test/file_htmlserializer_1_raw.html
@@ -20,23 +20,30 @@ aliquam,</li><li> fermentum sit amet,</l
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
  a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_sibling_body.html
+++ b/content/base/test/file_htmlserializer_1_sibling_body.html
@@ -3,42 +3,53 @@
 
 
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body><p>this is an other body element</p></body><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_sibling_body_only_body.html
+++ b/content/base/test/file_htmlserializer_1_sibling_body_only_body.html
@@ -1,38 +1,48 @@
-
 <body><p>this is an other body element</p></body><body>
 <p>Hello world</p> <p>
 
-       Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
-adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum.
-Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
-     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
  fringilla 
 aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
 <div> Duis tristique egestas ligula. Mauris quis felis. </div>
 <script type="text/javascript">
 // a script which does nothing
 
 function nothing() {
   var hey="hello";
   var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
 }
 
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
 </script>
 
 <ol><li>Fusce
- a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
 Donec sollicitudin tortor 
 <!-- test on 
 comments -->
 <pre>lacinia <em>libero</em> ullamcorper laoreet.<br>
  Cras quis<br>
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
 </body>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_basic.html
+++ b/content/base/test/file_htmlserializer_2_basic.html
@@ -1,17 +1,18 @@
 <!DOCTYPE HTML>
 <html><head>
 <meta http-equiv="content-type" content="text/html; charset=">
 
 
   <title>Test for html serializer with entities</title>
 </head><body>
 
-<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability with older products that don't support α and friends.</p>
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support α and friends.</p>
 
 <p>latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ 
 µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ
 Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø
 Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê 
 ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý 
 þ ÿ </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
--- a/content/base/test/file_htmlserializer_2_enthtml.html
+++ b/content/base/test/file_htmlserializer_2_enthtml.html
@@ -1,50 +1,54 @@
 <!DOCTYPE HTML>
 <html><head>
 <meta http-equiv="content-type" content="text/html; charset=">
 
 
   <title>Test for html serializer with entities</title>
 </head><body>
 
-<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability with older products that don't support &alpha; and friends.</p>
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support &alpha; and friends.</p>
 
-<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml;
-&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2;
-&sup3; &acute; &micro; &para; &middot; &cedil; &sup1; &ordm; &raquo;
-&frac14; &frac12; &frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde;
-&Auml; &Aring; &AElig;
-&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc;
-&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times;
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
 &Oslash;
-&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave;
-&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave;
-&eacute; &ecirc; &euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde;
-&ograve; &oacute; &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave;
-&uacute; &ucirc; &uuml; &yacute; &thorn; &yuml; </p>
-<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon;
-&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; 
+&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; 
 &Pi; &Rho; &Sigma; &Tau; &Upsilon;
-&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon;
-&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron;
+&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; 
+&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; 
 &pi; &rho; &sigmaf;
-&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih;
-&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image;
+&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; 
+&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; 
 &real;
-&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr;
-&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla;
+&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
+&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
 &isin; &notin;
-&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and;
-&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le;
+&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
+&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
 &ge;
-&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil;
-&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
+&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
 &diams;
 </p>
 <p> others
-&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp;
+&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
 &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
-&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo;
+&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
 &rsaquo; &euro;
 </p>
 
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_entw3c.html
+++ b/content/base/test/file_htmlserializer_2_entw3c.html
@@ -1,50 +1,54 @@
 <!DOCTYPE HTML>
 <html><head>
 <meta http-equiv="content-type" content="text/html; charset=">
 
 
   <title>Test for html serializer with entities</title>
 </head><body>
 
-<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability with older products that don't support &alpha; and friends.</p>
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support &alpha; and friends.</p>
 
-<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml;
-&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2;
-&sup3; &acute; &micro; &para; &middot; &cedil; &sup1; &ordm; &raquo;
-&frac14; &frac12; &frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde;
-&Auml; &Aring; &AElig;
-&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc;
-&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times;
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
 &Oslash;
-&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave;
-&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave;
-&eacute; &ecirc; &euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde;
-&ograve; &oacute; &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave;
-&uacute; &ucirc; &uuml; &yacute; &thorn; &yuml; </p>
-<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon;
-&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; 
+&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; 
 &Pi; &Rho; &Sigma; &Tau; &Upsilon;
-&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon;
-&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron;
+&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; 
+&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; 
 &pi; &rho; &sigmaf;
-&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih;
-&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image;
+&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; 
+&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; 
 &real;
-&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr;
-&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla;
+&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
+&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
 &isin; &notin;
-&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and;
-&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le;
+&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
+&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
 &ge;
-&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil;
-&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
+&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
 &diams;
 </p>
 <p> others
-&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp;
+&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
 &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
-&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo;
+&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
 &rsaquo; &euro;
 </p>
 
 </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_latin1.html
+++ b/content/base/test/file_htmlserializer_2_latin1.html
@@ -1,31 +1,35 @@
 <!DOCTYPE HTML>
 <html><head>
 <meta http-equiv="content-type" content="text/html; charset=">
 
 
   <title>Test for html serializer with entities</title>
 </head><body>
 
-<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability with older products that don't support α and friends.</p>
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support α and friends.</p>
 
-<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml;
-&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2;
-&sup3; &acute; &micro; &para; &middot; &cedil; &sup1; &ordm; &raquo;
-&frac14; &frac12; &frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde;
-&Auml; &Aring; &AElig;
-&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc;
-&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times;
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
 &Oslash;
-&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave;
-&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave;
-&eacute; &ecirc; &euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde;
-&ograve; &oacute; &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave;
-&uacute; &ucirc; &uuml; &yacute; &thorn; &yuml; </p>
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
 Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
 σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
 ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
 ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
 ⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
 </p>
 <p> others
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_bodyonly.xhtml
@@ -0,0 +1,61 @@
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_format.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+    <title>Test for html serializer</title>
+  </head>
+  <body>
+    <p>Hello world</p>
+    <p> Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
+      adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis
+      ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent
+      taciti <span>sociosqu ad litora</span> torquent <a
+        href="file_htmlserializer_1_result1.html">per conubia</a>
+      nostra, per inceptos hymenaeos. </p>
+    <ul>
+      <li>Nam tellus massa,éàèçù</li>
+      <li> fringilla aliquam,</li>
+      <li> fermentum sit amet,</li>
+      <li>posuere ac,</li>
+      <li> est.</li>
+    </ul>
+    <div> Duis tristique egestas ligula. Mauris quis felis. </div>
+    <script id="script" type="text/javascript"></script>
+    <script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+    <ol>
+      <li>Fusce a ipsum</li>
+      <li> non lacus posuere aliquet.</li>
+      <li> Sed fermentum posuere nulla</li>
+      <li> Donec tempor.</li>
+    </ol>
+    Donec sollicitudin tortor
+    <!-- test on 
+comments -->
+    <pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+    ut gravida eros <br />
+    leo ut libero
+    <!-- empty element: end tag should be generated for backward compatibility with HTML -->
+    <p></p>
+    <noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+    <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus
+      aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+    <pre xmlns="http://mozilla.org/ns/foo">lacinia
+      <em>libero</em> ullamcorper laoreet.<br/> Cras quis<br/> nisi at
+      odio<br/> consectetuer molestie. Curabitur consectetuer urna a
+      sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in
+      faucibus orci luctus et ultrices posuere cubilia Curae; Sed
+      sollicitudin, nulla at pharetra rutrum,
+      <br/>
+      lacus risus pulvinar ante.
+    </pre>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_linebreak.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_links.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a 
+href="http://localhost:8888/tests/content/base/test/file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_nested_body.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+<body><p>this is an other body element</p></body></body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_no_body.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_noflag.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_noformatpre.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.
+
+ Cras quis
+
+ nisi at odio
+
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, 
+
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_raw.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_sibling_body.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test for html serializer</title>
+
+</head>
+<body><p>this is an other body element</p></body><body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_1_sibling_body_only_body.xhtml
@@ -0,0 +1,61 @@
+<body><p>this is an other body element</p></body><body>
+<p>Hello world</p> <p>
+
+       Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
+ ad 
+     litora</span> torquent <a href="file_htmlserializer_1_result1.html">per
+ conubia</a> 
+nostra, per inceptos hymenaeos. </p>
+
+
+<ul><li>Nam tellus massa,éàèçù</li><li>
+ fringilla 
+aliquam,</li><li> fermentum sit amet,</li><li>posuere ac,</li><li> est.</li></ul>
+<div> Duis tristique egestas ligula. Mauris quis felis. </div>
+<script id="script" type="text/javascript"></script>
+<script type="text/javascript">
+//<![CDATA[
+// a script which does nothing
+
+function nothing() {
+  var hey="hello";
+  var aLongLine="consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere";
+}
+var a=3, b=4, c=7;
+// here we test the non-serialization of xml character into javascript content
+var d = a < b && a > c;
+//]]>
+</script>
+
+<ol><li>Fusce
+ a ipsum</li><li> non lacus posuere aliquet.</li><li> Sed fermentum 
+posuere nulla</li><li> Donec tempor.</li></ol>
+Donec sollicitudin tortor 
+<!-- test on 
+comments -->
+<pre>lacinia <em>libero</em> ullamcorper laoreet.<br />
+ Cras quis<br />
+ nisi at odio<br />
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br />
+lacus risus pulvinar ante.
+</pre>
+ut gravida eros <br />leo ut libero
+<!-- empty element: end tag should be generated for backward compatibility with HTML -->
+<p></p>
+<noscript>
+<p>Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
+<pre xmlns="http://mozilla.org/ns/foo">lacinia <em>libero</em> 
+ullamcorper laoreet.<br/>
+ Cras quis<br/>
+ nisi at odio<br/>
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non 
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci 
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at 
+pharetra rutrum, <br/>
+lacus risus pulvinar ante.
+</pre>
+</body>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_2.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>Test for html serializer with entities</title>
+</head>
+<body>
+
+<p>The basic set is just &nbsp; &amp; &lt; &gt; &quot; for interoperability with older products that don't support &alpha; and friends.</p>
+
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; &copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; &sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; &frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; &AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; &Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; &Oslash;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; &aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; &eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute; &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; &uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; &Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; &Pi; &Rho; &Sigma; &Tau; &Upsilon;
+&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; &zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; &pi; &rho; &sigmaf;
+&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; &piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; &real;
+&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; &uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; &isin; &notin;
+&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; &or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; &ge;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; &rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; &diams;
+</p>
+<p> others
+&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
+&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; &rsaquo; &euro;
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_2_basic.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=" />
+  <title>Test for html serializer with entities</title>
+</head>
+<body>
+
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support α and friends.</p>
+
+<p>latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ 
+µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ
+Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø
+Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê 
+ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý 
+þ ÿ </p>
+<p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
+Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
+σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
+™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
+∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+</p>
+<p> others
+Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
+‚“ ” „ † ‡ ‰ ‹ › €
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_2_enthtml.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=" />
+  <title>Test for html serializer with entities</title>
+</head>
+<body>
+
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support &alpha; and friends.</p>
+
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
+&Oslash;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; 
+&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; 
+&Pi; &Rho; &Sigma; &Tau; &Upsilon;
+&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; 
+&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; 
+&pi; &rho; &sigmaf;
+&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; 
+&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; 
+&real;
+&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
+&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
+&isin; &notin;
+&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
+&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
+&ge;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
+&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
+&diams;
+</p>
+<p> others
+&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
+&thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
+&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
+&rsaquo; &euro;
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_2_entw3c.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=" />
+  <title>Test for html serializer with entities</title>
+</head>
+<body>
+
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support &alpha; and friends.</p>
+
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
+&Oslash;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; 
+&Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; 
+&Pi; &Rho; &Sigma; &Tau; &Upsilon;
+&Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; 
+&zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; 
+&pi; &rho; &sigmaf;
+&sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; 
+&piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; 
+&real;
+&trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
+&uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
+&isin; &notin;
+&ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
+&or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
+&ge;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
+&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
+&diams;
+</p>
+<p> others
+&OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
+&thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
+&sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
+&rsaquo; &euro;
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_xhtmlserializer_2_latin1.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=" />
+  <title>Test for html serializer with entities</title>
+</head>
+<body>
+
+<p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
+with older products that don't support α and friends.</p>
+
+<p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
+&copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
+&sup3; &acute; 
+&micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; 
+&frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; 
+&AElig;
+&Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; 
+&Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; 
+&Oslash;
+&Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; 
+&aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; 
+&eacute; &ecirc; 
+&euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute;
+ &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
+&uuml; &yacute; 
+&thorn; &yuml; </p>
+<p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
+Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
+σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
+™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
+∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+</p>
+<p> others
+Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
+‚“ ” „ † ‡ ‰ ‹ › €
+</p>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug270145.xhtml
@@ -0,0 +1,55 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=270145
+-->
+<head>
+  <title>Test the html copy encoder with XHTML </title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=270145">Mozilla Bug 270145</a>
+<p id="display"></p>
+<div id="content" >
+<p id="foo"><![CDATA[a text to copy]]></p>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+//<![CDATA[
+function testHtmlCopyEncoder () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder;
+  var encoder = Components.classes["@mozilla.org/layout/htmlCopyEncoder;1"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+  var out, expected;
+  
+  var node = document.getElementById('draggable');
+
+  var select = window.getSelection();
+  select.removeAllRanges();
+
+  node = document.getElementById("foo").firstChild;
+  var range = document.createRange();
+  range.setStart(node, 0);
+  range.setEnd(node, "a text to copy".length);
+  select.addRange(range);
+  encoder.init(document, "text/html", 0);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = "a text to copy";
+  is(out, expected, "test xhtml copy");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testHtmlCopyEncoder);
+//]]>
+</script>
+</pre>
+
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug422403-1.html
@@ -0,0 +1,199 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+  <title>Test for XHTML serializer</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=422043">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="testframe" src="file_xhtmlserializer_1.xhtml">
+  </iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+
+function loadFileContent(aFile, aCharset) {
+    //if(aAsIso == undefined) aAsIso = false;
+    if(aCharset == undefined)
+        aCharset = 'UTF-8';
+
+    var baseUri = Components.classes['@mozilla.org/network/standard-url;1']
+                   .createInstance(Components.interfaces.nsIURI);
+    baseUri.spec = window.location.href;
+
+    var ios = Components.classes['@mozilla.org/network/io-service;1']
+            .getService(Components.interfaces.nsIIOService);
+    var chann = ios.newChannel(aFile, aCharset, baseUri);
+
+    var cis = Components.interfaces.nsIConverterInputStream;
+
+    var inputStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
+                       .createInstance(cis);
+    inputStream.init(chann.open(), aCharset, 1024, cis.DEFAULT_REPLACEMENT_CHARACTER);
+    var str = {}, content = '';
+    while (inputStream.readString(4096, str) != 0) {
+        content += str.value;
+    }
+    return content;
+}
+
+
+function testHtmlSerializer_1 () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder
+  var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=application/xhtml+xml"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+
+  var doc = $("testframe").contentDocument;
+  var out, expected;
+
+  // in the following tests, we must use the OutputLFLineBreak flag, to avoid
+  // to have the default line break of the platform in the result, so the test
+  // can pass on all platform
+
+  //------------ no flags
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_noflag.xhtml");
+  is(out, expected, "test no flags");
+
+  //------------- unsupported flags
+  // since the following flags are not supported, we should
+  // have a result like the one without flag
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputPreformatted);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputPreformatted");
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputFormatFlowed);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputFormatFlowed");
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputNoScriptContent);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputNoScriptContent");
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputNoFramesContent);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputNoFramesContent");
+
+
+  //------------ OutputWrap
+  // by default, this flag is set, so we should have the same result as
+  // when there are no flags.
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputWrap);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputWrap");
+
+  //------------ OutputFormatted
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputFormatted);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_format.xhtml");
+  is(out, expected, "test OutputFormatted");
+
+  //------------ OutputRaw
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputRaw);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_raw.xhtml");
+  is(out, expected, "test OutputRaw");
+
+  //------------ OutputBodyOnly
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputBodyOnly);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_bodyonly.xhtml");
+  is(out, expected, "test OutputBodyOnly");
+
+
+  //------------ OutputAbsoluteLinks
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputAbsoluteLinks);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_links.xhtml");
+  is(out, expected, "test OutputAbsoluteLinks");
+
+  //------------ OutputLFLineBreak
+  encoder.init(doc, "application/xhtml+xml",de.OutputLFLineBreak);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_linebreak.xhtml");
+  is(out, expected, "test OutputLFLineBreak");
+
+  //------------ OutputCRLineBreak
+  encoder.init(doc, "application/xhtml+xml",de.OutputCRLineBreak);
+  out = encoder.encodeToString();
+  expected = expected.replace(/\n/mg, "\r");
+  is(out, expected, "test OutputCRLineBreak");
+
+  //------------ OutputLFLineBreak + OutputCRLineBreak
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputCRLineBreak);
+  out = encoder.encodeToString();
+  expected = expected.replace(/\r/mg, "\r\n");
+  is(out, expected, "test OutputLFLineBreak + OutputCRLineBreak");
+
+  //------------ OutputNoFormattingInPre
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputNoFormattingInPre);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_noformatpre.xhtml");
+  is(out, expected, "test OutputNoFormattingInPre");
+
+  // ------------- nested body elements
+  var body2 = doc.createElement('body');
+  var p = doc.createElement('p');
+  p.appendChild(doc.createTextNode("this is an other body element"));
+  body2.appendChild(p);
+  var body = doc.getElementsByTagName('body')[0];
+  body.appendChild(body2);
+
+  is(doc.getElementsByTagName('body').length, 2); // to be sure we have two body elements
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_nested_body.xhtml");
+  is(out, expected, "test with two nested body elements");
+
+  // ------------- two body elements
+  body.parentNode.insertBefore(body2, body);
+
+  is(doc.getElementsByTagName('body').length, 2); // to be sure we have two body elements
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_sibling_body.xhtml");
+  is(out, expected, "test with two body elements");
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputBodyOnly);
+  encoder.setCharset("UTF-8");
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_sibling_body_only_body.xhtml");
+  is(out, expected, "test with two body elements, and output body only");
+
+  // --------------- no body element
+  doc.documentElement.removeChild(body);
+  doc.documentElement.removeChild(body2);
+
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_1_no_body.xhtml");
+  is(out, expected, "test with no body element");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testHtmlSerializer_1);
+
+</script>
+</pre>
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug422403-2.xhtml
@@ -0,0 +1,291 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+-->
+<head>
+  <title>Test XHTML serializer with entities and selection</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=422043">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="testframe" src="file_xhtmlserializer_2.xhtml">
+  </iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+//<![CDATA[
+
+function loadFileContent(aFile, aCharset) {
+    //if(aAsIso == undefined) aAsIso = false;
+    if(aCharset == undefined)
+        aCharset = 'UTF-8';
+
+    var baseUri = Components.classes['@mozilla.org/network/standard-url;1']
+                   .createInstance(Components.interfaces.nsIURI);
+    baseUri.spec = window.location.href;
+
+    var ios = Components.classes['@mozilla.org/network/io-service;1']
+            .getService(Components.interfaces.nsIIOService);
+    var chann = ios.newChannel(aFile, aCharset, baseUri);
+
+    var cis = Components.interfaces.nsIConverterInputStream;
+
+    var inputStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
+                       .createInstance(cis);
+    inputStream.init(chann.open(), aCharset, 1024, cis.DEFAULT_REPLACEMENT_CHARACTER);
+    var str = {}, content = '';
+    while (inputStream.readString(4096, str) != 0) {
+        content += str.value;
+    }
+    return content;
+}
+
+
+function testHtmlSerializer_1 () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder
+  var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=application/xhtml+xml"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+
+  var doc = $("testframe").contentDocument;
+  var out, expected;
+
+  // in the following tests, we must use the OutputLFLineBreak flag, to avoid
+  // to have the default line break of the platform in the result, so the test
+  // can pass on all platform
+
+  //------------ OutputEncodeW3CEntities
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputEncodeW3CEntities);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_2_entw3c.xhtml");
+  is(out, expected, "test OutputEncodeW3CEntities");
+
+  //------------ OutputEncodeBasicEntities
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputEncodeBasicEntities);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_2_basic.xhtml");
+  is(out, expected, "test OutputEncodeBasicEntities");
+
+  //------------ OutputEncodeLatin1Entities
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputEncodeLatin1Entities);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_2_latin1.xhtml");
+  is(out, expected, "test OutputEncodeLatin1Entities");
+
+  //------------ OutputEncodeHTMLEntities
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputEncodeHTMLEntities);
+  out = encoder.encodeToString();
+  expected = loadFileContent("file_xhtmlserializer_2_enthtml.xhtml");
+  is(out, expected, "test OutputEncodeHTMLEntities");
+
+  // tests on the serialization of selections
+
+  var node = document.getElementById('draggable');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);  
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = 'This is a <em xmlns=\"http://www.w3.org/1999/xhtml\">draggable</em> bit of\n text.';
+  is(out, expected, "test selection");
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(null);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = 'This is a <em xmlns=\"http://www.w3.org/1999/xhtml\">draggable</em> bit of\n text.';
+  is(out, expected, "test container node");
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<div xmlns=\"http://www.w3.org/1999/xhtml\" id=\"draggable\" \nondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em> \nbit of text.</div>";
+  is(out, expected, "test node");
+
+  node = document.getElementById('aList');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);  
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '\n   <li xmlns=\"http://www.w3.org/1999/xhtml\">Lorem ipsum dolor</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">sit amet, <strong>consectetuer</strong>\n </li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">adipiscing elit</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">Nam eu sapien. Sed viverra \nlacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. \nClass</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">aptent taciti</li>\n';
+  is(out, expected, "test list selection");
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(null);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = '\n   <li xmlns=\"http://www.w3.org/1999/xhtml\">Lorem ipsum dolor</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">sit amet, <strong>consectetuer</strong>\n </li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">adipiscing elit</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">Nam eu sapien. Sed viverra \nlacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. \nClass</li>\n  <li xmlns=\"http://www.w3.org/1999/xhtml\">aptent taciti</li>\n';
+  is(out, expected, "test list container node");
+
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<ol xmlns=\"http://www.w3.org/1999/xhtml\" id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>";
+  is(out, expected, "test list node");
+
+  var liList = node.getElementsByTagName("li");
+  var range = document.createRange();
+
+  // selection start at the first child of the ol, and end after the element ol
+  range.setStart(node, 1);
+  range.setEnd(node.parentNode, 2);
+  select.removeAllRanges();
+  select.addRange(range);
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol xmlns=\"http://www.w3.org/1999/xhtml\" id="aList"><li>Lorem ipsum \ndolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the first child of the ol, and end after the element ol");
+
+  // selection start at the third child of the ol, and end after the element ol
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol xmlns=\"http://www.w3.org/1999/xhtml\" id="aList"><li>sit amet, <strong>consectetuer</strong>\n </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol");
+
+
+  // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  node.setAttribute("start","5");
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol xmlns=\"http://www.w3.org/1999/xhtml\" id="aList" start="5"><li>sit \namet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
+
+
+  // selection contains only some child of the ol
+  node.removeAttribute("start");
+  range.setStart(node, 3);
+  range.setEnd(node, 5);
+  encoder.init(document, "application/xhtml+xml", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li xmlns=\"http://www.w3.org/1999/xhtml\">sit amet, <strong>consectetuer</strong>\n </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol");
+
+
+  // test on short attributes
+
+  node = document.getElementById('shortattr1');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<input xmlns="http://www.w3.org/1999/xhtml" id="shortattr1" checked="checked" value="" disabled="disabled" ismap="ismap" readonly="readonly" foo:checked="" xmlns:foo="http://mozilla.org/ns/any" foo:disabled="" />';
+  is(out, expected, "test short attr #1");
+
+  node = document.getElementById('shortattr2');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<ol xmlns="http://www.w3.org/1999/xhtml" id="shortattr2" compact="compact"><li></li></ol>';
+  is(out, expected, "test short attr #2");
+
+  node = document.getElementById('shortattr3');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<object xmlns="http://www.w3.org/1999/xhtml" id="shortattr3" declare="declare"></object>';
+  is(out, expected, "test short attr #3");
+
+  node = document.getElementById('shortattr4');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<script xmlns="http://www.w3.org/1999/xhtml" id="shortattr4" defer="defer"></script>';
+  is(out, expected, "test short attr #4");
+
+  node = document.getElementById('shortattr5');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<select xmlns="http://www.w3.org/1999/xhtml" id="shortattr5" multiple="multiple"><option selected="selected">aaa</option></select>';
+  is(out, expected, "test short attr #5");
+
+  node = document.getElementById('shortattr6');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<hr xmlns="http://www.w3.org/1999/xhtml" noshade="noshade" id="shortattr6" />';
+  is(out, expected, "test short attr #6");
+
+  node = document.getElementById('shortattr7');
+  encoder.init(document, "application/xhtml+xml",de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div xmlns="http://www.w3.org/1999/xhtml" id="shortattr7"><foo:bar xmlns:foo="http://mozilla.org/ns/any" checked="" value="" disabled="" ismap="" readonly=""/></div>';
+  is(out, expected, "test short attr #7");
+
+  // test on _moz and -moz attr
+  node = document.getElementById('mozattr');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div __moz_b="b" id="mozattr"> lorem ipsum</div>';
+  is(out, expected, "test -moz/_moz attr");
+
+  node.setAttribute('_moz_c','barc');
+  node.setAttribute('_-moz_d','bard');
+  node.setAttribute('__moz_e','bare');
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div __moz_e="bare" _-moz_d="bard" __moz_b="b" id="mozattr"> lorem ipsum</div>';
+  is(out, expected, "test -moz/_moz attr #2");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testHtmlSerializer_1);
+//]]>
+</script>
+</pre>
+<div style="display: none">
+
+<div id="draggable" ondragstart="doDragStartSelection(event)">This is a <em>draggable</em> bit of text.</div>
+
+</div>
+<div style="display: none">
+
+<ol id="aList">
+   <li>Lorem ipsum dolor</li>
+  <li>sit amet, <strong>consectetuer</strong> </li>
+  <li>adipiscing elit</li>
+  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>
+  <li>aptent taciti</li>
+</ol>
+
+<!-- test for some short attr -->
+<div id="shortattr" xmlns:foo="http://mozilla.org/ns/any">
+   <input id="shortattr1" checked="" value="" disabled="" ismap="" readonly="" foo:checked="" foo:disabled=""/>
+   <ol id="shortattr2" compact=""><li></li></ol>
+   <object id="shortattr3" declare="" />
+   <script id="shortattr4" defer="" />
+   <select id="shortattr5" multiple=""><option selected="">aaa</option></select>
+   <hr noshade="" id="shortattr6"/>
+   <div id="shortattr7"><foo:bar checked="" value="" disabled="" ismap="" readonly="" /></div>
+   <div id="mozattr" _moz_a="a" __moz_b="b"> lorem ipsum</div>
+</div>
+
+</div>
+</body>
+</html>
+
+
--- a/content/base/test/test_bug424359-1.html
+++ b/content/base/test/test_bug424359-1.html
@@ -67,33 +67,36 @@ function testHtmlSerializer_1 () {
 
   //------------- unsupported flags
   // since the following flags are not supported, we should
   // have a result like the one without flag
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputPreformatted);
   out = encoder.encodeToString();
   is(out, expected, "test OutputPreformatted");
 
-  encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputWrap);
-  out = encoder.encodeToString();
-  is(out, expected, "test OutputWrap");
-
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputFormatFlowed);
   out = encoder.encodeToString();
   is(out, expected, "test OutputFormatFlowed");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputNoScriptContent);
   out = encoder.encodeToString();
   is(out, expected, "test OutputNoScriptContent");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputNoFramesContent);
   out = encoder.encodeToString();
   is(out, expected, "test OutputNoFramesContent");
 
 
+  //------------ OutputWrap
+  // by default, this flag is set, so we should have the same result as
+  // when there are no flags.
+  encoder.init(doc, "text/html", de.OutputLFLineBreak |de.OutputWrap);
+  out = encoder.encodeToString();
+  is(out, expected, "test OutputWrap");
+
   //------------ OutputFormatted
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputFormatted);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_format.html");
   is(out, expected, "test OutputFormatted");
 
   //------------ OutputRaw
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputRaw);
@@ -176,17 +179,16 @@ function testHtmlSerializer_1 () {
   doc.documentElement.removeChild(body2);
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_no_body.html");
   is(out, expected, "test with no body element");
 
-
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(testHtmlSerializer_1);
 
--- a/content/base/test/test_bug424359-2.html
+++ b/content/base/test/test_bug424359-2.html
@@ -77,20 +77,234 @@ function testHtmlSerializer_1 () {
   is(out, expected, "test OutputEncodeLatin1Entities");
 
   //------------ OutputEncodeHTMLEntities
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputEncodeHTMLEntities);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_2_enthtml.html");
   is(out, expected, "test OutputEncodeHTMLEntities");
 
+
+  // tests on the serialization of selections
+
+  var node = document.getElementById('draggable');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);  
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = 'This is a <em>draggable</em> bit of text.';
+  is(out, expected, "test selection");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(null);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = 'This is a <em>draggable</em> bit of text.';
+  is(out, expected, "test container node");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n bit of text.</div>";
+  is(out, expected, "test node");
+
+  node = document.getElementById('aList');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);  
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n';
+  is(out, expected, "test list selection");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(null);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = '\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n';
+  is(out, expected, "test list container node");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<ol id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>";
+  is(out, expected, "test list node");
+
+  var liList = node.getElementsByTagName("li");
+  var range = document.createRange();
+
+  // selection start at the first child of the ol, and end after the element ol
+  range.setStart(node, 1);
+  range.setEnd(node.parentNode, 2);
+  select.removeAllRanges();
+  select.addRange(range);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList"><li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the first child of the ol, and end after the element ol");
+
+  // selection start at the third child of the ol, and end after the element ol
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList"><li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol");
+
+
+  // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol start="5" id="aList"><li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
+
+
+  // selection contains only some child of the ol
+  node.removeAttribute("start");
+  range.setStart(node, 3);
+  range.setEnd(node, 5);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol");
+
+  // selection contains only some child of the ol  + ol start at the value 5
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol + ol start at the value 5");
+
+  // selection contains only some child of the ol  + a value is set on the first li
+  node.removeAttribute("start");
+  liList[0].setAttribute("value","8");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol + ol start at the value 5");
+
+
+
+  // test on short attributes
+  node = document.getElementById('shortattr1');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<input id="shortattr1" checked="checked" value="" disabled="disabled" ismap="ismap" readonly="readonly" foo="">';
+  is(out, expected, "test short attr #1");
+
+  node = document.getElementById('shortattr2');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<ol id="shortattr2" compact="compact"><li></li></ol>';
+  is(out, expected, "test short attr #2");
+
+  node = document.getElementById('shortattr3');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<object id="shortattr3" declare="declare"></object>';
+  is(out, expected, "test short attr #3");
+
+  node = document.getElementById('shortattr4');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<script id="shortattr4" defer="defer"></'+ 'script>';
+  is(out, expected, "test short attr #4");
+
+  node = document.getElementById('shortattr5');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<select id="shortattr5" multiple="multiple"><option selected="selected">aaa</option></select>';
+  is(out, expected, "test short attr #5");
+
+  node = document.getElementById('shortattr6');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<hr id="shortattr6" noshade="noshade">';
+  is(out, expected, "test short attr #6");
+
+  node = document.getElementById('shortattr7');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div id="shortattr7"><foo checked="" value="" disabled="" ismap="" readonly=""></foo></div>';
+  is(out, expected, "test short attr #7");
+
+  // test on _moz and -moz attr
+  node = document.getElementById('mozattr');
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div id="mozattr" __moz_b="b"> lorem ipsum</div>';
+  is(out, expected, "test -moz/_moz attr");
+
+  node.setAttribute('_moz_c','barc');
+  node.setAttribute('_-moz_d','bard');
+  node.setAttribute('__moz_e','bare');
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = '<div __moz_e="bare" _-moz_d="bard" id="mozattr" __moz_b="b"> lorem ipsum</div>';
+  is(out, expected, "test -moz/_moz attr #2");
+
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(testHtmlSerializer_1);
 
 </script>
 </pre>
+<div style="display: none">
+
+<div id="draggable" ondragstart="doDragStartSelection(event)">This is a <em>draggable</em> bit of text.</div>
+
+</div>
+<div style="display: none">
+
+<ol id="aList">
+   <li>Lorem ipsum dolor</li>
+  <li>sit amet, <strong>consectetuer</strong> </li>
+  <li>adipiscing elit</li>
+  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>
+  <li>aptent taciti</li>
+</ol>
+
+
+<!-- test for some short attr -->
+<div id="shortattr">
+   <input id="shortattr1" checked="" value="" disabled="" ismap="" readonly="" foo="">
+   <ol id="shortattr2" compact=""><li></li></ol>
+   <object id="shortattr3" declare=""></object>
+   <script id="shortattr4" defer=""></script>
+   <select id="shortattr5" multiple=""><option selected="">aaa</option></select>
+   <hr noshade="" id="shortattr6">
+   <div id="shortattr7"><foo checked="" value="" disabled="" ismap="" readonly=""></div>
+   <div id="mozattr" _moz_a="a" __moz_b="b"> lorem ipsum</div>
+</div>
+
+
+
+</div>
 </body>
 </html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_htmlcopyencoder.html
@@ -0,0 +1,187 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+  <title>Test on the html copy encoder</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=422403">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function testHtmlCopyEncoder () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder;
+  var encoder = Components.classes["@mozilla.org/layout/htmlCopyEncoder;1"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+  var out, expected;
+
+  var node = document.getElementById('draggable');
+
+
+  // in the following tests, we must use the OutputLFLineBreak flag, to avoid
+  // to have the default line break of the platform in the result, so the test
+  // can pass on all platform
+
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = 'This is a <em>draggable</em> bit of text.';
+  is(out, expected, "test container node ");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n bit of text.</div>";
+  is(out, expected, "test node");
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = "<div style=\"display: none;\">\n\n<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n bit of text.</div>\n\n</div>";
+  is(out, expected, "test selection");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputAbsoluteLinks | de.OutputEncodeHTMLEntities | de.OutputSelectionOnly | de.OutputRaw);
+  encoder.setSelection(select);
+  var outContext = {value:''}, outInfo = {value:''};
+  out = encoder.encodeToStringWithContext(outContext, outInfo);
+  expected = "<div style=\"display: none;\">\n\n<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em> bit of text.</div>\n\n</div>";
+  is(out, expected, "test encodeToStringWithContext with selection ");
+
+  node.nextSibling.data="\nfoo bar\n";
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = "<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n bit of text.</div>";
+  is(out, expected, "test selection with additional data");
+
+  node = document.getElementById('aList');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = '\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n';
+  is(out, expected, "test list container node");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<ol id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>";
+  is(out, expected, "test list node");
+
+  var liList = node.getElementsByTagName("li");
+  var range = document.createRange();
+
+  // selection start at the first child of the ol, and end after the element ol
+  range.setStart(node, 1);
+  range.setEnd(node.parentNode, 2);
+  select.removeAllRanges();
+  select.addRange(range);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the first child of the ol, and end after the element ol");
+
+  // selection start at the third child of the ol, and end after the element ol
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList"><li value=\"2\">sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol");
+
+
+  // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol start=\"5\" id=\"aList\"><li value=\"6\">sit amet, <strong>consectetuer</strong>\n </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
+
+  // selection contains only some child of the ol
+  node.removeAttribute("start");
+  range.setStart(node, 3);
+  range.setEnd(node, 5);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol");
+
+  // selection contains only some child of the ol  + ol start at the value 5
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol + ol start at the value 5");
+
+  // selection contains only some child of the ol  + a value is set on the first li
+  node.removeAttribute("start");
+  liList[0].setAttribute("value","8");
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  is(out, expected, "test list selection with range: selection contains only some child of the ol + ol start at the value 5");
+
+  select.selectAllChildren(node);
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id=\"aList\">\n   <li value=\"8\">Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  is(out, expected, "test list selection with a value on a LI");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testHtmlCopyEncoder);
+
+</script>
+</pre>
+<div style="display: none">
+
+<div id="draggable" ondragstart="doDragStartSelection(event)">This is a <em>draggable</em> bit of text.</div>
+
+</div>
+<div style="display: none">
+
+<ol id="aList">
+   <li>Lorem ipsum dolor</li>
+  <li>sit amet, <strong>consectetuer</strong> </li>
+  <li>adipiscing elit</li>
+  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>
+  <li>aptent taciti</li>
+</ol>
+foo bar
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_htmlcopyencoder.xhtml
@@ -0,0 +1,186 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+-->
+<head>
+  <title>Test the html copy encoder with XHTML</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=422403">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+//<![CDATA[
+function testHtmlCopyEncoder () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder;
+  var encoder = Components.classes["@mozilla.org/layout/htmlCopyEncoder;1"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+  var out, expected;
+
+  var node = document.getElementById('draggable');
+
+
+  // in the following tests, we must use the OutputLFLineBreak flag, to avoid
+  // to have the default line break of the platform in the result, so the test
+  // can pass on all platform
+
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = 'This is a <em>draggable</em> <br>bit of text.';
+  is(out, expected, "test container node ");
+
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  // the attributes are in the reverse order because the XHTML parser parse in the
+  // right order but the html serializer serializes in the reverse order
+  // (because the html parser stores the attribute in the reverse order,
+  // see bug 213347 for reason).
+  expected = "<div ondragstart=\"doDragStartSelection(event)\" id=\"draggable\">This is a <em>draggable</em>\n <br>bit of text.</div>";
+  is(out, expected, "test node");
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);
+  
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = "<div style=\"display: none;\">\n\n<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n <br>bit of text.</div>\n\n</div>";
+  todo_is(out, expected, "test selection");
+
+  node.nextSibling.data="\nfoo bar\n";
+  encoder.init(document, "text/html", de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = "<div id=\"draggable\" ondragstart=\"doDragStartSelection(event)\">This is a <em>draggable</em>\n <br>bit of text.</div>";
+  todo_is(out, expected, "test selection with additional data");
+
+  node = document.getElementById('aList');
+
+  var select = window.getSelection();
+  select.selectAllChildren(node);  
+
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  todo_is(out, expected, "test list selection");
+
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setContainerNode(node);
+  out = encoder.encodeToString();
+  expected = '\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n';
+  is(out, expected, "test list container node");
+
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setNode(node);
+  out = encoder.encodeToString();
+  expected = "<ol id=\"aList\">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>";
+  is(out, expected, "test list node");
+
+  var liList = node.getElementsByTagName("li");
+  var range = document.createRange();
+
+  // selection start at the first child of the ol, and end after the element ol
+  range.setStart(node, 1);
+  range.setEnd(node.parentNode, 2);
+  select.removeAllRanges();
+  select.addRange(range);
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList">\n   <li>Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  todo_is(out, expected, "test list selection with range: selection start at the first child of the ol, and end after the element ol");
+
+  // selection start at the third child of the ol, and end after the element ol
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id="aList"><li value=\"2\">sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  todo_is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol");
+
+
+  // selection start at the third child of the ol, and end after the element ol + ol start at the value 5
+  range.setStart(node, 3);
+  range.setEnd(node.parentNode, 2);
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol start=\"5\" id=\"aList\"><li value=\"6\">sit amet, <strong>consectetuer</strong>\n </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  todo_is(out, expected, "test list selection with range: selection start at the third child of the ol, and end after the element ol + ol start at the value 5");
+
+
+  // selection contains only some child of the ol
+  node.removeAttribute("start");
+  range.setStart(node, 3);
+  range.setEnd(node, 5);
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  todo_is(out, expected, "test list selection with range: selection contains only some child of the ol");
+
+  // selection contains only some child of the ol  + ol start at the value 5
+  node.setAttribute("start","5");
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  todo_is(out, expected, "test list selection with range: selection contains only some child of the ol + ol start at the value 5");
+
+
+  // selection contains only some child of the ol  + a value is set on the first li
+  node.removeAttribute("start");
+  liList[0].setAttribute("value","8");
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<li>sit amet, <strong>consectetuer</strong> </li>\n  ';
+  todo_is(out, expected, "test list selection: contains only some child of the ol  + a value is set on the first li");
+
+  select.selectAllChildren(node);
+  encoder.init(document, "text/html",de.OutputLFLineBreak | de.OutputSelectionOnly);
+  encoder.setSelection(select);
+  out = encoder.encodeToString();
+  expected = '<ol id=\"aList\">\n   <li value=\"8\">Lorem ipsum dolor</li>\n  <li>sit amet, <strong>consectetuer</strong> </li>\n  <li>adipiscing elit</li>\n  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus \naliquet lectus. Nunc vitae eros. Class</li>\n  <li>aptent taciti</li>\n</ol>';
+  todo_is(out, expected, "test list selection with a value on a LI");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testHtmlCopyEncoder);
+//]]>
+</script>
+</pre>
+<div style="display: none">
+
+<div id="draggable" ondragstart="doDragStartSelection(event)">This is a <em>draggable</em> <br/>bit of text.</div>
+
+</div>
+<div style="display: none">
+
+<ol id="aList">
+   <li>Lorem ipsum dolor</li>
+  <li>sit amet, <strong>consectetuer</strong> </li>
+  <li>adipiscing elit</li>
+  <li>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class</li>
+  <li>aptent taciti</li>
+</ol>
+foo bar
+</div>
+</body>
+</html>
--- a/content/base/test/unit/2_original.xml
+++ b/content/base/test/unit/2_original.xml
@@ -1,16 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE whatever PUBLIC
           "-//MOZ//WHATEVER//EN"
           "http://mozilla.org/ns/foo">
-<foo xmln="htp://mozilla.org/ns">
-    <baz /> <!-- a comment -->
-    <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
-        <mozilla> a a a a a éèàùûî</mozilla>
-        <firefox>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi at odio consectetuer molestie.</firefox>
+<foo xmlns="htp://mozilla.org/ns">
+    <baz /><!-- a comment --> <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+<mozilla> a a a a a éèàùûî</mozilla>
+        <firefox>Lorem ip<!-- aaa -->sum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi at odio consectetuer molestie.</firefox>
         <?xml-foo "hey" ?>
-    </bar>
+</bar>
               <!-- a comment 
          on several lines-->
  <?xml-foo "another pi on two lines"  
               example="hello"?>
 </foo>
\ No newline at end of file
--- a/content/base/test/unit/2_result_1.xml
+++ b/content/base/test/unit/2_result_1.xml
@@ -1,14 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
-<foo xmln="htp://mozilla.org/ns">
-    <baz/> <!-- a comment -->
-    <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
-        <mozilla> a a a a a éèàùûî</mozilla>
-        <firefox>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi at odio consectetuer molestie.</firefox>
+<foo xmlns="htp://mozilla.org/ns">
+    <baz/><!-- a comment --> <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+<mozilla> a a a a a éèàùûî</mozilla>
+        <firefox>Lorem ip<!-- aaa -->sum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi at odio consectetuer molestie.</firefox>
         <?xml-foo "hey" ?>
-    </bar>
+</bar>
               <!-- a comment 
          on several lines-->
  <?xml-foo "another pi on two lines"  
               example="hello"?>
 </foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/2_result_2.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="htp://mozilla.org/ns">
+  <baz/><!-- a comment -->
+  <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+    <mozilla> a a a a a éèàùûî</mozilla>
+    <firefox>Lorem ip<!-- aaa -->sum dolor sit amet, consectetuer adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi at odio consectetuer molestie.</firefox>
+    <?xml-foo "hey" ?>
+  </bar>
+  <!-- a comment 
+         on several lines-->
+  <?xml-foo "another pi on two lines"  
+              example="hello"?>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/2_result_3.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="htp://mozilla.org/ns">
+  <baz/><!-- a comment -->
+  <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+    <mozilla> a a a a a éèàùûî</mozilla>
+    <firefox>Lorem ip<!-- aaa -->sum dolor sit amet, consectetuer
+      adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis
+      ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent
+      taciti sociosqu ad litora torquent per conubia nostra, per
+      inceptos hymenaeos. Nam tellus massa, fringilla aliquam, fermentum
+      sit amet, posuere ac, est. Duis tristique egestas ligula. Mauris
+      quis felis. Fusce a ipsum non lacus posuere aliquet. Sed fermentum
+      posuere nulla. Donec tempor. Donec sollicitudin tortor lacinia
+      libero ullamcorper laoreet. Cras quis nisi at odio consectetuer
+      molestie.</firefox>
+    <?xml-foo "hey" ?>
+  </bar>
+  <!-- a comment 
+         on several lines-->
+  <?xml-foo "another pi on two lines"  
+              example="hello"?>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/2_result_4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="htp://mozilla.org/ns">
+    <baz/><!-- a comment --> <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+<mozilla> a a a a a éèàùûî</mozilla>
+        <firefox>Lorem ip<!-- aaa -->sum dolor sit amet, consectetuer 
+adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
+Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti 
+sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. 
+Nam tellus massa, fringilla aliquam, fermentum sit amet, posuere ac, 
+est. Duis tristique egestas ligula. Mauris quis felis. Fusce a ipsum non
+ lacus posuere aliquet. Sed fermentum posuere nulla. Donec tempor. Donec
+ sollicitudin tortor lacinia libero ullamcorper laoreet. Cras quis nisi 
+at odio consectetuer molestie.</firefox>
+        <?xml-foo "hey" ?>
+</bar>
+              <!-- a comment 
+         on several lines-->
+ <?xml-foo "another pi on two lines"  
+              example="hello"?>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/3_original.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+Lorem ip<!-- aaa -->sum dolorsitamet, consectetuer adipiscing elit. Nameusapien. Sed viverralacus. this_is_a_very_long_long_word_which_has_a_length_higher_than_the_max_column Donecquisipsum. Nunc cursus aliquet lectus. Nunc vitae eros.
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/3_result.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+  Lorem ip<!-- aaa -->sum dolorsitamet, consectetuer adipiscing elit.
+  Nameusapien. Sed viverralacus.
+  this_is_a_very_long_long_word_which_has_a_length_higher_than_the_max_column
+  Donecquisipsum. Nunc cursus aliquet lectus. Nunc vitae eros.
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/3_result_2.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+Lorem ip<!-- aaa -->sum dolorsitamet, consectetuer adipiscing elit. 
+Nameusapien. Sed viverralacus. 
+this_is_a_very_long_long_word_which_has_a_length_higher_than_the_max_column
+ Donecquisipsum. Nunc cursus aliquet lectus. Nunc vitae eros.
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_original.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="http://mozilla.org/ns" xmlns:falsexul="http://mozilla.org/ns3">
+    <!-- document to test namespaces-->
+    <baz /> 
+    <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+        <mozilla xmlns="http://mozilla.org/ns2"> a a a <moz>a a</moz> éèàùûî</mozilla>
+        <firefox>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</firefox>
+    </bar>
+    
+    <xul xmlns="http://mozilla.org/ns3" xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description other:yes="no">xul fake</description>
+      </box>
+    </xul>
+
+    <falsexul:xul xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description>xul fake</description>
+        <what xmlns="http://mozilla.org/ns/other">lorem ipsum <falsexul:label value="hello" /> the return</what>
+      </box>
+    </falsexul:xul>
+
+    <ho:xul xmlns="http://mozilla.org/ns4" xmlns:ho="http://mozilla.org/ns4" xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description ho:foo="bar" bla="hello" other:yes="no" ho:foo2="bar2">xul fake</description>
+      </box>
+    </ho:xul>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_1.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="http://mozilla.org/ns" xmlns:falsexul="http://mozilla.org/ns3">
+    <!-- document to test namespaces-->
+    <baz/> 
+    <bar> &lt;robots&gt; &amp; &lt;aliens&gt;
+        <mozilla xmlns="http://mozilla.org/ns2"> a a a <moz>a a</moz> éèàùûî</mozilla>
+        <firefox>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</firefox>
+    </bar>
+    
+    <xul xmlns="http://mozilla.org/ns3" xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description other:yes="no">xul fake</description>
+      </box>
+    </xul>
+
+    <falsexul:xul xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description>xul fake</description>
+        <what xmlns="http://mozilla.org/ns/other">lorem ipsum <falsexul:label value="hello"/> the return</what>
+      </box>
+    </falsexul:xul>
+
+    <ho:xul xmlns="http://mozilla.org/ns4" xmlns:ho="http://mozilla.org/ns4" xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description ho:foo="bar" bla="hello" other:yes="no" ho:foo2="bar2">xul fake</description>
+      </box>
+    </ho:xul>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_2.xml
@@ -0,0 +1,7 @@
+<falsexul:xul xmlns:falsexul="http://mozilla.org/ns3" xmlns:other="http://mozilla.org/ns/other">
+      <box xmlns="http://mozilla.org/ns">
+        <other:what>lorem ipsum</other:what>
+        <description>xul fake</description>
+        <what xmlns="http://mozilla.org/ns/other">lorem ipsum <falsexul:label value="hello"/> the return</what>
+      </box>
+    </falsexul:xul>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_3.xml
@@ -0,0 +1,4 @@
+<box xmlns="http://mozilla.org/ns3">
+        <other:what xmlns:other="http://mozilla.org/ns/other">lorem ipsum</other:what>
+        <description other:yes="no" xmlns:other="http://mozilla.org/ns/other">xul fake</description>
+      </box>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_4.xml
@@ -0,0 +1,4 @@
+<box xmlns="http://mozilla.org/ns4">
+        <other:what xmlns:other="http://mozilla.org/ns/other">lorem ipsum</other:what>
+        <description ho:foo="bar" xmlns:ho="http://mozilla.org/ns4" bla="hello" other:yes="no" xmlns:other="http://mozilla.org/ns/other" ho:foo2="bar2">xul fake</description>
+      </box>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_5.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="http://mozilla.org/ns"
+  xmlns:falsexul="http://mozilla.org/ns3">
+  <!-- document to test namespaces-->
+  <baz/>
+  <bar> &lt;robots&gt; &amp;
+    &lt;aliens&gt;
+    <mozilla
+      xmlns="http://mozilla.org/ns2"> a
+      a a
+      <moz>a a</moz> éèàùûî</mozilla>
+    <firefox>Lorem ipsum dolor sit amet,
+      consectetuer adipiscing elit.</firefox>
+  </bar>
+  <xul xmlns="http://mozilla.org/ns3"
+xmlns:other="http://mozilla.org/ns/other">
+    <box>
+      <other:what>lorem ipsum</other:what>
+      <description other:yes="no">xul
+        fake</description>
+    </box>
+  </xul>
+  <falsexul:xul
+xmlns:other="http://mozilla.org/ns/other">
+    <box>
+      <other:what>lorem ipsum</other:what>
+      <description>xul fake</description>
+      <what
+        xmlns="http://mozilla.org/ns/other">lorem
+        ipsum
+        <falsexul:label value="hello"/>
+        the return</what>
+    </box>
+  </falsexul:xul>
+  <ho:xul xmlns="http://mozilla.org/ns4"
+    xmlns:ho="http://mozilla.org/ns4"
+xmlns:other="http://mozilla.org/ns/other">
+    <box>
+      <other:what>lorem ipsum</other:what>
+      <description ho:foo="bar"
+        bla="hello" other:yes="no"
+        ho:foo2="bar2">xul fake</description>
+    </box>
+  </ho:xul>
+</foo>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/4_result_6.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE whatever PUBLIC "-//MOZ//WHATEVER//EN" "http://mozilla.org/ns/foo">
+<foo xmlns="http://mozilla.org/ns" 
+xmlns:falsexul="http://mozilla.org/ns3">
+    <!-- document to test namespaces-->
+    <baz/> 
+    <bar> &lt;robots&gt; &amp; 
+&lt;aliens&gt;
+        <mozilla 
+xmlns="http://mozilla.org/ns2"> a a a <moz>a
+ a</moz> éèàùûî</mozilla>
+        <firefox>Lorem ipsum dolor sit 
+amet, consectetuer adipiscing elit.</firefox>
+    </bar>
+    
+    <xul xmlns="http://mozilla.org/ns3" 
+xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description other:yes="no">xul 
+fake</description>
+      </box>
+    </xul>
+
+    <falsexul:xul 
+xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description>xul fake</description>
+        <what 
+xmlns="http://mozilla.org/ns/other">lorem
+ ipsum <falsexul:label value="hello"/> 
+the return</what>
+      </box>
+    </falsexul:xul>
+
+    <ho:xul 
+xmlns="http://mozilla.org/ns4" 
+xmlns:ho="http://mozilla.org/ns4" 
+xmlns:other="http://mozilla.org/ns/other">
+      <box>
+        <other:what>lorem ipsum</other:what>
+        <description ho:foo="bar" 
+bla="hello" other:yes="no" 
+ho:foo2="bar2">xul fake</description>
+      </box>
+    </ho:xul>
+</foo>
\ No newline at end of file
--- a/content/base/test/unit/test_xmlserializer.js
+++ b/content/base/test/unit/test_xmlserializer.js
@@ -57,19 +57,78 @@ function run_test()
     result = xmlEncode("1_original.xml", de.OutputLFLineBreak);
     expected =loadContentFile("1_result.xml");
     do_check_eq(expected, result);
 
     result =  xmlEncode("2_original.xml", de.OutputLFLineBreak);
     expected = loadContentFile("2_result_1.xml");
     do_check_eq(expected, result);
 
-    result =  xmlEncode("2_original.xml", de.OutputLFLineBreak);
-    do_check_eq(expected, result);
-
     result =  xmlEncode("2_original.xml", de.OutputCRLineBreak);
     expected = expected.replace(/\n/g, "\r");
     do_check_eq(expected, result);
 
     result = xmlEncode("2_original.xml", de.OutputLFLineBreak | de.OutputCRLineBreak);
     expected = expected.replace(/\r/mg, "\r\n");
     do_check_eq(expected, result);
+
+    result =  xmlEncode("2_original.xml", de.OutputLFLineBreak | de.OutputFormatted);
+    expected = loadContentFile("2_result_2.xml");
+    do_check_eq(expected, result);
+
+    result =  xmlEncode("2_original.xml", de.OutputLFLineBreak | de.OutputFormatted | de.OutputWrap);
+    expected = loadContentFile("2_result_3.xml");
+    do_check_eq(expected, result);
+
+    result =  xmlEncode("2_original.xml", de.OutputLFLineBreak | de.OutputWrap);
+    expected = loadContentFile("2_result_4.xml");
+    do_check_eq(expected, result);
+
+    result =  xmlEncode("3_original.xml", de.OutputLFLineBreak | de.OutputFormatted | de.OutputWrap);
+    expected = loadContentFile("3_result.xml");
+    do_check_eq(expected, result);
+
+    result =  xmlEncode("3_original.xml", de.OutputLFLineBreak | de.OutputWrap);
+    expected = loadContentFile("3_result_2.xml");
+    do_check_eq(expected, result);
+
+    // tests on namespaces
+    var doc = do_parse_document("4_original.xml", "text/xml");
+
+    var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/xml"]
+                   .createInstance(nsIDocumentEncoder);
+    encoder.setCharset("UTF-8");
+    encoder.init(doc, "text/xml", de.OutputLFLineBreak);
+
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_1.xml");
+    do_check_eq(expected, result);
+
+    encoder.setNode(doc.documentElement.childNodes[9]);
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_2.xml");
+    do_check_eq(expected, result);
+
+    encoder.setNode(doc.documentElement.childNodes[7].childNodes[1]);
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_3.xml");
+    do_check_eq(expected, result);
+
+    encoder.setNode(doc.documentElement.childNodes[11].childNodes[1]);
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_4.xml");
+    do_check_eq(expected, result);
+
+    encoder.setCharset("UTF-8");
+    // it doesn't support this flags
+    encoder.init(doc, "text/xml",  de.OutputLFLineBreak | de.OutputFormatted | de.OutputWrap);
+    encoder.setWrapColumn(40);
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_5.xml");
+    do_check_eq(expected, result);
+
+    encoder.init(doc, "text/xml",  de.OutputLFLineBreak | de.OutputWrap);
+    encoder.setWrapColumn(40);
+    result = encoder.encodeToString();
+    expected = loadContentFile("4_result_6.xml");
+    do_check_eq(expected, result);
+
 }
--- a/embedding/test/test_bug293834.html
+++ b/embedding/test/test_bug293834.html
@@ -37,22 +37,22 @@ function fillform(doc) {
     doc.getElementById('a-checkbox').checked = true;
     doc.getElementById("radioa").checked = true;
     doc.getElementById("aselect").selectedIndex = 0;
 }
 
 function checkform(doc) {
     for (var i in textareas) {
         var textContent = doc.getElementById(textareas[i]).textContent;
-        ok(/form state/.test(textContent),
+        ok(/form\s+state/m.test(textContent),
             "Modified textarea "+textareas[i]+" form state not preserved!");
     }
     for (var i in textboxes) {
         var value = doc.getElementById(textboxes[i]).value;
-        ok(/form state/.test(value),
+        ok(/form\s+state/m.test(value),
             "Modified textbox "+textboxes[i]+" form state not preserved!");
     }
     ok(doc.getElementById('a-checkbox').checked,
         "Modified checkbox checked state not preserved!");
     ok(doc.getElementById("radioa").checked,
         "Modified radio checked state not preserved!");
     ok(doc.getElementById("aselect").selectedIndex == 0,
         "Modified select selected index not preserved");
--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -181,16 +181,20 @@
 // {ECEA1B28-AE54-4047-8BBE-C624235106B4}
 #define NS_COMPUTEDDOMSTYLE_CID \
 { 0xecea1b28, 0xae54, 0x4047, { 0x8b, 0xbe, 0xc6, 0x24, 0x23, 0x51, 0x06, 0xb4 } }
 
 // {4aef38b7-6364-4e23-a5e7-12f837fbbd9c}
 #define NS_XMLCONTENTSERIALIZER_CID \
 { 0x4aef38b7, 0x6364, 0x4e23, { 0xa5, 0xe7, 0x12, 0xf8, 0x37, 0xfb, 0xbd, 0x9c } }
 
+// {e7c2aaf5-c11a-4954-9dbf-e28edec1fd91}
+#define NS_XHTMLCONTENTSERIALIZER_CID \
+{ 0xe7c2aaf5, 0xc11a, 0x4954, { 0x9d, 0xbf, 0xe2, 0x8e, 0xde, 0xc1, 0xfd, 0x91 } }
+
 // {9d3f70da-86e9-11d4-95ec-00b0d03e37b7}
 #define NS_HTMLCONTENTSERIALIZER_CID \
 { 0x9d3f70da, 0x86e9, 0x11d4, { 0x95, 0xec, 0x00, 0xb0, 0xd0, 0x3e, 0x37, 0xb7 } }
 
 // {6030f7ef-32ed-46a7-9a63-6a5d3f90445f}
 #define NS_PLAINTEXTSERIALIZER_CID \
 { 0x6030f7ef, 0x32ed, 0x46a7, { 0x9a, 0x63, 0x6a, 0x5d, 0x3f, 0x90, 0x44, 0x5f } }
 
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -83,16 +83,17 @@
 #include "nsIRangeUtils.h"
 #include "nsIScriptNameSpaceManager.h"
 #include "nsISelection.h"
 #include "nsIXBLService.h"
 #include "nsCaret.h"
 #include "nsPlainTextSerializer.h"
 #include "mozSanitizingSerializer.h"
 #include "nsXMLContentSerializer.h"
+#include "nsXHTMLContentSerializer.h"
 #include "nsRuleNode.h"
 #include "nsWyciwygProtocolHandler.h"
 #include "nsContentAreaDragDrop.h"
 #include "nsContentList.h"
 #include "nsSyncLoadService.h"
 #include "nsBox.h"
 #include "nsIFrameTraversal.h"
 #include "nsLayoutCID.h"
@@ -490,16 +491,17 @@ MAKE_CTOR(CreateContentIterator,        
 MAKE_CTOR(CreatePreContentIterator,       nsIContentIterator,          NS_NewPreContentIterator)
 MAKE_CTOR(CreateSubtreeIterator,          nsIContentIterator,          NS_NewContentSubtreeIterator)
 // CreateHTMLImgElement, see below
 // CreateHTMLOptionElement, see below
 MAKE_CTOR(CreateTextEncoder,              nsIDocumentEncoder,          NS_NewTextEncoder)
 MAKE_CTOR(CreateHTMLCopyTextEncoder,      nsIDocumentEncoder,          NS_NewHTMLCopyTextEncoder)
 MAKE_CTOR(CreateXMLContentSerializer,     nsIContentSerializer,        NS_NewXMLContentSerializer)
 MAKE_CTOR(CreateHTMLContentSerializer,    nsIContentSerializer,        NS_NewHTMLContentSerializer)
+MAKE_CTOR(CreateXHTMLContentSerializer,   nsIContentSerializer,        NS_NewXHTMLContentSerializer)
 MAKE_CTOR(CreatePlainTextSerializer,      nsIContentSerializer,        NS_NewPlainTextSerializer)
 MAKE_CTOR(CreateHTMLFragmentSink,         nsIFragmentContentSink,      NS_NewHTMLFragmentContentSink)
 MAKE_CTOR(CreateHTMLFragmentSink2,        nsIFragmentContentSink,      NS_NewHTMLFragmentContentSink2)
 MAKE_CTOR(CreateHTMLParanoidFragmentSink, nsIFragmentContentSink,      NS_NewHTMLParanoidFragmentSink)
 MAKE_CTOR(CreateXMLFragmentSink,          nsIFragmentContentSink,      NS_NewXMLFragmentContentSink)
 MAKE_CTOR(CreateXMLFragmentSink2,         nsIFragmentContentSink,      NS_NewXMLFragmentContentSink2)
 MAKE_CTOR(CreateXHTMLParanoidFragmentSink,nsIFragmentContentSink,      NS_NewXHTMLParanoidFragmentSink)
 MAKE_CTOR(CreateSanitizingHTMLSerializer, nsIContentSerializer,        NS_NewSanitizingHTMLSerializer)
@@ -1025,17 +1027,17 @@ static const nsModuleComponentInfo gComp
     NS_DOC_ENCODER_CONTRACTID_BASE "text/xml",
     CreateTextEncoder },
 
   { "XML document encoder",
     NS_TEXT_ENCODER_CID,
     NS_DOC_ENCODER_CONTRACTID_BASE "application/xml",
     CreateTextEncoder },
 
-  { "XML document encoder",
+  { "XHTML document encoder",
     NS_TEXT_ENCODER_CID,
     NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml",
     CreateTextEncoder },
 
 #ifdef MOZ_SVG
   { "SVG document encoder",
     NS_TEXT_ENCODER_CID,
     NS_DOC_ENCODER_CONTRACTID_BASE "image/svg+xml",
@@ -1062,20 +1064,20 @@ static const nsModuleComponentInfo gComp
     NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "text/xml",
     CreateXMLContentSerializer },
 
   { "XML content serializer",
     NS_XMLCONTENTSERIALIZER_CID,
     NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "application/xml",
     CreateXMLContentSerializer },
 
-  { "XML content serializer",
-    NS_XMLCONTENTSERIALIZER_CID,
+  { "XHTML content serializer",
+    NS_XHTMLCONTENTSERIALIZER_CID,
     NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "application/xhtml+xml",
-    CreateXMLContentSerializer },
+    CreateXHTMLContentSerializer },
 
 #ifdef MOZ_SVG
   { "SVG content serializer",
     NS_XMLCONTENTSERIALIZER_CID,
     NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "image/svg+xml",
     CreateXMLContentSerializer },
 #endif