Back to index

lightning-sunbird  0.9+nobinonly
nsXMLContentBuilder.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mozilla XTF project.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Alex Fritze.
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alex Fritze <alex@croczilla.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsCOMPtr.h"
00040 #include "nsString.h"
00041 #include "nsIXMLContentBuilder.h"
00042 #include "nsISupportsArray.h"
00043 #include "nsINameSpaceManager.h"
00044 #include "nsINodeInfo.h"
00045 #include "nsIContent.h"
00046 #include "nsIComponentManager.h"
00047 #include "nsIServiceManager.h"
00048 #include "nsIAtom.h"
00049 #include "nsContentCID.h"
00050 #include "nsIDocument.h"
00051 #include "nsIDOMElement.h"
00052 #include "nsIDOMDocument.h"
00053 #include "nsIDOMText.h"
00054 #include "nsNodeInfoManager.h"
00055 #include "nsContentCreatorFunctions.h"
00056 #include "nsContentUtils.h"
00057 
00058 static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID);
00059 
00060 
00061 class nsXMLContentBuilder : public nsIXMLContentBuilder
00062 {
00063 protected:
00064   friend nsresult NS_NewXMLContentBuilder(nsIXMLContentBuilder** aResult);
00065   
00066   nsXMLContentBuilder();
00067   ~nsXMLContentBuilder();
00068   
00069 public:
00070   // nsISupports interface
00071   NS_DECL_ISUPPORTS
00072 
00073   // nsIXMLContentBuilder interface
00074   NS_DECL_NSIXMLCONTENTBUILDER
00075 
00076 private:
00077   void EnsureDoc();
00078   
00079   nsCOMPtr<nsIContent> mTop;
00080   nsCOMPtr<nsIContent> mCurrent;
00081   nsCOMPtr<nsIDocument> mDocument;
00082   PRInt32 mNamespaceId;
00083 };
00084 
00085 //----------------------------------------------------------------------
00086 // implementation:
00087 
00088 nsXMLContentBuilder::nsXMLContentBuilder()
00089     : mNamespaceId(kNameSpaceID_None)
00090 {
00091 #ifdef DEBUG
00092 //  printf("nsXMLContentBuilder CTOR\n");
00093 #endif
00094 }
00095 
00096 nsXMLContentBuilder::~nsXMLContentBuilder()
00097 {
00098 #ifdef DEBUG
00099 //  printf("~nsXMLContentBuilder\n");
00100 #endif
00101 }
00102 
00103 nsresult
00104 NS_NewXMLContentBuilder(nsIXMLContentBuilder** aResult)
00105 {
00106   nsXMLContentBuilder* result = new nsXMLContentBuilder();
00107   if (! result)
00108     return NS_ERROR_OUT_OF_MEMORY;
00109 
00110   NS_ADDREF(result);
00111   *aResult = result;
00112   return NS_OK;
00113 }
00114 
00115 //----------------------------------------------------------------------
00116 // nsISupports methods
00117 
00118 NS_IMPL_ISUPPORTS1(nsXMLContentBuilder, nsIXMLContentBuilder)
00119 
00120 //----------------------------------------------------------------------
00121 // nsIXMLContentBuilder implementation
00122 
00123 /* void clear (in nsIDOMElement root); */
00124 NS_IMETHODIMP nsXMLContentBuilder::Clear(nsIDOMElement *root)
00125 {
00126   mCurrent = do_QueryInterface(root);
00127   mTop = do_QueryInterface(root);
00128   if (mNamespaceId != kNameSpaceID_None) {
00129     mNamespaceId = kNameSpaceID_None;
00130   }
00131   return NS_OK;
00132 }
00133 
00134 /* void setDocument (in nsIDOMDocument doc); */
00135 NS_IMETHODIMP nsXMLContentBuilder::SetDocument(nsIDOMDocument *doc)
00136 {
00137   mDocument = do_QueryInterface(doc);
00138 #ifdef DEBUG
00139   if (!mDocument)
00140     NS_WARNING("null document in nsXMLContentBuilder::SetDocument");
00141 #endif
00142   return NS_OK;
00143 }
00144 
00145 /* void setElementNamespace (in AString ns); */
00146 NS_IMETHODIMP nsXMLContentBuilder::SetElementNamespace(const nsAString & ns)
00147 {
00148   nsContentUtils::GetNSManagerWeakRef()->RegisterNameSpace(ns, mNamespaceId);
00149   return NS_OK;
00150 }
00151 
00152 /* void beginElement (in AString tagname); */
00153 NS_IMETHODIMP nsXMLContentBuilder::BeginElement(const nsAString & tagname)
00154 {
00155   nsCOMPtr<nsIContent> node;
00156   {
00157     EnsureDoc();
00158     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(tagname);
00159     mDocument->CreateElem(nameAtom, nsnull, mNamespaceId, PR_FALSE, getter_AddRefs(node));
00160   }
00161   if (!node) {
00162     NS_ERROR("could not create node");
00163     return NS_ERROR_FAILURE;
00164   }
00165 
00166   // ok, we created a content element. now either append it to our
00167   // top-level array or to the current element.
00168   if (!mCurrent) {
00169     if (mTop) {
00170       NS_ERROR("Building of multi-rooted trees not supported");
00171       return NS_ERROR_FAILURE;
00172     }
00173     mTop = node;
00174     mCurrent = mTop;
00175   }
00176   else {    
00177     mCurrent->AppendChildTo(node, PR_TRUE);
00178     mCurrent = node;
00179   }
00180   
00181   return NS_OK;
00182 }
00183 
00184 /* void endElement (); */
00185 NS_IMETHODIMP nsXMLContentBuilder::EndElement()
00186 {
00187   NS_ASSERTION(mCurrent, "unbalanced begin/endelement");
00188   mCurrent = mCurrent->GetParent();
00189   return NS_OK;
00190 }
00191 
00192 /* void attrib (in AString name, in AString value); */
00193 NS_IMETHODIMP nsXMLContentBuilder::Attrib(const nsAString & name, const nsAString & value)
00194 {
00195   NS_ASSERTION(mCurrent, "can't set attrib w/o open element");
00196   nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(name);
00197   mCurrent->SetAttr(0, nameAtom, value, PR_TRUE);
00198   return NS_OK;
00199 }
00200 
00201 /* void textNode (in AString text); */
00202 NS_IMETHODIMP nsXMLContentBuilder::TextNode(const nsAString & text)
00203 {
00204   EnsureDoc();
00205   NS_ASSERTION(mCurrent, "can't append textnode w/o open element");
00206   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(mDocument);
00207   NS_ASSERTION(domDoc, "no dom document");
00208 
00209   nsCOMPtr<nsIDOMText> textNode;
00210   domDoc->CreateTextNode(text, getter_AddRefs(textNode));
00211   NS_ASSERTION(textNode, "Failed to create text node");
00212   nsCOMPtr<nsIContent> textContent = do_QueryInterface(textNode);
00213   mCurrent->AppendChildTo(textContent, PR_TRUE);
00214   return NS_OK;
00215 }
00216 
00217 /* readonly attribute nsIDOMElement root; */
00218 NS_IMETHODIMP nsXMLContentBuilder::GetRoot(nsIDOMElement * *aRoot)
00219 {
00220   if (!mTop) {
00221     *aRoot = nsnull;
00222     return NS_OK;
00223   }
00224   return mTop->QueryInterface(nsIDOMElement::GetIID(), (void**)aRoot);
00225 }
00226 
00227 /* readonly attribute nsIDOMElement current; */
00228 NS_IMETHODIMP nsXMLContentBuilder::GetCurrent(nsIDOMElement * *aCurrent)
00229 {
00230   if (!mCurrent) {
00231     *aCurrent = nsnull;
00232     return NS_OK;
00233   }  
00234   return mCurrent->QueryInterface(nsIDOMElement::GetIID(), (void**)aCurrent);
00235 }
00236 
00237 //----------------------------------------------------------------------
00238 // implementation helpers
00239 
00240 void nsXMLContentBuilder::EnsureDoc()
00241 {
00242   if (!mDocument) {
00243     mDocument = do_CreateInstance(kXMLDocumentCID);
00244     // XXX should probably do some doc initialization here, such as
00245     // setting the base url
00246   }
00247   NS_ASSERTION(mDocument, "null doc");
00248 }