void 
nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
                                             nsIDOMElement *aOriginalElement,
                                             nsAString& aTagPrefix,
                                             const nsAString& aTagNamespaceURI,
                                             nsIAtom* aTagName,
                                             nsAString& aStr)
{
  PRInt32 count = aContent->GetAttrCount();
  if (!count)
    return;

  nsresult rv;
  nsAutoString nameStr, valueStr;
  NS_NAMED_LITERAL_STRING(_mozStr, "_moz");

  // HTML5 parser stored them in the order they were parsed so we want to
  // loop forward in that case.
  nsIDocument* doc = aContent->GetOwnerDocument();
  PRBool caseSensitive = doc && doc->IsCaseSensitive();
  PRBool loopForward = PR_FALSE;
  if (!caseSensitive) {
    nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
    if (htmlDoc) {
      loopForward = nsHtml5Module::sEnabled;
    }
  }
  PRInt32 index, limit, step;
  if (loopForward) {
    index = 0;
    limit = count;
    step = 1;
  }
  else {
    // Loop backward over the attributes, since the order they are stored in is
    // the opposite of the order they were parsed in (see bug 213347 for reason).
    index = count - 1;
    limit = -1;
    step = -1;
  }
  
  for (; index != limit; index += step) {
    const nsAttrName* name = aContent->GetAttrNameAt(index);
    PRInt32 namespaceID = name->NamespaceID();
    nsIAtom* attrName = name->LocalName();

    // 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;
    }
    aContent->GetAttr(namespaceID, attrName, valueStr);

    // 
    // Filter out special case of <br type="_moz"> or <br _moz*>,
    // used by the editor.  Bug 16988.  Yuck.
    //
    if (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;
    }
    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.
        // 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 (mRewriteEncodingDeclaration && 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);

    // Expand shorthand attribute.
    if (IsShorthandAttr(attrName, aTagName) && valueStr.IsEmpty()) {
      valueStr = nameStr;
    }
    SerializeAttr(EmptyString(), nameStr, valueStr, aStr, !isJS);
  }
}
NS_IMETHODIMP 
nsXMLContentSerializer::AppendElementStart(nsIDOMElement *aElement,
                                           nsIDOMElement *aOriginalElement,
                                           nsAString& aStr)
{
  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();

  // 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);
    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);

      if (!name->GetPrefix()) {
        if (tagNamespaceURI.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.
          skipAttr = index;
        }
        else {
          // Default NS attribute does not have prefix (and the name is "xmlns")
          PushNameSpaceDecl(EmptyString(), uriStr, aOriginalElement);
        }
      }
      else {
        attrName->ToString(nameStr);
        PushNameSpaceDecl(nameStr, uriStr, aOriginalElement);
      }
    }
  }

  PRBool addNSAttr;
    
  MaybeAddNewline(aStr);

  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);
  }
  AppendToString(tagLocalName, aStr);
    
  // If we had to add a new namespace declaration, serialize
  // and push it on the namespace stack
  if (addNSAttr) {
    if (tagPrefix.IsEmpty()) {
      // Serialize default namespace decl
      SerializeAttr(EmptyString(), xmlnsStr, tagNamespaceURI, aStr, PR_TRUE);
    } else {
      // Serialize namespace decl
      SerializeAttr(xmlnsStr, tagPrefix, tagNamespaceURI, aStr, PR_TRUE);
    }
    PushNameSpaceDecl(tagPrefix, tagNamespaceURI, aOriginalElement);
  }

  // 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) {
        continue;
    }

    const nsAttrName* name = content->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;
    if (kNameSpaceID_XMLNS != namespaceID) {
      nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID, uriStr);
      addNSAttr = ConfirmPrefix(prefixStr, uriStr, aOriginalElement, PR_TRUE);
    }
    
    content->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.
    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);
    
    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;
  if (NS_FAILED(aOriginalElement->HasChildNodes(&hasChildren)) ||
      !hasChildren) {
    AppendToString(NS_LITERAL_STRING("/>"), aStr);    
    MaybeFlagNewline(aElement);
  } else {
    AppendToString(NS_LITERAL_STRING(">"), aStr);    
  }
  
  return NS_OK;
}
bool
nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
                                              nsIContent *aOriginalElement,
                                              nsAString& aTagPrefix,
                                              const nsAString& aTagNamespaceURI,
                                              nsIAtom* aTagName,
                                              nsAString& aStr,
                                              uint32_t aSkipAttr,
                                              bool aAddNSAttr)
{
  nsresult rv;
  uint32_t index, count;
  nsAutoString prefixStr, uriStr, valueStr;
  nsAutoString xmlnsStr;
  xmlnsStr.AssignLiteral(kXMLNS);

  int32_t 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;
      int32_t startAttrVal = 0;
      aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::start, start);
      if (!start.IsEmpty()) {
        nsresult rv = NS_OK;
        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, true);
      mOLStateStack.AppendElement(state);
    }
    else if (aTagName == nsGkAtoms::li) {
      mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
      if (mIsFirstChildOfOL) {
        // If OL is parent of this LI, serialize attributes in different manner.
        NS_ENSURE_TRUE(SerializeLIValueAttribute(aContent, aStr), false);
      }
    }
  }

  // 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
      NS_ENSURE_TRUE(SerializeAttr(EmptyString(), xmlnsStr,
                                   aTagNamespaceURI,
                                   aStr, true), false);
    } else {
      // Serialize namespace decl
      NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, aTagPrefix,
                                   aTagNamespaceURI,
                                   aStr, true), false);
    }
    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;
    }

    mozilla::dom::BorrowedAttrInfo info = aContent->GetAttrInfoAt(index);
    const nsAttrName* name = info.mName;

    int32_t namespaceID = name->NamespaceID();
    nsIAtom* attrName = name->LocalName();
    nsIAtom* attrPrefix = name->GetPrefix();

    // Filter out any attribute starting with [-|_]moz
    nsDependentAtomString attrNameStr(attrName);
    if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
        StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
      continue;
    }

    if (attrPrefix) {
      attrPrefix->ToString(prefixStr);
    }
    else {
      prefixStr.Truncate();
    }

    bool addNSAttr = false;
    if (kNameSpaceID_XMLNS != namespaceID) {
      nsContentUtils::NameSpaceManager()->GetNameSpaceURI(namespaceID, uriStr);
      addNSAttr = ConfirmPrefix(prefixStr, uriStr, aOriginalElement, true);
    }

    info.mValue->ToString(valueStr);

    nsDependentAtomString nameStr(attrName);
    bool isJS = 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 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;
            }
          }
        }
      }

      if (mRewriteEncodingDeclaration && 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);
    }

    NS_ENSURE_TRUE(SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS), false);

    if (addNSAttr) {
      NS_ASSERTION(!prefixStr.IsEmpty(),
                   "Namespaced attributes must have a prefix");
      NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true), false);
      PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
    }
  }

  return true;
}
void
nsHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
        nsIAtom* aTagName,
        nsAString& aStr)
{
    nsresult rv;
    PRUint32 index, count;
    nsAutoString nameStr, valueStr;

    count = aContent->GetAttrCount();

    NS_NAMED_LITERAL_STRING(_mozStr, "_moz");

    // Loop backward over the attributes, since the order they are stored in is
    // the opposite of the order they were parsed in (see bug 213347 for reason).
    // index is unsigned, hence index >= 0 is always true.
    for (index = count; index > 0; ) {
        --index;
        const nsAttrName* name = aContent->GetAttrNameAt(index);
        PRInt32 namespaceID = name->NamespaceID();
        nsIAtom* attrName = name->LocalName();

        // 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;
        }
        aContent->GetAttr(namespaceID, attrName, valueStr);

        //
        // Filter out special case of <br type="_moz"> or <br _moz*>,
        // used by the editor.  Bug 16988.  Yuck.
        //
        if (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;
        }
        PRBool isJS = IsJavaScript(attrName, 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.
                // 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(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);
    }
}