source: icXML/icXML-devel/src/xercesc/dom/impl/DOMElementImpl.cpp @ 3565

Last change on this file since 3565 was 3565, checked in by cameron, 6 years ago

Updates to xercesc sources

File size: 28.1 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMElementImpl.cpp 901107 2010-01-20 08:45:02Z borisk $
20 */
21
22#include <xercesc/dom/impl/DOMElementImpl.hpp>
23
24#include <xercesc/dom/DOMAttr.hpp>
25#include <xercesc/dom/DOMDocument.hpp>
26#include <xercesc/dom/DOMException.hpp>
27#include <xercesc/util/XMLUniDefs.hpp>
28#include <xercesc/util/XMLUri.hpp>
29
30#include <xercesc/dom/impl/DOMAttrMapImpl.hpp>
31#include <xercesc/dom/impl/DOMAttrImpl.hpp>
32#include <xercesc/dom/impl/DOMDocumentImpl.hpp>
33#include <xercesc/dom/impl/DOMParentNode.hpp>
34#include <xercesc/dom/impl/DOMCasts.hpp>
35#include <xercesc/dom/impl/DOMElementNSImpl.hpp>
36#include <xercesc/dom/impl/DOMTypeInfoImpl.hpp>
37
38#include <xercesc/dom/impl/DOMDocumentTypeImpl.hpp>
39#include <xercesc/util/OutOfMemoryException.hpp>
40
41XERCES_CPP_NAMESPACE_BEGIN
42
43class DOMAttr;
44
45DOMElementImpl::DOMElementImpl(DOMDocument *ownerDoc, const XMLCh *eName)
46: fNode(ownerDoc)
47, fName(((DOMDocumentImpl *)ownerDoc)->getPooledString(eName))
48, fParent(ownerDoc)
49, fAttributes(0)
50, fDefaultAttributes(0)
51{
52    DOMDocumentImpl *docImpl = (DOMDocumentImpl *)ownerDoc;
53    setupDefaultAttributes();
54    fAttributes = new (docImpl) DOMAttrMapImpl(this, fDefaultAttributes);
55}
56
57
58DOMElementImpl::DOMElementImpl(const DOMElementImpl &other, bool deep)
59: DOMElement(other)
60, fNode(other.fParent.fOwnerDocument)
61, fName(other.fName)
62, fParent(other.fParent.fOwnerDocument)
63, fAttributes(0)
64, fDefaultAttributes(0)
65{
66    if (deep)
67        fParent.cloneChildren(&other);
68
69    if (other.getAttributes())
70    {
71        fAttributes = ((DOMAttrMapImpl *)other.getAttributes())->cloneAttrMap(this);
72    }
73
74    if (other.getDefaultAttributes())
75    {
76        fDefaultAttributes = ((DOMAttrMapImpl *)other.getDefaultAttributes())->cloneAttrMap(this);
77    }
78    else
79    {
80        setupDefaultAttributes();
81    }
82
83    if (!fAttributes)
84    {
85        fAttributes = new (fParent.fOwnerDocument) DOMAttrMapImpl(this, fDefaultAttributes);
86    }
87
88}
89
90
91DOMElementImpl::~DOMElementImpl()
92{
93}
94
95
96DOMNode *DOMElementImpl::cloneNode(bool deep) const
97{
98    DOMNode* newNode = new (fParent.fOwnerDocument, DOMMemoryManager::ELEMENT_OBJECT) DOMElementImpl(*this, deep);
99    fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newNode);
100    return newNode;
101}
102
103
104
105
106const XMLCh * DOMElementImpl::getNodeName() const
107{
108    return fName;
109}
110
111
112DOMNode::NodeType DOMElementImpl::getNodeType() const
113{
114    return DOMNode::ELEMENT_NODE;
115}
116
117
118const XMLCh * DOMElementImpl::getAttribute(const XMLCh *nam) const
119{
120    DOMNode * attr = fAttributes->getNamedItem(nam);
121    if (attr)
122        return attr->getNodeValue();
123
124    return XMLUni::fgZeroLenString;
125}
126
127
128
129DOMAttr *DOMElementImpl::getAttributeNode(const XMLCh *nam) const
130{
131    return  (DOMAttr *)fAttributes->getNamedItem(nam);
132}
133
134
135DOMNamedNodeMap *DOMElementImpl::getAttributes() const
136{
137    return const_cast<DOMElementImpl *>(this)->fAttributes;
138}
139
140
141
142DOMNodeList *DOMElementImpl::getElementsByTagName(const XMLCh *tagname) const
143{
144    DEBUG_MESSAGE("DOMElementImpl::getElementsByTagName(" << tagname << ')')
145
146    DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument;
147    return docImpl->getDeepNodeList(this,tagname);
148}
149
150
151const XMLCh * DOMElementImpl::getTagName() const
152{
153    return fName;
154}
155
156
157void DOMElementImpl::removeAttribute(const XMLCh *nam)
158{
159    if (fNode.isReadOnly())
160        throw DOMException(
161             DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
162
163    int i = fAttributes->findNamePoint(nam);
164    if (i >= 0)
165    {
166        DOMNode *att = fAttributes->removeNamedItemAt(i);
167        ((DOMAttrImpl *)att)->removeAttrFromIDNodeMap();
168        att->release();
169    }
170}
171
172
173
174DOMAttr *DOMElementImpl::removeAttributeNode(DOMAttr *oldAttr)
175{
176    if (fNode.isReadOnly())
177        throw DOMException(
178        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
179
180    DOMNode* found = 0;
181
182    // Since there is no removeAttributeNodeNS, check if this oldAttr has NS or not
183    const XMLCh* localName = oldAttr->getLocalName();
184    int i = 0;
185    if (localName)
186        i = fAttributes->findNamePoint(oldAttr->getNamespaceURI(), localName);
187    else
188        i = fAttributes->findNamePoint(oldAttr->getName());
189
190    if (i >= 0) {
191        // If it is in fact the right object, remove it.
192        found = fAttributes->item(i);
193        if (found == oldAttr) {
194            fAttributes->removeNamedItemAt(i);
195            ((DOMAttrImpl *)oldAttr)->removeAttrFromIDNodeMap();
196        }
197        else
198            throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
199
200    }
201    else
202        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
203
204   return (DOMAttr *)found;
205}
206
207
208
209void DOMElementImpl::setAttribute(const XMLCh *nam, const XMLCh *val)
210{
211    if (fNode.isReadOnly())
212        throw DOMException(
213        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
214
215    DOMAttr* newAttr = getAttributeNode(nam);
216    if (!newAttr)
217    {
218        newAttr = fParent.fOwnerDocument->createAttribute(nam);
219        fAttributes->setNamedItem(newAttr);
220    }
221
222    newAttr->setNodeValue(val);
223}
224
225void DOMElementImpl::setIdAttribute(const XMLCh* name, bool isId)
226{
227    if (fNode.isReadOnly())
228        throw DOMException(
229        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
230
231    DOMAttr *attr = getAttributeNode(name);
232
233    if (!attr)
234        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
235
236    if(isId)
237        ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
238    else
239        ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
240}
241
242void DOMElementImpl::setIdAttributeNS(const XMLCh* namespaceURI, const XMLCh* localName, bool isId) {
243
244    if (fNode.isReadOnly())
245        throw DOMException(
246        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
247
248    DOMAttr *attr = getAttributeNodeNS(namespaceURI, localName);
249
250    if (!attr)
251        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
252
253    if(isId)
254        ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
255    else
256        ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
257}
258
259
260void DOMElementImpl::setIdAttributeNode(const DOMAttr *idAttr, bool isId) {
261
262    if (fNode.isReadOnly())
263        throw DOMException(
264        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
265
266    DOMAttr *attr;
267    const XMLCh* localName = idAttr->getLocalName();
268    if (localName)
269        attr = getAttributeNodeNS(idAttr->getNamespaceURI(), idAttr->getLocalName());
270    else
271        attr = getAttributeNode(idAttr->getName());
272
273    if(!attr)
274        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
275
276    if(isId)
277        ((DOMAttrImpl *)attr)->addAttrToIDNodeMap();
278    else
279        ((DOMAttrImpl *)attr)->removeAttrFromIDNodeMap();
280}
281
282
283DOMAttr * DOMElementImpl::setAttributeNode(DOMAttr *newAttr)
284{
285    if (fNode.isReadOnly())
286        throw DOMException(
287        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
288
289    if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE)
290        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
291        // revisit.  Exception doesn't match test.
292
293    // This will throw INUSE if necessary
294    DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItem(newAttr);
295
296    return oldAttr;
297}
298
299
300void DOMElementImpl::setNodeValue(const XMLCh *x)
301{
302    fNode.setNodeValue(x);
303}
304
305
306
307void DOMElementImpl::setReadOnly(bool readOnl, bool deep)
308{
309    fNode.setReadOnly(readOnl,deep);
310    fAttributes->setReadOnly(readOnl,true);
311}
312
313
314//Introduced in DOM Level 2
315const XMLCh * DOMElementImpl::getAttributeNS(const XMLCh *fNamespaceURI,
316    const XMLCh *fLocalName) const
317{
318    DOMAttr * attr=
319      (DOMAttr *)(fAttributes->getNamedItemNS(fNamespaceURI, fLocalName));
320    return (attr==0) ? XMLUni::fgZeroLenString : attr->getValue();
321}
322
323
324void DOMElementImpl::setAttributeNS(const XMLCh *fNamespaceURI,
325    const XMLCh *qualifiedName, const XMLCh *fValue)
326{
327    if (fNode.isReadOnly())
328        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
329
330    int index = DOMDocumentImpl::indexofQualifiedName(qualifiedName);
331    if (index < 0)
332        throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
333
334    DOMAttr* newAttr = getAttributeNodeNS(fNamespaceURI, qualifiedName+index);
335    if (!newAttr)
336    {
337        newAttr = fParent.fOwnerDocument->createAttributeNS(fNamespaceURI, qualifiedName);
338        fAttributes->setNamedItemNS(newAttr);
339    }
340
341    newAttr->setNodeValue(fValue);
342}
343
344
345void DOMElementImpl::removeAttributeNS(const XMLCh *fNamespaceURI,
346    const XMLCh *fLocalName)
347{
348    if (fNode.isReadOnly())
349        throw DOMException(
350        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
351
352    int i = fAttributes->findNamePoint(fNamespaceURI, fLocalName);
353    if (i >= 0)
354    {
355        DOMNode *att = fAttributes->removeNamedItemAt(i);
356        att->release();
357    }
358}
359
360
361DOMAttr *DOMElementImpl::getAttributeNodeNS(const XMLCh *fNamespaceURI,
362    const XMLCh *fLocalName) const
363{
364    return (DOMAttr *)fAttributes->getNamedItemNS(fNamespaceURI, fLocalName);
365}
366
367
368DOMAttr *DOMElementImpl::setAttributeNodeNS(DOMAttr *newAttr)
369{
370    if (fNode.isReadOnly())
371        throw DOMException(
372            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
373
374    if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument)
375        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
376
377    // This will throw INUSE if necessary
378    DOMAttr *oldAttr = (DOMAttr *) fAttributes->setNamedItemNS(newAttr);
379
380    return oldAttr;
381}
382
383
384DOMNodeList *DOMElementImpl::getElementsByTagNameNS(const XMLCh *namespaceURI, const XMLCh *localName) const
385{
386    DEBUG_MESSAGE("DOMElementImpl::getElementsByTagNameNS(" << namespaceURI << ',' << localName << ')')
387
388    DOMDocumentImpl *docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument;
389    return docImpl->getDeepNodeList(this, namespaceURI, localName);
390}
391
392bool DOMElementImpl::hasAttributes() const
393{
394    return (fAttributes != 0 && fAttributes->getLength() != 0);
395}
396
397
398bool DOMElementImpl::hasAttribute(const XMLCh *name) const
399{
400    return (getAttributeNode(name) != 0);
401}
402
403
404bool DOMElementImpl::hasAttributeNS(const XMLCh *namespaceURI, const XMLCh *localName) const
405{
406    return (getAttributeNodeNS(namespaceURI, localName) != 0);
407}
408
409
410// util functions for default attributes
411// returns the default attribute map for this node from the owner document
412DOMAttrMapImpl *DOMElementImpl::getDefaultAttributes() const
413{
414    if (unlikely(fDefaultAttributes == 0))
415    {
416        DOMDocumentImpl * docImpl = (DOMDocumentImpl *)fParent.fOwnerDocument;
417        const_cast<DOMElementImpl*>(this)->fDefaultAttributes = new (docImpl) DOMAttrMapImpl(const_cast<DOMElementImpl*>(this));
418    }
419    return fDefaultAttributes;
420}
421
422// initially set up the default attribute information based on doctype information
423void DOMElementImpl::setupDefaultAttributes()
424{
425    DOMDocument *tmpdoc = fParent.fOwnerDocument;
426    if ((fNode.fOwnerNode == 0) || (tmpdoc == 0) || (tmpdoc->getDoctype() == 0))
427        return;
428
429    DOMNode *eldef = ((DOMDocumentTypeImpl*)tmpdoc->getDoctype())->getElements()->getNamedItem(getNodeName());
430    DOMAttrMapImpl* defAttrs = (eldef == 0) ? 0 : (DOMAttrMapImpl *)(eldef->getAttributes());
431
432    if (defAttrs)
433        fDefaultAttributes = new (tmpdoc) DOMAttrMapImpl(this, defAttrs);
434}
435
436DOMAttr * DOMElementImpl::setDefaultAttributeNode(DOMAttr *newAttr)
437{
438    if (fNode.isReadOnly())
439        throw DOMException(
440        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
441
442    if (newAttr->getNodeType() != DOMNode::ATTRIBUTE_NODE)
443        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
444        // revisit.  Exception doesn't match test.
445
446    // This will throw INUSE if necessary
447    DOMAttr *oldAttr = (DOMAttr *)getDefaultAttributes()->setNamedItem(newAttr);
448    fAttributes->hasDefaults(true);
449
450    return oldAttr;
451}
452
453
454DOMAttr *DOMElementImpl::setDefaultAttributeNodeNS(DOMAttr *newAttr)
455{
456    if (fNode.isReadOnly())
457        throw DOMException(
458            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
459
460    if (newAttr -> getOwnerDocument() != fParent.fOwnerDocument)
461        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNodeMemoryManager);
462
463    // This will throw INUSE if necessary
464    DOMAttr *oldAttr = (DOMAttr *)getDefaultAttributes()->setNamedItemNS(newAttr);
465    fAttributes->hasDefaults(true);
466
467    return oldAttr;
468}
469
470void DOMElementImpl::release()
471{
472    if (fNode.isOwned() && !fNode.isToBeReleased())
473        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
474
475    DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
476    if (doc) {
477        fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
478        // release children
479        fParent.release();
480        // release attributes
481        fAttributes->hasDefaults(false);
482        XMLSize_t count;
483        while((count = fAttributes->getLength()) != 0)
484        {
485            DOMNode* attr = fAttributes->removeNamedItemAt(count-1);
486            attr->release();
487        }
488
489        doc->release(this, DOMMemoryManager::ELEMENT_OBJECT);
490    }
491    else {
492        // shouldn't reach here
493        throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
494    }
495}
496
497const XMLCh* DOMElementImpl::getBaseURI() const
498{
499    const XMLCh* baseURI = fNode.fOwnerNode->getBaseURI();
500    if (fAttributes) {
501        const XMLCh baseString[] =
502        {
503            chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
504        };
505        DOMNode* attrNode = fAttributes->getNamedItemNS(DOMNodeImpl::getXmlURIString(), baseString);
506        if (attrNode==NULL) {
507            const XMLCh xmlBaseString[] =
508            {
509                chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
510            };
511            attrNode = fAttributes->getNamedItem(xmlBaseString);
512        }
513        if (attrNode) {
514            const XMLCh* uri =  attrNode->getNodeValue();
515            if (uri && *uri) {// attribute value is always empty string
516                // if there is a base URI for the parent node, use it to resolve relative URI
517                if(baseURI)
518                {
519                    try {
520                      DOMDocumentImpl* doc = (DOMDocumentImpl *)fParent.fOwnerDocument;
521                      XMLUri temp(baseURI, doc->getMemoryManager());
522                      XMLUri temp2(&temp, uri, doc->getMemoryManager());
523                      uri = doc->cloneString(temp2.getUriText());
524                    }
525                    catch(const OutOfMemoryException&)
526                    {
527                        throw;
528                    }
529                    catch (...){
530                        // REVISIT: what should happen in this case?
531                        return 0;
532                    }
533                }
534                return uri;
535            }
536        }
537    }
538    return baseURI;
539}
540
541
542
543//
544//   Functions inherited from Node
545//
546           DOMNode*         DOMElementImpl::appendChild(DOMNode *newChild)          {return fParent.appendChild (newChild); }
547           DOMNodeList*     DOMElementImpl::getChildNodes() const                   {return fParent.getChildNodes (); }
548           DOMNode*         DOMElementImpl::getFirstChild() const                   {return fParent.getFirstChild (); }
549           DOMNode*         DOMElementImpl::getLastChild() const                    {return fParent.getLastChild (); }
550     const XMLCh*           DOMElementImpl::getLocalName() const                    {return fNode.getLocalName (); }
551     const XMLCh*           DOMElementImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); }
552           DOMNode*         DOMElementImpl::getNextSibling() const                  {return fChild.getNextSibling (); }
553     const XMLCh*           DOMElementImpl::getNodeValue() const                    {return fNode.getNodeValue (); }
554           DOMDocument*     DOMElementImpl::getOwnerDocument() const                {return fParent.fOwnerDocument; }
555     const XMLCh*           DOMElementImpl::getPrefix() const                       {return fNode.getPrefix (); }
556           DOMNode*         DOMElementImpl::getParentNode() const                   {return fChild.getParentNode (this); }
557           DOMNode*         DOMElementImpl::getPreviousSibling() const              {return fChild.getPreviousSibling (this); }
558           bool             DOMElementImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); }
559           DOMNode*         DOMElementImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
560                                                                                    {return fParent.insertBefore (newChild, refChild); }
561           void             DOMElementImpl::normalize()                             {fParent.normalize (); }
562           DOMNode*         DOMElementImpl::removeChild(DOMNode *oldChild)          {return fParent.removeChild (oldChild); }
563           DOMNode*         DOMElementImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
564                                                                                    {return fParent.replaceChild (newChild, oldChild); }
565           bool             DOMElementImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
566                                                                                    {return fNode.isSupported (feature, version); }
567           void             DOMElementImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); }
568           bool             DOMElementImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other); }
569           void*            DOMElementImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
570                                                                                    {return fNode.setUserData(key, data, handler); }
571           void*            DOMElementImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); }
572           short            DOMElementImpl::compareDocumentPosition(const DOMNode* other) const {return fNode.compareDocumentPosition(other); }
573           const XMLCh*     DOMElementImpl::getTextContent() const                  {return fNode.getTextContent(); }
574           void             DOMElementImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
575           const XMLCh*     DOMElementImpl::lookupPrefix(const XMLCh* namespaceURI) const  {return fNode.lookupPrefix(namespaceURI); }
576           bool             DOMElementImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
577           const XMLCh*     DOMElementImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); }
578           void*            DOMElementImpl::getFeature(const XMLCh* feature, const XMLCh* version) const {return fNode.getFeature(feature, version); }
579
580
581
582bool DOMElementImpl::isEqualNode(const DOMNode* arg) const
583{
584    if (isSameNode(arg)) {
585        return true;
586    }
587
588    if (!fNode.isEqualNode(arg)) {
589        return false;
590    }
591
592    bool hasAttrs = hasAttributes();
593
594    if (hasAttrs != arg->hasAttributes()) {
595        return false;
596    }
597
598    if (hasAttrs) {
599        DOMNamedNodeMap* map1 = getAttributes();
600        DOMNamedNodeMap* map2 = arg->getAttributes();
601
602        XMLSize_t len = map1->getLength();
603        if (len != map2->getLength()) {
604            return false;
605        }
606        for (XMLSize_t i = 0; i < len; i++) {
607            DOMNode* n1 = map1->item(i);
608            if (!n1->getLocalName()) { // DOM Level 1 Node
609                DOMNode* n2 = map2->getNamedItem(n1->getNodeName());
610                if (!n2 || !n1->isEqualNode(n2)) {
611                    return false;
612                }
613            }
614            else {
615                DOMNode* n2 = map2->getNamedItemNS(n1->getNamespaceURI(),
616                                              n1->getLocalName());
617                if (!n2 || !n1->isEqualNode(n2)) {
618                    return false;
619                }
620            }
621        }
622    }
623
624    return fParent.isEqualNode(arg);
625}
626
627DOMNode* DOMElementImpl::rename(const XMLCh* namespaceURI, const XMLCh* name)
628{
629    DOMDocumentImpl* doc = (DOMDocumentImpl*) fParent.fOwnerDocument;
630
631    if (!namespaceURI || !*namespaceURI) {
632        fName = doc->getPooledString(name);
633        fAttributes->reconcileDefaultAttributes(getDefaultAttributes());
634
635        // and fire user data NODE_RENAMED event
636        castToNodeImpl(this)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, this);
637
638        return this;
639    }
640    else {
641
642        // create a new ElementNS
643        DOMElementNSImpl* newElem = (DOMElementNSImpl*)doc->createElementNS(namespaceURI, name);
644
645        // transfer the userData
646        doc->transferUserData(castToNodeImpl(this), castToNodeImpl(newElem));
647
648        // remove old node from parent if any
649        DOMNode* parent = getParentNode();
650        DOMNode* nextSib = getNextSibling();
651        if (parent) {
652            parent->removeChild(this);
653        }
654
655        // move children to new node
656        DOMNode* child = getFirstChild();
657        while (child) {
658            removeChild(child);
659            newElem->appendChild(child);
660            child = getFirstChild();
661        }
662
663        // insert new node where old one was
664        if (parent) {
665            parent->insertBefore(newElem, nextSib);
666        }
667
668        // move specified attributes to new node
669        newElem->fAttributes->moveSpecifiedAttributes(fAttributes);
670
671        // and fire user data NODE_RENAMED event
672        castToNodeImpl(newElem)->callUserDataHandlers(DOMUserDataHandler::NODE_RENAMED, this, newElem);
673
674        return newElem;
675    }
676}
677
678const DOMTypeInfo *DOMElementImpl::getSchemaTypeInfo() const
679{
680    return &DOMTypeInfoImpl::g_DtdValidatedElement;
681}
682
683// DOMElementTraversal
684DOMElement * DOMElementImpl::getFirstElementChild() const
685{
686    DOMNode* n = getFirstChild();
687    while (n != NULL) {
688        switch (n->getNodeType()) {
689            case DOMNode::ELEMENT_NODE:
690                return (DOMElement*) n;
691            case DOMNode::ENTITY_REFERENCE_NODE:
692                {
693                    DOMElement* e = getFirstElementChild(n);
694                    if (e != NULL)
695                        return e;
696                }
697                break;
698            default:
699                break;
700        }
701        n = n->getNextSibling();
702    }
703    return NULL;
704}
705
706DOMElement * DOMElementImpl::getLastElementChild() const
707{
708    DOMNode* n = getLastChild();
709    while (n != NULL) {
710        switch (n->getNodeType()) {
711            case DOMNode::ELEMENT_NODE:
712                return (DOMElement*) n;
713            case DOMNode::ENTITY_REFERENCE_NODE:
714                {
715                    DOMElement* e = getLastElementChild(n);
716                    if (e != NULL)
717                        return e;
718                }
719                break;
720            default:
721                break;
722        }
723        n = n->getPreviousSibling();
724    }
725    return NULL;
726}
727
728DOMElement * DOMElementImpl::getNextElementSibling() const
729{
730    DOMNode* n = getNextLogicalSibling(this);
731    while (n != NULL) {
732        switch (n->getNodeType()) {
733            case DOMNode::ELEMENT_NODE:
734                return (DOMElement*) n;
735            case DOMNode::ENTITY_REFERENCE_NODE:
736                {
737                    DOMElement* e = getFirstElementChild(n);
738                    if (e != NULL)
739                        return e;
740                }
741                break;
742            default:
743                break;
744        }
745        n = getNextLogicalSibling(n);
746    }
747    return NULL;
748}
749
750DOMElement * DOMElementImpl::getPreviousElementSibling() const
751{
752    DOMNode* n = getPreviousLogicalSibling(this);
753    while (n != NULL) {
754        switch (n->getNodeType()) {
755            case DOMNode::ELEMENT_NODE:
756                return (DOMElement*) n;
757            case DOMNode::ENTITY_REFERENCE_NODE:
758                {
759                    DOMElement* e = getLastElementChild(n);
760                    if (e != NULL)
761                        return e;
762                }
763                break;
764            default:
765                break;
766        }
767        n = getPreviousLogicalSibling(n);
768    }
769    return NULL;
770}
771
772XMLSize_t DOMElementImpl::getChildElementCount() const
773{
774    XMLSize_t count = 0;
775    DOMElement* child = getFirstElementChild();
776    while (child != NULL) {
777        ++count;
778        child = child->getNextElementSibling();
779    }
780    return count;
781}
782
783// Returns the first element node found from a
784// non-recursive in order traversal of the given node.
785DOMElement* DOMElementImpl::getFirstElementChild(const DOMNode* n) const
786{
787    const DOMNode* top = n;
788    while (n != NULL) {
789        if (n->getNodeType() == DOMNode::ELEMENT_NODE) {
790            return (DOMElement*) n;
791        }
792        DOMNode* next = n->getFirstChild();
793        while (next == NULL) {
794            if (top == n) {
795                break;
796            }
797            next = n->getNextSibling();
798            if (next == NULL) {
799                n = n->getParentNode();
800                if (n == NULL || top == n) {
801                    return NULL;
802                }
803            }
804        }
805        n = next;
806    }
807    return NULL;
808}
809
810// Returns the first element node found from a
811// non-recursive reverse order traversal of the given node.
812DOMElement* DOMElementImpl::getLastElementChild(const DOMNode* n) const
813{
814    const DOMNode* top = n;
815    while (n != NULL) {
816        if (n->getNodeType() == DOMNode::ELEMENT_NODE) {
817            return (DOMElement*) n;
818        }
819        DOMNode* next = n->getLastChild();
820        while (next == NULL) {
821            if (top == n) {
822                break;
823            }
824            next = n->getPreviousSibling();
825            if (next == NULL) {
826                n = n->getParentNode();
827                if (n == NULL || top == n) {
828                    return NULL;
829                }
830            }
831        }
832        n = next;
833    }
834    return NULL;
835}
836
837// Returns the next logical sibling with respect to the given node.
838DOMNode* DOMElementImpl::getNextLogicalSibling(const DOMNode* n) const
839{
840    DOMNode* next = n->getNextSibling();
841    // If "n" has no following sibling and its parent is an entity reference node we
842    // need to continue the search through the following siblings of the entity
843    // reference as these are logically siblings of the given node.
844    if (next == NULL) {
845        DOMNode* parent = n->getParentNode();
846        while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
847            next = parent->getNextSibling();
848            if (next != NULL) {
849                break;
850            }
851            parent = parent->getParentNode();
852        }
853    }
854    return next;
855}
856
857// Returns the previous logical sibling with respect to the given node.
858DOMNode* DOMElementImpl::getPreviousLogicalSibling(const DOMNode* n) const
859{
860    DOMNode* prev = n->getPreviousSibling();
861    // If "n" has no previous sibling and its parent is an entity reference node we
862    // need to continue the search through the previous siblings of the entity
863    // reference as these are logically siblings of the given node.
864    if (prev == NULL) {
865        DOMNode* parent = n->getParentNode();
866        while (parent != NULL && parent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
867            prev = parent->getPreviousSibling();
868            if (prev != NULL) {
869                break;
870            }
871            parent = parent->getParentNode();
872        }
873    }
874    return prev;
875}
876
877
878XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.