GME  13
DOMElementImpl.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (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  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: DOMElementImpl.cpp 901107 2010-01-20 08:45:02Z borisk $
00020  */
00021 
00022 #include "DOMElementImpl.hpp"
00023 
00024 #include <xercesc/dom/DOMAttr.hpp>
00025 #include <xercesc/dom/DOMDocument.hpp>
00026 #include <xercesc/dom/DOMException.hpp>
00027 #include <xercesc/util/XMLUniDefs.hpp>
00028 #include <xercesc/util/XMLUri.hpp>
00029 
00030 #include "DOMAttrMapImpl.hpp"
00031 #include "DOMAttrImpl.hpp"
00032 #include "DOMDocumentImpl.hpp"
00033 #include "DOMParentNode.hpp"
00034 #include "DOMCasts.hpp"
00035 #include "DOMElementNSImpl.hpp"
00036 #include "DOMTypeInfoImpl.hpp"
00037 
00038 #include "DOMDocumentTypeImpl.hpp"
00039 #include <xercesc/util/OutOfMemoryException.hpp>
00040 
00041 XERCES_CPP_NAMESPACE_BEGIN
00042 
00043 class DOMAttr;
00044 
00045 DOMElementImpl::DOMElementImpl(DOMDocument *ownerDoc, const XMLCh *eName)
00046     : fNode(ownerDoc), fParent(ownerDoc), fAttributes(0), fDefaultAttributes(0)
00047 {
00048     DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
00049     fName = docImpl->getPooledString(eName);
00050     setupDefaultAttributes();
00051     if (!fDefaultAttributes) {
00052         fDefaultAttributes = new (docImpl) DOMAttrMapImpl(this);
00053         fAttributes = new (docImpl) DOMAttrMapImpl(this);
00054     }
00055     else {
00056       fAttributes = new (docImpl) DOMAttrMapImpl(this, fDefaultAttributes);
00057     }
00058 }
00059 
00060 
00061 DOMElementImpl::DOMElementImpl(const DOMElementImpl &other, bool deep)
00062     : DOMElement(other),
00063       fNode (other.fParent.fOwnerDocument),
00064       fParent (other.fParent.fOwnerDocument),
00065       fAttributes(0),
00066       fDefaultAttributes(0)
00067 {
00068     fName = other.fName;
00069 
00070     if (deep)
00071         fParent.cloneChildren(&other);
00072 
00073     if (other.getAttributes())
00074     {
00075         fAttributes = ((DOMAttrMapImpl *)other.getAttributes())->cloneAttrMap(this);
00076     }
00077 
00078     if (other.getDefaultAttributes())
00079     {
00080         fDefaultAttributes = ((DOMAttrMapImpl *)other.getDefaultAttributes())->cloneAttrMap(this);
00081     }
00082 
00083     if (!fDefaultAttributes)
00084         setupDefaultAttributes();
00085 
00086     if (!fDefaultAttributes)
00087         fDefaultAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this);
00088 
00089     if (!fAttributes) {
00090         if (!fDefaultAttributes) {
00091             fAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this);
00092         }
00093         else {
00094             fAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this, fDefaultAttributes);
00095         }
00096     }
00097 
00098 }
00099 
00100 
00101 DOMElementImpl::~DOMElementImpl()
00102 {
00103 }
00104 
00105 
00106 DOMNode *DOMElementImpl::cloneNode(bool deep) const
00107 {
00108     DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ELEMENT_OBJECT) DOMElementImpl(*this, deep);
00109     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
00110     return newNode;
00111 }
00112 
00113 
00114 
00115 
00116 const XMLCh * DOMElementImpl::getNodeName() const {
00117     return fName;
00118 }
00119 
00120 
00121 DOMNode::NodeType DOMElementImpl::getNodeType() const {
00122     return DOMNode::ELEMENT_NODE;
00123 }
00124 
00125 
00126 const XMLCh * DOMElementImpl::getAttribute(const XMLCh *nam) const
00127 {
00128     DOMNode * attr = fAttributes->getNamedItem(nam);
00129     if (attr)
00130         return attr->getNodeValue();
00131 
00132     return XMLUni::fgZeroLenString;
00133 }
00134 
00135 
00136 
00137 DOMAttr *DOMElementImpl::getAttributeNode(const XMLCh *nam) const
00138 {
00139     return  (DOMAttr *)fAttributes->getNamedItem(nam);
00140 }
00141 
00142 
00143 DOMNamedNodeMap *DOMElementImpl::getAttributes() const
00144 {
00145     DOMElementImpl *ncThis = (DOMElementImpl *)this;   // cast off const
00146     return ncThis->fAttributes;
00147 }
00148 
00149 
00150 
00151 DOMNodeList *DOMElementImpl::getElementsByTagName(const XMLCh *tagname) const
00152 {
00153     DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument;
00154     return docImpl->getDeepNodeList(this,tagname);
00155 }
00156 
00157 
00158 const XMLCh * DOMElementImpl::getTagName() const
00159 {
00160     return fName;
00161 }
00162 
00163 
00164 void DOMElementImpl::removeAttribute(const XMLCh *nam)
00165 {
00166     if (fNode.isReadOnly())
00167         throw DOMException(
00168              DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00169 
00170     int i = fAttributes->findNamePoint(nam);
00171     if (i >= 0)
00172     {
00173         DOMNode *att = fAttributes->removeNamedItemAt(i);
00174         ((DOMAttrImpl *)att)->removeAttrFromIDNodeMap();
00175         att->release();
00176     }
00177 }
00178 
00179 
00180 
00181 DOMAttr *DOMElementImpl::removeAttributeNode(DOMAttr *oldAttr)
00182 {
00183     if (fNode.isReadOnly())
00184         throw DOMException(
00185         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00186 
00187     DOMNode* found = 0;
00188 
00189     // Since there is no removeAttributeNodeNS, check if this oldAttr has NS or not
00190     const XMLCh* localName = oldAttr->getLocalName();
00191     int i = 0;
00192     if (localName)
00193         i = fAttributes->findNamePoint(oldAttr->getNamespaceURI(), localName);
00194     else
00195         i = fAttributes->findNamePoint(oldAttr->getName());
00196 
00197     if (i >= 0) {
00198         // If it is in fact the right object, remove it.
00199         found = fAttributes->item(i);
00200         if (found == oldAttr) {
00201             fAttributes->removeNamedItemAt(i);
00202             ((DOMAttrImpl *)oldAttr)->removeAttrFromIDNodeMap();
00203         }
00204         else
00205             throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00206 
00207     }
00208     else
00209         throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00210 
00211    return (DOMAttr *)found;
00212 }
00213 
00214 
00215 
00216 void DOMElementImpl::setAttribute(const XMLCh *nam, const XMLCh *val)
00217 {
00218     if (fNode.isReadOnly())
00219         throw DOMException(
00220         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00221 
00222     DOMAttr* newAttr = getAttributeNode(nam);
00223     if (!newAttr)
00224     {
00225         newAttr = fParent.fOwnerDocument->createAttribute(nam);
00226         fAttributes->setNamedItem(newAttr);
00227     }
00228 
00229     newAttr->setNodeValue(val);
00230 }
00231 
00232 void DOMElementImpl::setIdAttribute(const XMLCh* name, bool isId)
00233 {
00234     if (fNode.isReadOnly())
00235         throw DOMException(
00236         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00237 
00238     DOMAttr *attr = getAttributeNode(name);
00239 
00240     if (!attr)
00241         throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00242 
00243     if(isId)
00244         ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
00245     else
00246         ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
00247 }
00248 
00249 void DOMElementImpl::setIdAttributeNS(const XMLCh* namespaceURI, const XMLCh* localName, bool isId) {
00250 
00251     if (fNode.isReadOnly())
00252         throw DOMException(
00253         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00254 
00255     DOMAttr *attr = getAttributeNodeNS(namespaceURI, localName);
00256 
00257     if (!attr)
00258         throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00259 
00260     if(isId)
00261         ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
00262     else
00263         ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
00264 }
00265 
00266 
00267 void DOMElementImpl::setIdAttributeNode(const DOMAttr *idAttr, bool isId) {
00268 
00269     if (fNode.isReadOnly())
00270         throw DOMException(
00271         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00272 
00273     DOMAttr *attr;
00274     const XMLCh* localName = idAttr->getLocalName();
00275     if (localName)
00276         attr = getAttributeNodeNS(idAttr->getNamespaceURI(), idAttr->getLocalName());
00277     else
00278         attr = getAttributeNode(idAttr->getName());
00279 
00280     if(!attr)
00281         throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
00282 
00283     if(isId)
00284         ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
00285     else
00286         ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
00287 }
00288 
00289 
00290 DOMAttr * DOMElementImpl::setAttributeNode(DOMAttr *newAttr)
00291 {
00292     if (fNode.isReadOnly())
00293         throw DOMException(
00294         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00295 
00296     if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE)
00297         throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
00298         // revisit.  Exception doesn't match test.
00299 
00300     // This will throw INUSE if necessary
00301     DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItem(newAttr);
00302 
00303     return oldAttr;
00304 }
00305 
00306 
00307 void DOMElementImpl::setNodeValue(const XMLCh *x)
00308 {
00309     fNode.setNodeValue(x);
00310 }
00311 
00312 
00313 
00314 void DOMElementImpl::setReadOnly(bool readOnl, bool deep)
00315 {
00316     fNode.setReadOnly(readOnl,deep);
00317     fAttributes->setReadOnly(readOnl,true);
00318 }
00319 
00320 
00321 //Introduced in DOM Level 2
00322 const XMLCh * DOMElementImpl::getAttributeNS(const XMLCh *fNamespaceURI,
00323     const XMLCh *fLocalName) const
00324 {
00325     DOMAttr * attr=
00326       (DOMAttr *)(fAttributes->getNamedItemNS(fNamespaceURI, fLocalName));
00327     return (attr==0) ? XMLUni::fgZeroLenString : attr->getValue();
00328 }
00329 
00330 
00331 void DOMElementImpl::setAttributeNS(const XMLCh *fNamespaceURI,
00332     const XMLCh *qualifiedName, const XMLCh *fValue)
00333 {
00334     if (fNode.isReadOnly())
00335         throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00336 
00337     int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
00338     if (index < 0)
00339         throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
00340 
00341     DOMAttr* newAttr = getAttributeNodeNS(fNamespaceURI, qualifiedName+index);
00342     if (!newAttr)
00343     {
00344         newAttr = fParent.fOwnerDocument->createAttributeNS(fNamespaceURI, qualifiedName);
00345         fAttributes->setNamedItemNS(newAttr);
00346     }
00347 
00348     newAttr->setNodeValue(fValue);
00349 }
00350 
00351 
00352 void DOMElementImpl::removeAttributeNS(const XMLCh *fNamespaceURI,
00353     const XMLCh *fLocalName)
00354 {
00355     if (fNode.isReadOnly())
00356         throw DOMException(
00357         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00358 
00359     int i = fAttributes->findNamePoint(fNamespaceURI, fLocalName);
00360     if (i >= 0)
00361     {
00362         DOMNode *att = fAttributes->removeNamedItemAt(i);
00363         att->release();
00364     }
00365 }
00366 
00367 
00368 DOMAttr *DOMElementImpl::getAttributeNodeNS(const XMLCh *fNamespaceURI,
00369     const XMLCh *fLocalName) const
00370 {
00371     return (DOMAttr *)fAttributes->getNamedItemNS(fNamespaceURI, fLocalName);
00372 }
00373 
00374 
00375 DOMAttr *DOMElementImpl::setAttributeNodeNS(DOMAttr *newAttr)
00376 {
00377     if (fNode.isReadOnly())
00378         throw DOMException(
00379             DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00380 
00381     if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument)
00382         throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
00383 
00384     // This will throw INUSE if necessary
00385     DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItemNS(newAttr);
00386 
00387     return oldAttr;
00388 }
00389 
00390 
00391 DOMNodeList *DOMElementImpl::getElementsByTagNameNS(const XMLCh *namespaceURI,
00392     const XMLCh *localName) const
00393 {
00394     DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument;
00395     return docImpl->getDeepNodeList(this, namespaceURI, localName);
00396 }
00397 
00398 bool DOMElementImpl::hasAttributes() const
00399 {
00400     return (fAttributes != 0 && fAttributes->getLength() != 0);
00401 }
00402 
00403 
00404 bool DOMElementImpl::hasAttribute(const XMLCh *name) const
00405 {
00406     return (getAttributeNode(name) != 0);
00407 }
00408 
00409 
00410 bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI,
00411     const XMLCh *localName) const
00412 {
00413     return (getAttributeNodeNS(namespaceURI, localName) != 0);
00414 }
00415 
00416 
00417 // util functions for default attributes
00418 // returns the default attribute map for this node from the owner document
00419 DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes() const
00420 {
00421     return fDefaultAttributes;
00422 }
00423 
00424 // initially set up the default attribute information based on doctype information
00425 void DOMElementImpl::setupDefaultAttributes()
00426 {
00427     DOMDocument *tmpdoc = fParent.fOwnerDocument;
00428     if ((fNode.fOwnerNode == 0) || (tmpdoc == 0) || (tmpdoc->getDoctype() == 0))
00429         return;
00430 
00431     DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName());
00432     DOMAttrMapImpl* defAttrs = (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes());
00433 
00434     if (defAttrs)
00435         fDefaultAttributes = new (tmpdoc) DOMAttrMapImpl(this, defAttrs);
00436 }
00437 
00438 DOMAttr * DOMElementImpl::setDefaultAttributeNode(DOMAttr *newAttr)
00439 {
00440     if (fNode.isReadOnly())
00441         throw DOMException(
00442         DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00443 
00444     if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE)
00445         throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
00446         // revisit.  Exception doesn't match test.
00447 
00448     // This will throw INUSE if necessary
00449     DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItem(newAttr);
00450     fAttributes->hasDefaults(true);
00451 
00452     return oldAttr;
00453 }
00454 
00455 
00456 DOMAttr *DOMElementImpl::setDefaultAttributeNodeNS(DOMAttr *newAttr)
00457 {
00458     if (fNode.isReadOnly())
00459         throw DOMException(
00460             DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
00461 
00462     if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument)
00463         throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
00464 
00465     // This will throw INUSE if necessary
00466     DOMAttr *oldAttr = (DOMAttr *) fDefaultAttributes->setNamedItemNS(newAttr);
00467     fAttributes->hasDefaults(true);
00468 
00469     return oldAttr;
00470 }
00471 
00472 void DOMElementImpl::release()
00473 {
00474     if (fNode.isOwned() && !fNode.isToBeReleased())
00475         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00476 
00477     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
00478     if (doc) {
00479         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
00480         // release children
00481         fParent.release();
00482         // release attributes
00483         fAttributes->hasDefaults(false);
00484         XMLSize_t count;
00485         while((count = fAttributes->getLength()) != 0)
00486         {
00487             DOMNode* attr = fAttributes->removeNamedItemAt(count-1);
00488             attr->release();
00489         }
00490 
00491         doc->release(this, DOMMemoryManager::ELEMENT_OBJECT);
00492     }
00493     else {
00494         // shouldn't reach here
00495         throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
00496     }
00497 }
00498 
00499 const XMLCh* DOMElementImpl::getBaseURI() const
00500 {
00501     const XMLCh* baseURI = fNode.fOwnerNode->getBaseURI();
00502     if (fAttributes) {
00503         const XMLCh baseString[] =
00504         {
00505             chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
00506         };
00507         DOMNode* attrNode = fAttributes->getNamedItemNS(DOMNodeImpl::getXmlURIString(), baseString);
00508         if (attrNode==NULL) {
00509             const XMLCh xmlBaseString[] =
00510             {
00511                 chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
00512             };
00513             attrNode = fAttributes->getNamedItem(xmlBaseString);
00514         }
00515         if (attrNode) {
00516             const XMLCh* uri =  attrNode->getNodeValue();
00517             if (uri && *uri) {// attribute value is always empty string
00518                 // if there is a base URI for the parent node, use it to resolve relative URI
00519                 if(baseURI)
00520                 {
00521                     try {
00522                       DOMDocumentImpl* doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
00523                       XMLUri temp(baseURI, doc->getMemoryManager());
00524                       XMLUri temp2(&temp, uri, doc->getMemoryManager());
00525                       uri = doc->cloneString(temp2.getUriText());
00526                     }
00527                     catch(const OutOfMemoryException&)
00528                     {
00529                         throw;
00530                     }
00531                     catch (...){
00532                         // REVISIT: what should happen in this case?
00533                         return 0;
00534                     }
00535                 }
00536                 return uri;
00537             }
00538         }
00539     }
00540     return baseURI;
00541 }
00542 
00543 
00544 
00545 //
00546 //   Functions inherited from Node
00547 //
00548            DOMNode*         DOMElementImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
00549            DOMNodeList*     DOMElementImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
00550            DOMNode*         DOMElementImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
00551            DOMNode*         DOMElementImpl::getLastChild() const                    {return fParent.getLastChild (); }
00552      const XMLCh*           DOMElementImpl::getLocalName() const                    {return fNode.getLocalName (); }
00553      const XMLCh*           DOMElementImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
00554            DOMNode*         DOMElementImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
00555      const XMLCh*           DOMElementImpl::getNodeValue() const                    {return fNode.getNodeValue (); }
00556            DOMDocument*     DOMElementImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
00557      const XMLCh*           DOMElementImpl::getPrefix() const                       {return fNode.getPrefix (); }
00558            DOMNode*         DOMElementImpl::getParentNode() const                   {return fChild.getParentNode (this); }
00559            DOMNode*         DOMElementImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
00560            bool             DOMElementImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
00561            DOMNode*         DOMElementImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
00562                                                                                     {return fParent.insertBefore (newChild, refChild); }
00563            void             DOMElementImpl::normalize()                             {fParent.normalize (); }
00564            DOMNode*         DOMElementImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
00565            DOMNode*         DOMElementImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
00566                                                                                     {return fParent.replaceChild (newChild, oldChild); }
00567            bool             DOMElementImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
00568                                                                                     {return fNode.isSupported (feature, version); }
00569            void             DOMElementImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
00570            bool             DOMElementImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
00571            void*            DOMElementImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
00572                                                                                     {return fNode.setUserData(key, data, handler); }
00573            void*            DOMElementImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
00574            short            DOMElementImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
00575            const XMLCh*     DOMElementImpl::getTextContent() const                  {return fNode.getTextContent(); }
00576            void             DOMElementImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
00577            const XMLCh*     DOMElementImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
00578            bool             DOMElementImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
00579            const XMLCh*     DOMElementImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
00580            void*            DOMElementImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
00581 
00582 
00583 
00584 bool DOMElementImpl::isEqualNode(const DOMNode* arg) const
00585 {
00586     if (isSameNode(arg)) {
00587         return true;
00588     }
00589 
00590     if (!fNode.isEqualNode(arg)) {
00591         return false;
00592     }
00593 
00594     bool hasAttrs = hasAttributes();
00595 
00596     if (hasAttrs != arg->hasAttributes()) {
00597         return false;
00598     }
00599 
00600     if (hasAttrs) {
00601         DOMNamedNodeMap* map1 = getAttributes();
00602         DOMNamedNodeMap* map2 = arg->getAttributes();
00603 
00604         XMLSize_t len = map1->getLength();
00605         if (len != map2->getLength()) {
00606             return false;
00607         }
00608         for (XMLSize_t i = 0; i < len; i++) {
00609             DOMNode* n1 = map1->item(i);
00610             if (!n1->getLocalName()) { // DOM Level 1 Node
00611                 DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
00612                 if (!n2 || !n1->isEqualNode(n2)) {
00613                     return false;
00614                 }
00615             }
00616             else {
00617                 DOMNode* n2 = map2->getNamedItemNS(n1->getNamespaceURI(),
00618                                               n1->getLocalName());
00619                 if (!n2 || !n1->isEqualNode(n2)) {
00620                     return false;
00621                 }
00622             }
00623         }
00624     }
00625 
00626     return fParent.isEqualNode(arg);
00627 }
00628 
00629 DOMNode* DOMElementImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
00630 {
00631     DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
00632 
00633     if (!namespaceURI || !*namespaceURI) {
00634         fName = doc->getPooledString(name);
00635         fAttributes->reconcileDefaultAttributes(getDefaultAttributes());
00636 
00637         // and fire user data NODE_RENAMED event
00638         castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this);
00639 
00640         return this;
00641     }
00642     else {
00643 
00644         // create a new ElementNS
00645         DOMElementNSImpl* newElem = (DOMElementNSImpl*)doc->createElementNS(namespaceURI, name);
00646 
00647         // transfer the userData
00648         doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newElem));
00649 
00650         // remove old node from parent if any
00651         DOMNode* parent = getParentNode();
00652         DOMNode* nextSib = getNextSibling();
00653         if (parent) {
00654             parent->removeChild(this);
00655         }
00656 
00657         // move children to new node
00658         DOMNode* child = getFirstChild();
00659         while (child) {
00660             removeChild(child);
00661             newElem->appendChild(child);
00662             child = getFirstChild();
00663         }
00664 
00665         // insert new node where old one was
00666         if (parent) {
00667             parent->insertBefore(newElem, nextSib);
00668         }
00669 
00670         // move specified attributes to new node
00671         newElem->fAttributes->moveSpecifiedAttributes(fAttributes);
00672 
00673         // and fire user data NODE_RENAMED event
00674         castToNodeImpl(newElem)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newElem);
00675 
00676         return newElem;
00677     }
00678 }
00679 
00680 const DOMTypeInfo *DOMElementImpl::getSchemaTypeInfo() const
00681 {
00682     return &DOMTypeInfoImpl::g_DtdValidatedElement;
00683 }
00684 
00685 // DOMElementTraversal
00686 DOMElement * DOMElementImpl::getFirstElementChild() const
00687 {
00688     DOMNode* n = getFirstChild();
00689     while (n != NULL) {
00690         switch (n->getNodeType()) {
00691             case DOMNode::ELEMENT_NODE:
00692                 return (DOMElement*) n;
00693             case DOMNode::ENTITY_REFERENCE_NODE:
00694                 {
00695                     DOMElement* e = getFirstElementChild(n);
00696                     if (e != NULL)
00697                         return e;
00698                 }
00699                 break;
00700             default:
00701                 break;
00702         }
00703         n = n->getNextSibling();
00704     }
00705     return NULL;
00706 }
00707 
00708 DOMElement * DOMElementImpl::getLastElementChild() const
00709 {
00710     DOMNode* n = getLastChild();
00711     while (n != NULL) {
00712         switch (n->getNodeType()) {
00713             case DOMNode::ELEMENT_NODE:
00714                 return (DOMElement*) n;
00715             case DOMNode::ENTITY_REFERENCE_NODE:
00716                 {
00717                     DOMElement* e = getLastElementChild(n);
00718                     if (e != NULL)
00719                         return e;
00720                 }
00721                 break;
00722             default:
00723                 break;
00724         }
00725         n = n->getPreviousSibling();
00726     }
00727     return NULL;
00728 }
00729 
00730 DOMElement * DOMElementImpl::getNextElementSibling() const
00731 {
00732     DOMNode* n = getNextLogicalSibling(this);
00733     while (n != NULL) {
00734         switch (n->getNodeType()) {
00735             case DOMNode::ELEMENT_NODE:
00736                 return (DOMElement*) n;
00737             case DOMNode::ENTITY_REFERENCE_NODE:
00738                 {
00739                     DOMElement* e = getFirstElementChild(n);
00740                     if (e != NULL)
00741                         return e;
00742                 }
00743                 break;
00744             default:
00745                 break;
00746         }
00747         n = getNextLogicalSibling(n);
00748     }
00749     return NULL;
00750 }
00751 
00752 DOMElement * DOMElementImpl::getPreviousElementSibling() const
00753 {
00754     DOMNode* n = getPreviousLogicalSibling(this);
00755     while (n != NULL) {
00756         switch (n->getNodeType()) {
00757             case DOMNode::ELEMENT_NODE:
00758                 return (DOMElement*) n;
00759             case DOMNode::ENTITY_REFERENCE_NODE:
00760                 {
00761                     DOMElement* e = getLastElementChild(n);
00762                     if (e != NULL)
00763                         return e;
00764                 }
00765                 break;
00766             default:
00767                 break;
00768         }
00769         n = getPreviousLogicalSibling(n);
00770     }
00771     return NULL;
00772 }
00773 
00774 XMLSize_t DOMElementImpl::getChildElementCount() const
00775 {
00776     XMLSize_t count = 0;
00777     DOMElement* child = getFirstElementChild();
00778     while (child != NULL) {
00779         ++count;
00780         child = child->getNextElementSibling();
00781     }
00782     return count;
00783 }
00784 
00785 // Returns the first element node found from a
00786 // non-recursive in order traversal of the given node.
00787 DOMElement* DOMElementImpl::getFirstElementChild(const DOMNode* n) const
00788 {
00789     const DOMNode* top = n;
00790     while (n != NULL) {
00791         if (n->getNodeType() == DOMNode::ELEMENT_NODE) {
00792             return (DOMElement*) n;
00793         }
00794         DOMNode* next = n->getFirstChild();
00795         while (next == NULL) {
00796             if (top == n) {
00797                 break;
00798             }
00799             next = n->getNextSibling();
00800             if (next == NULL) {
00801                 n = n->getParentNode();
00802                 if (n == NULL || top == n) {
00803                     return NULL;
00804                 }
00805             }
00806         }
00807         n = next;
00808     }
00809     return NULL;
00810 }
00811 
00812 // Returns the first element node found from a
00813 // non-recursive reverse order traversal of the given node.
00814 DOMElement* DOMElementImpl::getLastElementChild(const DOMNode* n) const
00815 {
00816     const DOMNode* top = n;
00817     while (n != NULL) {
00818         if (n->getNodeType() == DOMNode::ELEMENT_NODE) {
00819             return (DOMElement*) n;
00820         }
00821         DOMNode* next = n->getLastChild();
00822         while (next == NULL) {
00823             if (top == n) {
00824                 break;
00825             }
00826             next = n->getPreviousSibling();
00827             if (next == NULL) {
00828                 n = n->getParentNode();
00829                 if (n == NULL || top == n) {
00830                     return NULL;
00831                 }
00832             }
00833         }
00834         n = next;
00835     }
00836     return NULL;
00837 }
00838 
00839 // Returns the next logical sibling with respect to the given node.
00840 DOMNode* DOMElementImpl::getNextLogicalSibling(const DOMNode* n) const
00841 {
00842     DOMNode* next = n->getNextSibling();
00843     // If "n" has no following sibling and its parent is an entity reference node we
00844     // need to continue the search through the following siblings of the entity
00845     // reference as these are logically siblings of the given node.
00846     if (next == NULL) {
00847         DOMNode* parent = n->getParentNode();
00848         while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
00849             next = parent->getNextSibling();
00850             if (next != NULL) {
00851                 break;
00852             }
00853             parent = parent->getParentNode();
00854         }
00855     }
00856     return next;
00857 }
00858 
00859 // Returns the previous logical sibling with respect to the given node.
00860 DOMNode* DOMElementImpl::getPreviousLogicalSibling(const DOMNode* n) const
00861 {
00862     DOMNode* prev = n->getPreviousSibling();
00863     // If "n" has no previous sibling and its parent is an entity reference node we
00864     // need to continue the search through the previous siblings of the entity
00865     // reference as these are logically siblings of the given node.
00866     if (prev == NULL) {
00867         DOMNode* parent = n->getParentNode();
00868         while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
00869             prev = parent->getPreviousSibling();
00870             if (prev != NULL) {
00871                 break;
00872             }
00873             parent = parent->getParentNode();
00874         }
00875     }
00876     return prev;
00877 }
00878 
00879 
00880 XERCES_CPP_NAMESPACE_END