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

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

Original Xerces files with import mods for icxercesc

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