Back to index

lightning-sunbird  0.9+nobinonly
Element.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 TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * The MITRE Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 // Tom Kneeland (3/29/99)
00039 //
00040 //  Implementation of the Document Object Model Level 1 Core
00041 //    Implementation of the Element class
00042 //
00043 
00044 #include "dom.h"
00045 #include "txAtoms.h"
00046 #include "XMLUtils.h"
00047 
00048 //
00049 //Construct a new element with the specified tagName and Document owner.
00050 //Simply call the constructor for NodeDefinition, and specify the proper node
00051 //type.
00052 //
00053 Element::Element(const nsAString& tagName, Document* owner) :
00054          NodeDefinition(Node::ELEMENT_NODE, tagName, EmptyString(), owner)
00055 {
00056   mAttributes.ownerElement = this;
00057   mNamespaceID = kNameSpaceID_Unknown;
00058 
00059   int idx = tagName.FindChar(':');
00060   if (idx == kNotFound) {
00061     mLocalName = do_GetAtom(tagName);
00062   }
00063   else {
00064     mLocalName = do_GetAtom(Substring(tagName, idx + 1,
00065                                       tagName.Length() - (idx + 1)));
00066   }
00067 }
00068 
00069 Element::Element(const nsAString& aNamespaceURI,
00070                  const nsAString& aTagName,
00071                  Document* aOwner) :
00072          NodeDefinition(Node::ELEMENT_NODE, aTagName, EmptyString(), aOwner)
00073 {
00074   Element(aTagName, aOwner);
00075   if (aNamespaceURI.IsEmpty())
00076     mNamespaceID = kNameSpaceID_None;
00077   else
00078     mNamespaceID = txStandaloneNamespaceManager::getNamespaceID(aNamespaceURI);
00079 }
00080 
00081 //
00082 // This element is being destroyed, so destroy all attributes stored
00083 // in the mAttributes NamedNodeMap.
00084 //
00085 Element::~Element()
00086 {
00087   mAttributes.clear();
00088 }
00089 
00090 Node* Element::appendChild(Node* newChild)
00091 {
00092   switch (newChild->getNodeType())
00093     {
00094       case Node::ELEMENT_NODE :
00095       case Node::TEXT_NODE :
00096       case Node::COMMENT_NODE :
00097       case Node::PROCESSING_INSTRUCTION_NODE :
00098         {
00099           // Remove the "newChild" if it is already a child of this node
00100           NodeDefinition* pNewChild = (NodeDefinition*)newChild;
00101           if (pNewChild->getParentNode() == this)
00102             pNewChild = implRemoveChild(pNewChild);
00103 
00104           return implAppendChild(pNewChild);
00105         }
00106 
00107       default:
00108         break;
00109     }
00110 
00111   return nsnull;
00112 }
00113 
00114 //
00115 //Return the elements local (unprefixed) name.
00116 //
00117 MBool Element::getLocalName(nsIAtom** aLocalName)
00118 {
00119   if (!aLocalName)
00120     return MB_FALSE;
00121   *aLocalName = mLocalName;
00122   NS_ADDREF(*aLocalName);
00123   return MB_TRUE;
00124 }
00125 
00126 //
00127 //Return the namespace the elements belongs to.
00128 //
00129 PRInt32 Element::getNamespaceID()
00130 {
00131   if (mNamespaceID>=0)
00132     return mNamespaceID;
00133   int idx = nodeName.FindChar(':');
00134   if (idx == kNotFound) {
00135     Node* node = this;
00136     while (node && node->getNodeType() == Node::ELEMENT_NODE) {
00137       nsAutoString nsURI;
00138       if (((Element*)node)->getAttr(txXMLAtoms::xmlns, kNameSpaceID_XMLNS,
00139                                     nsURI)) {
00140         // xmlns = "" sets the default namespace ID to kNameSpaceID_None;
00141         if (!nsURI.IsEmpty()) {
00142           mNamespaceID = txStandaloneNamespaceManager::getNamespaceID(nsURI);
00143         }
00144         else {
00145           mNamespaceID = kNameSpaceID_None;
00146         }
00147         return mNamespaceID;
00148       }
00149       node = node->getParentNode();
00150     }
00151     mNamespaceID = kNameSpaceID_None;
00152   }
00153   else {
00154     nsCOMPtr<nsIAtom> prefix = do_GetAtom(Substring(nodeName, 0, idx));
00155     mNamespaceID = lookupNamespaceID(prefix);
00156   }
00157   return mNamespaceID;
00158 }
00159 
00160 NamedNodeMap* Element::getAttributes()
00161 {
00162   return &mAttributes;
00163 }
00164 
00165 //
00166 //Add an attribute to this Element.  Create a new Attr object using the
00167 //name and value specified.  Then add the Attr to the the Element's
00168 //mAttributes NamedNodeMap.
00169 //
00170 void Element::setAttribute(const nsAString& name, const nsAString& value)
00171 {
00172   // Check to see if an attribute with this name already exists. If it does
00173   // overwrite its value, if not, add it.
00174   Attr* tempAttribute = getAttributeNode(name);
00175   if (tempAttribute) {
00176     tempAttribute->setNodeValue(value);
00177   }
00178   else {
00179     tempAttribute = getOwnerDocument()->createAttribute(name);
00180     tempAttribute->setNodeValue(value);
00181     tempAttribute->ownerElement = this;
00182     mAttributes.append(tempAttribute);
00183   }
00184 }
00185 
00186 void Element::setAttributeNS(const nsAString& aNamespaceURI,
00187                              const nsAString& aName,
00188                              const nsAString& aValue)
00189 {
00190   // Check to see if an attribute with this name already exists. If it does
00191   // overwrite its value, if not, add it.
00192   PRInt32 namespaceID =
00193       txStandaloneNamespaceManager::getNamespaceID(aNamespaceURI);
00194   nsCOMPtr<nsIAtom> localName = do_GetAtom(XMLUtils::getLocalPart(aName));
00195 
00196   Attr* foundNode = 0;
00197   AttrMap::ListItem* item = mAttributes.firstItem;
00198   while (item) {
00199     foundNode = (Attr*)item->node;
00200     nsCOMPtr<nsIAtom> attrName;
00201     if (foundNode->getLocalName(getter_AddRefs(attrName)) &&
00202         namespaceID == foundNode->getNamespaceID() &&
00203         localName == attrName) {
00204       break;
00205     }
00206     foundNode = 0;
00207     item = item->next;
00208   }
00209 
00210   if (foundNode) {
00211     foundNode->setNodeValue(aValue);
00212   }
00213   else {
00214     Attr* temp = getOwnerDocument()->createAttributeNS(aNamespaceURI,
00215                                                        aName);
00216     temp->setNodeValue(aValue);
00217     temp->ownerElement = this;
00218     mAttributes.append(temp);
00219   }
00220 }
00221 
00222 //
00223 //Return the attribute specified by name
00224 //
00225 Attr* Element::getAttributeNode(const nsAString& name)
00226 {
00227   return (Attr*)mAttributes.getNamedItem(name);
00228 }
00229 
00230 //
00231 // Return true if the attribute specified by localname and nsID
00232 // exists, and sets aValue to the value of the attribute.
00233 // Return false, if the attribute does not exist.
00234 //
00235 MBool Element::getAttr(nsIAtom* aLocalName, PRInt32 aNSID,
00236                        nsAString& aValue)
00237 {
00238   aValue.Truncate();
00239   AttrMap::ListItem* item = mAttributes.firstItem;
00240   while (item) {
00241     Attr* attrNode = (Attr*)item->node;
00242     nsCOMPtr<nsIAtom> localName;
00243     if (attrNode->getLocalName(getter_AddRefs(localName)) &&
00244         aNSID == attrNode->getNamespaceID() &&
00245         aLocalName == localName) {
00246       attrNode->getNodeValue(aValue);
00247       return MB_TRUE;
00248     }
00249     item = item->next;
00250   }
00251   return MB_FALSE;
00252 }
00253 
00254 //
00255 // Return true if the attribute specified by localname and nsID
00256 // exists. Return false otherwise.
00257 //
00258 MBool Element::hasAttr(nsIAtom* aLocalName, PRInt32 aNSID)
00259 {
00260   AttrMap::ListItem* item = mAttributes.firstItem;
00261   while (item) {
00262     Attr* attrNode = (Attr*)item->node;
00263     nsCOMPtr<nsIAtom> localName;
00264     if (attrNode->getLocalName(getter_AddRefs(localName)) &&
00265         aNSID == attrNode->getNamespaceID() &&
00266         aLocalName == localName) {
00267       return MB_TRUE;
00268     }
00269     item = item->next;
00270   }
00271   return MB_FALSE;
00272 }
00273 
00277 PRBool
00278 Element::getIDValue(nsAString& aValue)
00279 {
00280   if (mIDValue.IsEmpty()) {
00281     return PR_FALSE;
00282   }
00283   aValue = mIDValue;
00284   return PR_TRUE;
00285 }
00286 
00287 void
00288 Element::setIDValue(const nsAString& aValue)
00289 {
00290   mIDValue = aValue;
00291 }