зеркало из https://github.com/mozilla/gecko-dev.git
Bug 45627 and bug 45552. XMLSerializer to deal better with empty elements, special characters, elements from the HTML namespace and namespaces in general, and processing instructions. Removed a lot of duplicate code in XML Extras component, and made several small optimizations with nsCOMPtr initializations. r=vidur, a=jst.
This commit is contained in:
Родитель
6ae78af1a6
Коммит
1d17a728f1
|
@ -22,40 +22,21 @@
|
||||||
|
|
||||||
#include "nsDOMSerializer.h"
|
#include "nsDOMSerializer.h"
|
||||||
#include "nsIDOMNode.h"
|
#include "nsIDOMNode.h"
|
||||||
#include "nsIDOMElement.h"
|
#include "nsIDOMRange.h"
|
||||||
#include "nsIDOMDocumentType.h"
|
|
||||||
#include "nsIDOMText.h"
|
|
||||||
#include "nsIDOMCDATASection.h"
|
|
||||||
#include "nsIDOMComment.h"
|
|
||||||
#include "nsIDOMProcessingInstruction.h"
|
|
||||||
#include "nsIDOMNamedNodeMap.h"
|
|
||||||
#include "nsIDOMAttr.h"
|
|
||||||
#include "nsIDOMNodeList.h"
|
|
||||||
|
|
||||||
#include "nsIOutputStream.h"
|
#include "nsIOutputStream.h"
|
||||||
#include "nsIUnicodeEncoder.h"
|
|
||||||
#include "nsIServiceManager.h"
|
|
||||||
#include "nsICharsetConverterManager.h"
|
|
||||||
|
|
||||||
#define USE_NSICONTENT
|
|
||||||
#ifdef USE_NSICONTENT
|
|
||||||
#include "nsIContent.h"
|
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsINameSpaceManager.h"
|
#include "nsIDOMDocument.h"
|
||||||
#endif
|
#include "nsIDocumentEncoder.h"
|
||||||
|
#include "nsIComponentManager.h"
|
||||||
|
#include "nsIContentSerializer.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
#include "nsLayoutCID.h" // XXX Need range CID
|
||||||
|
static NS_DEFINE_CID(kRangeCID,NS_RANGE_CID);
|
||||||
typedef struct {
|
|
||||||
nsString mPrefix;
|
|
||||||
nsString mURI;
|
|
||||||
nsIDOMElement* mOwner;
|
|
||||||
} NameSpaceDecl;
|
|
||||||
|
|
||||||
nsDOMSerializer::nsDOMSerializer()
|
nsDOMSerializer::nsDOMSerializer()
|
||||||
{
|
{
|
||||||
NS_INIT_ISUPPORTS();
|
NS_INIT_ISUPPORTS();
|
||||||
mPrefixIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDOMSerializer::~nsDOMSerializer()
|
nsDOMSerializer::~nsDOMSerializer()
|
||||||
|
@ -64,582 +45,85 @@ nsDOMSerializer::~nsDOMSerializer()
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsDOMSerializer, nsIDOMSerializer, nsISecurityCheckedComponent)
|
NS_IMPL_ISUPPORTS2(nsDOMSerializer, nsIDOMSerializer, nsISecurityCheckedComponent)
|
||||||
|
|
||||||
void
|
static nsresult SetUpEncoder(nsIDOMNode *aRoot, const char* aCharset, nsIDocumentEncoder **aEncoder)
|
||||||
nsDOMSerializer::SerializeText(nsIDOMText* aText, nsString& aStr)
|
|
||||||
{
|
{
|
||||||
nsAutoString data;
|
*aEncoder = nsnull;
|
||||||
if (aText) {
|
|
||||||
aText->GetData(data);
|
|
||||||
aStr.Append(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::SerializeCDATASection(nsIDOMCDATASection* aCDATASection,
|
|
||||||
nsString& aStr)
|
|
||||||
{
|
|
||||||
nsAutoString data;
|
|
||||||
if (aCDATASection) {
|
|
||||||
aCDATASection->GetData(data);
|
|
||||||
aStr.AppendWithConversion("<![CDATA[");
|
|
||||||
aStr.Append(data);
|
|
||||||
aStr.AppendWithConversion("]]>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::SerializeProcessingInstruction(nsIDOMProcessingInstruction* aPI,
|
|
||||||
nsString& aStr)
|
|
||||||
{
|
|
||||||
nsAutoString target, data;
|
|
||||||
if (aPI) {
|
|
||||||
aStr.AppendWithConversion("<?");
|
|
||||||
aPI->GetTarget(target);
|
|
||||||
aStr.Append(target);
|
|
||||||
aPI->GetData(data);
|
|
||||||
if (data.Length() > 0) {
|
|
||||||
aStr.AppendWithConversion(" ");
|
|
||||||
aStr.Append(data);
|
|
||||||
}
|
|
||||||
aStr.AppendWithConversion(">");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::SerializeComment(nsIDOMComment* aComment,
|
|
||||||
nsString& aStr)
|
|
||||||
{
|
|
||||||
nsAutoString data;
|
|
||||||
if (aComment) {
|
|
||||||
aStr.AppendWithConversion("<!--");
|
|
||||||
aComment->GetData(data);
|
|
||||||
aStr.Append(data);
|
|
||||||
aStr.AppendWithConversion("-->");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::SerializeDoctype(nsIDOMDocumentType* aDoctype,
|
|
||||||
nsString& aStr)
|
|
||||||
{
|
|
||||||
if (aDoctype) {
|
|
||||||
nsAutoString name, publicId, systemId, internalSubset;
|
|
||||||
|
|
||||||
aDoctype->GetName(name);
|
|
||||||
aDoctype->GetPublicId(publicId);
|
|
||||||
aDoctype->GetSystemId(systemId);
|
|
||||||
aDoctype->GetInternalSubset(internalSubset);
|
|
||||||
|
|
||||||
aStr.AppendWithConversion("<!DOCTYPE ");
|
|
||||||
aStr.Append(name);
|
|
||||||
if (publicId.Length() > 0) {
|
|
||||||
aStr.AppendWithConversion(" PUBLIC \"");
|
|
||||||
aStr.Append(publicId);
|
|
||||||
aStr.AppendWithConversion("\" \"");
|
|
||||||
aStr.Append(systemId);
|
|
||||||
aStr.AppendWithConversion("\"");
|
|
||||||
}
|
|
||||||
else if (systemId.Length() > 0) {
|
|
||||||
aStr.AppendWithConversion(" SYSTEM \"");
|
|
||||||
aStr.Append(systemId);
|
|
||||||
aStr.AppendWithConversion("\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (internalSubset.Length() > 0) {
|
|
||||||
aStr.AppendWithConversion(" ");
|
|
||||||
aStr.Append(internalSubset);
|
|
||||||
}
|
|
||||||
|
|
||||||
aStr.AppendWithConversion(">");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const char* kXMLNS = "xmlns";
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::PushNameSpaceDecl(nsString& aPrefix,
|
|
||||||
nsString& aURI,
|
|
||||||
nsIDOMElement* aOwner)
|
|
||||||
{
|
|
||||||
NameSpaceDecl* decl = new NameSpaceDecl();
|
|
||||||
if (decl) {
|
|
||||||
decl->mPrefix.Assign(aPrefix);
|
|
||||||
decl->mURI.Assign(aURI);
|
|
||||||
// Don't addref - this weak reference will be removed when
|
|
||||||
// we pop the stack
|
|
||||||
decl->mOwner = aOwner;
|
|
||||||
|
|
||||||
mNameSpaceStack.AppendElement((void*)decl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::PopNameSpaceDeclsFor(nsIDOMElement* aOwner)
|
|
||||||
{
|
|
||||||
PRInt32 index, count;
|
|
||||||
|
|
||||||
count = mNameSpaceStack.Count();
|
|
||||||
for (index = count; index >= 0; index--) {
|
|
||||||
NameSpaceDecl* decl = (NameSpaceDecl*)mNameSpaceStack.ElementAt(index);
|
|
||||||
if (decl) {
|
|
||||||
if (decl->mOwner != aOwner) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mNameSpaceStack.RemoveElementAt(index);
|
|
||||||
delete decl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool
|
|
||||||
nsDOMSerializer::ConfirmPrefix(nsString& aPrefix,
|
|
||||||
nsString& aURI)
|
|
||||||
{
|
|
||||||
if (aPrefix.EqualsWithConversion(kXMLNS)) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
if (aURI.Length() == 0) {
|
|
||||||
aPrefix.Truncate();
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
PRInt32 index, count;
|
|
||||||
nsAutoString closestURIMatch;
|
|
||||||
PRBool uriMatch = PR_FALSE;
|
|
||||||
|
|
||||||
count = mNameSpaceStack.Count();
|
|
||||||
for (index = count; index >= 0; index--) {
|
|
||||||
NameSpaceDecl* decl = (NameSpaceDecl*)mNameSpaceStack.ElementAt(index);
|
|
||||||
if (decl) {
|
|
||||||
// Check if we've found a prefix match
|
|
||||||
if (aPrefix.Equals(decl->mPrefix)) {
|
|
||||||
|
|
||||||
// If the URI's match, we don't have to add a namespace decl
|
|
||||||
if (aURI.Equals(decl->mURI)) {
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
// If they don't, we can't use this prefix
|
|
||||||
else {
|
|
||||||
aPrefix.Truncate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we've found a URI match, then record the first one
|
|
||||||
else if (!uriMatch && aURI.Equals(decl->mURI)) {
|
|
||||||
uriMatch = PR_TRUE;
|
|
||||||
closestURIMatch.Assign(decl->mPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are no namespace declarations that match the prefix, uri pair.
|
|
||||||
// If there's another prefix that matches that URI, us it.
|
|
||||||
if (uriMatch) {
|
|
||||||
aPrefix.Assign(closestURIMatch);
|
|
||||||
return PR_FALSE;
|
|
||||||
}
|
|
||||||
// If we don't have a prefix, create one
|
|
||||||
else if (aPrefix.Length() == 0) {
|
|
||||||
aPrefix.AssignWithConversion("a");
|
|
||||||
aPrefix.AppendInt(mPrefixIndex++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicate that we need to create a namespace decl for the
|
|
||||||
// final prefix
|
|
||||||
return PR_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDOMSerializer::SerializeAttr(nsString& aPrefix,
|
|
||||||
nsString& aName,
|
|
||||||
nsString& aValue,
|
|
||||||
nsString& aStr)
|
|
||||||
{
|
|
||||||
aStr.AppendWithConversion(" ");
|
|
||||||
if (aPrefix.Length() > 0) {
|
|
||||||
aStr.Append(aPrefix);
|
|
||||||
aStr.AppendWithConversion(":");
|
|
||||||
}
|
|
||||||
aStr.Append(aName);
|
|
||||||
|
|
||||||
aStr.AppendWithConversion("=\"");
|
nsresult rv;
|
||||||
aStr.Append(aValue);
|
nsCOMPtr<nsIDocumentEncoder> encoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/xml",&rv));
|
||||||
aStr.AppendWithConversion("\"");
|
if (NS_FAILED(rv))
|
||||||
}
|
return rv;
|
||||||
|
|
||||||
void
|
PRBool entireDocument = PR_TRUE;
|
||||||
nsDOMSerializer::SerializeElementStart(nsIDOMElement* aElement, nsString& aStr)
|
nsCOMPtr<nsIDocument> document(do_QueryInterface(aRoot));
|
||||||
{
|
if (!document) {
|
||||||
if (aElement) {
|
entireDocument = PR_FALSE;
|
||||||
nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||||
nsAutoString xmlnsStr, defaultnsStr;
|
rv = aRoot->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||||
xmlnsStr.AssignWithConversion(kXMLNS);
|
if (NS_FAILED(rv))
|
||||||
defaultnsStr.AssignWithConversion("");
|
return rv;
|
||||||
|
document = do_QueryInterface(domDoc);
|
||||||
aElement->GetPrefix(tagPrefix);
|
|
||||||
aElement->GetLocalName(tagLocalName);
|
|
||||||
aElement->GetNamespaceURI(tagNamespaceURI);
|
|
||||||
|
|
||||||
#ifdef USE_NSICONTENT
|
|
||||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
|
||||||
PRInt32 index, count;
|
|
||||||
nsAutoString nameStr, prefixStr, uriStr, valueStr;
|
|
||||||
PRInt32 namespaceID;
|
|
||||||
nsCOMPtr<nsIAtom> attrName, attrPrefix;
|
|
||||||
if (content) {
|
|
||||||
content->GetAttributeCount(count);
|
|
||||||
|
|
||||||
// First scan for namespace declarations, pushing each on the stack
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
|
|
||||||
content->GetAttributeNameAt(index,
|
|
||||||
namespaceID,
|
|
||||||
*getter_AddRefs(attrName),
|
|
||||||
*getter_AddRefs(attrPrefix));
|
|
||||||
|
|
||||||
if (attrPrefix) {
|
|
||||||
attrPrefix->ToString(prefixStr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prefixStr.Truncate();
|
|
||||||
}
|
|
||||||
attrName->ToString(nameStr);
|
|
||||||
|
|
||||||
content->GetAttribute(namespaceID, attrName, uriStr);
|
|
||||||
if ((namespaceID == kNameSpaceID_XMLNS) ||
|
|
||||||
prefixStr.EqualsWithConversion(kXMLNS)) {
|
|
||||||
PushNameSpaceDecl(nameStr, uriStr, aElement);
|
|
||||||
}
|
|
||||||
else if (nameStr.EqualsWithConversion(kXMLNS)) {
|
|
||||||
PushNameSpaceDecl(defaultnsStr, uriStr, aElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
PRInt32 index, count;
|
|
||||||
nsAutoString nameStr, prefixStr, uriStr, valueStr;
|
|
||||||
nsCOMPtr<nsIDOMNamedNodeMap> attrMap;
|
|
||||||
nsCOMPtr<nsIDOMNode> attrNode;
|
|
||||||
nsCOMPtr<nsIDOMAttr> attrObj;
|
|
||||||
|
|
||||||
aElement->GetAttributes(getter_AddRefs(attrMap));
|
|
||||||
if (attrMap) {
|
|
||||||
attrMap->GetLength((PRUint32*)&count);
|
|
||||||
|
|
||||||
// First scan for namespace declarations, pushing each on the stack
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
attrMap->Item(index, getter_AddRefs(attrNode));
|
|
||||||
attrObj = do_QueryInterface(attrNode);
|
|
||||||
if (attrObj) {
|
|
||||||
attrObj->GetPrefix(prefixStr);
|
|
||||||
attrObj->GetLocalName(nameStr);
|
|
||||||
attrObj->GetNamespaceURI(uriStr);
|
|
||||||
if (prefixStr.EqualsWithConversion(kXMLNS)) {
|
|
||||||
PushNameSpaceDecl(nameStr, uriStr, aElement);
|
|
||||||
}
|
|
||||||
else if (nameStr.EqualsWithConversion(kXMLNS)) {
|
|
||||||
PushNameSpaceDecl(nsAutoString(), uriStr, aElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool addNSAttr;
|
|
||||||
|
|
||||||
// Serialize the qualified name of the element
|
|
||||||
addNSAttr = ConfirmPrefix(tagPrefix, tagNamespaceURI);
|
|
||||||
aStr.AppendWithConversion("<");
|
|
||||||
if (tagPrefix.Length() > 0) {
|
|
||||||
aStr.Append(tagPrefix);
|
|
||||||
aStr.AppendWithConversion(":");
|
|
||||||
}
|
|
||||||
aStr.Append(tagLocalName);
|
|
||||||
|
|
||||||
// If we had to add a new namespace declaration, serialize
|
|
||||||
// and push it on the namespace stack
|
|
||||||
if (addNSAttr) {
|
|
||||||
SerializeAttr(xmlnsStr, tagPrefix, tagNamespaceURI, aStr);
|
|
||||||
PushNameSpaceDecl(tagPrefix, tagNamespaceURI, aElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_NSICONTENT
|
|
||||||
if (content) {
|
|
||||||
// Now serialize each of the attributes
|
|
||||||
// XXX Unfortunately we need a namespace manager to get
|
|
||||||
// attribute URIs.
|
|
||||||
nsCOMPtr<nsIDocument> document;
|
|
||||||
nsCOMPtr<nsINameSpaceManager> nsmanager;
|
|
||||||
content->GetDocument(*getter_AddRefs(document));
|
|
||||||
if (document) {
|
|
||||||
document->GetNameSpaceManager(*getter_AddRefs(nsmanager));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
content->GetAttributeNameAt(index,
|
|
||||||
namespaceID,
|
|
||||||
*getter_AddRefs(attrName),
|
|
||||||
*getter_AddRefs(attrPrefix));
|
|
||||||
if (attrPrefix) {
|
|
||||||
attrPrefix->ToString(prefixStr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prefixStr.Truncate();
|
|
||||||
}
|
|
||||||
|
|
||||||
addNSAttr = PR_FALSE;
|
|
||||||
if (kNameSpaceID_XMLNS == namespaceID) {
|
|
||||||
prefixStr.AssignWithConversion(kXMLNS);
|
|
||||||
}
|
|
||||||
else if (nsmanager) {
|
|
||||||
nsmanager->GetNameSpaceURI(namespaceID, uriStr);
|
|
||||||
addNSAttr = ConfirmPrefix(prefixStr, uriStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
content->GetAttribute(namespaceID, attrName, valueStr);
|
|
||||||
attrName->ToString(nameStr);
|
|
||||||
|
|
||||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr);
|
|
||||||
|
|
||||||
if (addNSAttr) {
|
|
||||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr);
|
|
||||||
PushNameSpaceDecl(prefixStr, uriStr, aElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (attrMap) {
|
|
||||||
// Now serialize each of the attributes
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
aStr.AppendWithConversion(" ");
|
|
||||||
attrMap->Item(index, getter_AddRefs(attrNode));
|
|
||||||
attrObj = do_QueryInterface(attrNode);
|
|
||||||
if (attrObj) {
|
|
||||||
attrObj->GetPrefix(prefixStr);
|
|
||||||
attrObj->GetLocalName(nameStr);
|
|
||||||
attrObj->GetNamespaceURI(uriStr);
|
|
||||||
|
|
||||||
addNSAttr = ConfirmPrefix(prefixStr, uriStr);
|
|
||||||
attrObj->GetNodeValue(valueStr);
|
|
||||||
|
|
||||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr);
|
|
||||||
|
|
||||||
if (addNSAttr) {
|
|
||||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr);
|
|
||||||
PushNameSpaceDecl(prefixStr, uriStr, aElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
aStr.AppendWithConversion(">");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
// This method will fail if no document
|
||||||
nsDOMSerializer::SerializeElementEnd(nsIDOMElement* aElement, nsString& aStr)
|
rv = encoder->Init(document,NS_LITERAL_STRING("text/xml"),nsIDocumentEncoder::OutputEncodeEntities);
|
||||||
{
|
if (NS_FAILED(rv))
|
||||||
if (aElement) {
|
return rv;
|
||||||
nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
|
|
||||||
|
|
||||||
aElement->GetPrefix(tagPrefix);
|
nsAutoString charset;
|
||||||
aElement->GetLocalName(tagLocalName);
|
if (aCharset) {
|
||||||
aElement->GetNamespaceURI(tagNamespaceURI);
|
charset.AssignWithConversion(aCharset);
|
||||||
|
} else {
|
||||||
ConfirmPrefix(tagPrefix, tagNamespaceURI);
|
rv = document->GetDocumentCharacterSet(charset);
|
||||||
aStr.AppendWithConversion("</");
|
if (NS_FAILED(rv))
|
||||||
if (tagPrefix.Length() > 0) {
|
return rv;
|
||||||
aStr.Append(tagPrefix);
|
|
||||||
aStr.AppendWithConversion(":");
|
|
||||||
}
|
|
||||||
aStr.Append(tagLocalName);
|
|
||||||
aStr.AppendWithConversion(">");
|
|
||||||
|
|
||||||
PopNameSpaceDeclsFor(aElement);
|
|
||||||
}
|
}
|
||||||
}
|
rv = encoder->SetCharset(charset);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
// If we are working on the entire document we do not need to specify which part to serialize
|
||||||
nsresult
|
if (!entireDocument) {
|
||||||
nsDOMSerializer::SerializeNodeStart(nsIDOMNode* aNode, nsString& aStr)
|
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID));
|
||||||
{
|
rv = range->SelectNode(aRoot);
|
||||||
PRUint16 type;
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = encoder->SetRange(range);
|
||||||
aNode->GetNodeType(&type);
|
|
||||||
switch (type) {
|
|
||||||
case nsIDOMNode::ELEMENT_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
|
||||||
SerializeElementStart(element, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIDOMNode::TEXT_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMText> text = do_QueryInterface(aNode);
|
|
||||||
SerializeText(text, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMCDATASection> cdata = do_QueryInterface(aNode);
|
|
||||||
SerializeCDATASection(cdata, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMProcessingInstruction> pi = do_QueryInterface(aNode);
|
|
||||||
SerializeProcessingInstruction(pi, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIDOMNode::COMMENT_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMComment> comment = do_QueryInterface(aNode);
|
|
||||||
SerializeComment(comment, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIDOMNode::DOCUMENT_TYPE_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMDocumentType> doctype = do_QueryInterface(aNode);
|
|
||||||
SerializeDoctype(doctype, aStr);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
if (NS_SUCCEEDED(rv)) {
|
||||||
nsDOMSerializer::SerializeNodeEnd(nsIDOMNode* aNode, nsString& aStr)
|
*aEncoder = encoder.get();
|
||||||
{
|
NS_ADDREF(*aEncoder);
|
||||||
PRUint16 type;
|
|
||||||
|
|
||||||
aNode->GetNodeType(&type);
|
|
||||||
switch (type) {
|
|
||||||
case nsIDOMNode::ELEMENT_NODE:
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
|
||||||
SerializeElementEnd(element, aStr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsDOMSerializer::SerializeToStringRecursive(nsIDOMNode* aNode, nsString& aStr)
|
|
||||||
{
|
|
||||||
nsresult rv = SerializeNodeStart(aNode, aStr);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
|
||||||
rv = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (childNodes) {
|
|
||||||
PRInt32 index, count;
|
|
||||||
|
|
||||||
childNodes->GetLength((PRUint32*)&count);
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
nsCOMPtr<nsIDOMNode> child;
|
|
||||||
|
|
||||||
rv = childNodes->Item(index, getter_AddRefs(child));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = SerializeToStringRecursive(child, aStr);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = SerializeNodeEnd(aNode, aStr);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMSerializer::SerializeToString(nsIDOMNode *root, PRUnichar **_retval)
|
nsDOMSerializer::SerializeToString(nsIDOMNode *root, PRUnichar **_retval)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(root);
|
NS_ENSURE_ARG_POINTER(root);
|
||||||
NS_ENSURE_ARG_POINTER(_retval);
|
NS_ENSURE_ARG_POINTER(_retval);
|
||||||
nsresult rv;
|
|
||||||
nsAutoString str;
|
*_retval = nsnull;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocumentEncoder> encoder;
|
||||||
|
nsresult rv = SetUpEncoder(root,nsnull,getter_AddRefs(encoder));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
nsAutoString str;
|
||||||
|
rv = encoder->EncodeToString(str);
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
rv = SerializeToStringRecursive(root, str);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
*_retval = str.ToNewUnicode();
|
*_retval = str.ToNewUnicode();
|
||||||
if (nsnull == *_retval) {
|
if (!*_retval)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
|
||||||
ConvertAndWrite(nsString& aString,
|
|
||||||
nsIOutputStream* aStream,
|
|
||||||
nsIUnicodeEncoder* aEncoder)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aStream);
|
|
||||||
NS_ENSURE_ARG_POINTER(aEncoder);
|
|
||||||
nsresult rv;
|
|
||||||
PRInt32 charLength;
|
|
||||||
PRUnichar* unicodeBuf = (PRUnichar*)aString.GetUnicode();
|
|
||||||
PRInt32 unicodeLength = aString.Length();
|
|
||||||
|
|
||||||
rv = aEncoder->GetMaxLength(unicodeBuf, unicodeLength, &charLength);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
nsCAutoString charXferString;
|
|
||||||
charXferString.SetCapacity(charLength);
|
|
||||||
char* charXferBuf = (char*)charXferString.GetBuffer();
|
|
||||||
|
|
||||||
rv = aEncoder->Convert(unicodeBuf, &unicodeLength, charXferBuf, &charLength);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
PRUint32 written;
|
|
||||||
rv = aStream->Write(charXferBuf, charLength, &written);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsDOMSerializer::SerializeToStreamRecursive(nsIDOMNode* aNode,
|
|
||||||
nsIOutputStream* aStream,
|
|
||||||
nsIUnicodeEncoder* aEncoder)
|
|
||||||
{
|
|
||||||
nsAutoString start;
|
|
||||||
nsresult rv = SerializeNodeStart(aNode, start);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = ConvertAndWrite(start, aStream, aEncoder);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
|
||||||
rv = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (childNodes) {
|
|
||||||
PRInt32 index, count;
|
|
||||||
|
|
||||||
childNodes->GetLength((PRUint32*)&count);
|
|
||||||
for (index = 0; index < count; index++) {
|
|
||||||
nsCOMPtr<nsIDOMNode> child;
|
|
||||||
|
|
||||||
rv = childNodes->Item(index, getter_AddRefs(child));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = SerializeToStreamRecursive(child, aStream, aEncoder);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoString end;
|
|
||||||
rv = SerializeNodeEnd(aNode, end);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = ConvertAndWrite(end, aStream, aEncoder);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMSerializer::SerializeToStream(nsIDOMNode *root,
|
nsDOMSerializer::SerializeToStream(nsIDOMNode *root,
|
||||||
nsIOutputStream *stream,
|
nsIOutputStream *stream,
|
||||||
|
@ -649,24 +133,12 @@ nsDOMSerializer::SerializeToStream(nsIDOMNode *root,
|
||||||
NS_ENSURE_ARG_POINTER(stream);
|
NS_ENSURE_ARG_POINTER(stream);
|
||||||
NS_ENSURE_ARG_POINTER(charset);
|
NS_ENSURE_ARG_POINTER(charset);
|
||||||
|
|
||||||
nsresult rv;
|
nsCOMPtr<nsIDocumentEncoder> encoder;
|
||||||
nsCOMPtr<nsIUnicodeEncoder> encoder;
|
nsresult rv = SetUpEncoder(root,charset,getter_AddRefs(encoder));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
return rv;
|
||||||
|
|
||||||
NS_WITH_SERVICE(nsICharsetConverterManager,
|
return encoder->EncodeToStream(stream);
|
||||||
charsetConv,
|
|
||||||
kCharsetConverterManagerCID,
|
|
||||||
&rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsAutoString charsetStr;
|
|
||||||
charsetStr.AssignWithConversion(charset);
|
|
||||||
rv = charsetConv->GetUnicodeEncoder(&charsetStr,
|
|
||||||
getter_AddRefs(encoder));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = SerializeToStreamRecursive(root, stream, encoder);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* kAllAccess = "AllAccess";
|
static const char* kAllAccess = "AllAccess";
|
||||||
|
|
|
@ -26,17 +26,6 @@
|
||||||
#include "nsIDOMSerializer.h"
|
#include "nsIDOMSerializer.h"
|
||||||
#include "nsISecurityCheckedComponent.h"
|
#include "nsISecurityCheckedComponent.h"
|
||||||
#include "nsISupportsUtils.h"
|
#include "nsISupportsUtils.h"
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsVoidArray.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
|
|
||||||
class nsIDOMElement;
|
|
||||||
class nsIDOMDocumentType;
|
|
||||||
class nsIDOMText;
|
|
||||||
class nsIDOMCDATASection;
|
|
||||||
class nsIDOMComment;
|
|
||||||
class nsIDOMProcessingInstruction;
|
|
||||||
class nsIUnicodeEncoder;
|
|
||||||
|
|
||||||
class nsDOMSerializer : public nsIDOMSerializer,
|
class nsDOMSerializer : public nsIDOMSerializer,
|
||||||
public nsISecurityCheckedComponent
|
public nsISecurityCheckedComponent
|
||||||
|
@ -54,36 +43,6 @@ public:
|
||||||
const char *charset);
|
const char *charset);
|
||||||
|
|
||||||
NS_DECL_NSISECURITYCHECKEDCOMPONENT
|
NS_DECL_NSISECURITYCHECKEDCOMPONENT
|
||||||
|
|
||||||
protected:
|
|
||||||
void SerializeText(nsIDOMText* aText, nsString& aStr);
|
|
||||||
void SerializeCDATASection(nsIDOMCDATASection* aCDATASection, nsString& aStr);
|
|
||||||
void SerializeProcessingInstruction(nsIDOMProcessingInstruction* aPI,
|
|
||||||
nsString& aStr);
|
|
||||||
void SerializeComment(nsIDOMComment* aComment, nsString& aStr);
|
|
||||||
void SerializeDoctype(nsIDOMDocumentType* aDoctype, nsString& aStr);
|
|
||||||
void PushNameSpaceDecl(nsString& aPrefix,
|
|
||||||
nsString& aURI,
|
|
||||||
nsIDOMElement* aOwner);
|
|
||||||
void PopNameSpaceDeclsFor(nsIDOMElement* aOwner);
|
|
||||||
PRBool ConfirmPrefix(nsString& aPrefix,
|
|
||||||
nsString& aURI);
|
|
||||||
void SerializeAttr(nsString& aPrefix,
|
|
||||||
nsString& aName,
|
|
||||||
nsString& aValue,
|
|
||||||
nsString& aStr);
|
|
||||||
void SerializeElementStart(nsIDOMElement* aElement, nsString& aStr);
|
|
||||||
void SerializeElementEnd(nsIDOMElement* aElement, nsString& aStr);
|
|
||||||
nsresult SerializeNodeStart(nsIDOMNode* aNode, nsString& aStr);
|
|
||||||
nsresult SerializeNodeEnd(nsIDOMNode* aNode, nsString& aStr);
|
|
||||||
nsresult SerializeToStringRecursive(nsIDOMNode* aNode, nsString& aStr);
|
|
||||||
nsresult SerializeToStreamRecursive(nsIDOMNode* aNode,
|
|
||||||
nsIOutputStream* aStream,
|
|
||||||
nsIUnicodeEncoder* aEncoder);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
PRInt32 mPrefixIndex;
|
|
||||||
nsVoidArray mNameSpaceStack;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче