source: icXML/icXML-devel/src/xercesc/dom/impl/DOMNodeImpl.cpp @ 2777

Last change on this file since 2777 was 2777, checked in by cameron, 7 years ago

Set up to use xercesc/icxercesc root-relative paths for all includes

File size: 33.3 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: DOMNodeImpl.cpp 673428 2008-07-02 16:00:35Z amassari $
20 */
21
22// This class doesn't support having any children, and implements the behavior
23// of an empty NodeList as far getChildNodes is concerned.
24// The ParentNode subclass overrides this behavior.
25
26
27#include <xercesc/dom/impl/DOMCasts.hpp>
28
29#include <xercesc/dom/impl/DOMDocumentTypeImpl.hpp>
30#include <xercesc/dom/impl/DOMElementImpl.hpp>
31#include <xercesc/dom/impl/DOMAttrImpl.hpp>
32
33#include <xercesc/dom/DOMImplementation.hpp>
34#include <xercesc/dom/DOMException.hpp>
35
36#include <xercesc/util/XMLUniDefs.hpp>
37#include <icxercesc/util/PlatformUtils.hpp>
38#include <xercesc/util/XMLInitializer.hpp>
39#include <stdio.h>
40#include <assert.h>
41
42XERCES_CPP_NAMESPACE_BEGIN
43
44//Though DOMNodeImpl does not derivate from DOMNode, it shares
45//the same GetDOMNodeMemoryManager
46
47const unsigned short DOMNodeImpl::READONLY     = 0x1<<0;
48const unsigned short DOMNodeImpl::SYNCDATA     = 0x1<<1;
49const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2;
50const unsigned short DOMNodeImpl::OWNED        = 0x1<<3;
51const unsigned short DOMNodeImpl::FIRSTCHILD   = 0x1<<4;
52const unsigned short DOMNodeImpl::SPECIFIED    = 0x1<<5;
53const unsigned short DOMNodeImpl::IGNORABLEWS  = 0x1<<6;
54const unsigned short DOMNodeImpl::SETVALUE     = 0x1<<7;
55const unsigned short DOMNodeImpl::ID_ATTR      = 0x1<<8;
56const unsigned short DOMNodeImpl::USERDATA     = 0x1<<9;
57const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10;
58const unsigned short DOMNodeImpl::CHILDNODE    = 0x1<<11;
59const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12;
60
61//
62//
63static DOMNodeListImpl *gEmptyNodeList = 0; // Singleton empty node list.
64
65void XMLInitializer::initializeDOMNodeListImpl()
66{
67    gEmptyNodeList = new DOMNodeListImpl(0);
68}
69
70void XMLInitializer::terminateDOMNodeListImpl()
71{
72    delete gEmptyNodeList;
73    gEmptyNodeList = 0;
74}
75
76// -----------------------------------------------------------------------
77//  DOMNodeImpl Functions
78// -----------------------------------------------------------------------
79DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode)
80:  fOwnerNode(ownerNode)
81{
82    this->flags = 0;
83    // as long as we do not have any owner, fOwnerNode is our ownerDocument
84}
85
86// This only makes a shallow copy, cloneChildren must also be called for a
87// deep clone
88DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other)
89{
90    this->flags = other.flags;
91    this->isReadOnly(false);
92
93    // Need to break the association w/ original parent
94    this->fOwnerNode = other.getOwnerDocument();
95    this->isOwned(false);
96}
97
98
99
100DOMNodeImpl::~DOMNodeImpl() {
101}
102
103
104DOMNode * DOMNodeImpl::appendChild(DOMNode *)
105{
106    // Only node types that don't allow children will use this default function.
107    //   Others will go to DOMParentNode::appendChild.
108    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
109    return 0;
110    //  return insertBefore(newChild, 0);
111}
112
113
114DOMNamedNodeMap * DOMNodeImpl::getAttributes() const {
115    return 0;                   // overridden in ElementImpl
116}
117
118
119DOMNodeList *DOMNodeImpl::getChildNodes() const {
120    return gEmptyNodeList;
121}
122
123
124
125DOMNode * DOMNodeImpl::getFirstChild() const {
126    return 0;                   // overridden in ParentNode
127}
128
129
130DOMNode * DOMNodeImpl::getLastChild() const
131{
132    return 0;                   // overridden in ParentNode
133}
134
135
136DOMNode * DOMNodeImpl::getNextSibling() const {
137    return 0;                // overridden in ChildNode
138}
139
140
141const XMLCh * DOMNodeImpl::getNodeValue() const {
142    return 0;                    // Overridden by anything that has a value
143}
144
145
146//
147//  Unlike the external getOwnerDocument, this one returns the owner document
148//     for document nodes as well as all of the other node types.
149//
150DOMDocument *DOMNodeImpl::getOwnerDocument() const
151{
152    if (!this->isLeafNode())
153    {
154        DOMElementImpl *ep = (DOMElementImpl *)castToNode(this);
155        return ep->fParent.fOwnerDocument;
156    }
157
158    //  Leaf node types - those that cannot have children, like Text.
159    if (isOwned()) {
160
161        DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument();
162
163        if (!ownerDoc) {
164
165            assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
166            return  (DOMDocument *)fOwnerNode;
167        }
168        else {
169            return ownerDoc;
170        }
171    } else {
172        assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
173        return  (DOMDocument *)fOwnerNode;
174    }
175}
176
177
178void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) {
179    // if we have an owner we rely on it to have it right
180    // otherwise fOwnerNode is our ownerDocument
181    if (!isOwned()) {
182        // revisit.  Problem with storage for doctype nodes that were created
183        //                on the system heap in advance of having a document.
184        fOwnerNode = doc;
185    }
186}
187
188DOMNode * DOMNodeImpl::getParentNode() const
189{
190    return 0;                // overridden in ChildNode
191}
192
193
194DOMNode*  DOMNodeImpl::getPreviousSibling() const
195{
196    return 0;                // overridden in ChildNode
197}
198
199bool DOMNodeImpl::hasChildNodes() const
200{
201    return false;
202}
203
204
205
206DOMNode *DOMNodeImpl::insertBefore(DOMNode *, DOMNode *) {
207    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNodeMemoryManager);
208    return 0;
209}
210
211
212DOMNode *DOMNodeImpl::removeChild(DOMNode *)
213{
214    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager);
215    return 0;
216}
217
218
219DOMNode *DOMNodeImpl::replaceChild(DOMNode *, DOMNode *)
220{
221    throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager);
222    return 0;
223}
224
225
226
227void DOMNodeImpl::setNodeValue(const XMLCh *)
228{
229    // Default behavior is to do nothing, overridden in some subclasses
230}
231
232
233
234void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
235{
236    this->isReadOnly(readOnl);
237
238    if (deep) {
239        for (DOMNode *mykid = castToNode(this)->getFirstChild();
240            mykid != 0;
241            mykid = mykid->getNextSibling()) {
242
243            short kidNodeType = mykid->getNodeType();
244
245            switch (kidNodeType) {
246            case DOMNode::ENTITY_REFERENCE_NODE:
247                break;
248            case DOMNode::ELEMENT_NODE:
249                ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true);
250                break;
251            case DOMNode::DOCUMENT_TYPE_NODE:
252               ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true);
253               break;
254            default:
255                castToNodeImpl(mykid)->setReadOnly(readOnl, true);
256                break;
257            }
258        }
259    }
260}
261
262
263//Introduced in DOM Level 2
264
265void DOMNodeImpl::normalize()
266{
267    // does nothing by default, overridden by subclasses
268}
269
270
271bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
272{
273    return DOMImplementation::getImplementation()->hasFeature(feature, version);
274}
275
276const XMLCh *DOMNodeImpl::getNamespaceURI() const
277{
278    return 0;
279}
280
281const XMLCh *DOMNodeImpl::getPrefix() const
282{
283    return 0;
284}
285
286const XMLCh *DOMNodeImpl::getLocalName() const
287{
288    return 0;
289}
290
291
292void DOMNodeImpl::setPrefix(const XMLCh *)
293{
294    throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager);
295}
296
297
298bool DOMNodeImpl::hasAttributes() const {
299    return 0;                   // overridden in ElementImpl
300}
301
302
303
304
305
306const XMLCh *DOMNodeImpl::getXmlString()      {return XMLUni::fgXMLString;}
307const XMLCh *DOMNodeImpl::getXmlURIString()   {return XMLUni::fgXMLURIName;}
308const XMLCh *DOMNodeImpl::getXmlnsString()    {return XMLUni::fgXMLNSString;}
309const XMLCh *DOMNodeImpl::getXmlnsURIString() {return XMLUni::fgXMLNSURIName;}
310
311//Return a URI mapped from the given prefix and namespaceURI as below
312//    prefix   namespaceURI    output
313//---------------------------------------------------
314//    "xml"     xmlURI          xmlURI
315//    "xml"     otherwise       NAMESPACE_ERR
316//    "xmlns"   xmlnsURI        xmlnsURI (nType = ATTRIBUTE_NODE only)
317//    "xmlns"   otherwise       NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
318//    != null   null or ""      NAMESPACE_ERR
319//    else      any             namesapceURI
320const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix,
321                                     const XMLCh *namespaceURI, short nType)
322{
323    if (prefix == 0)
324        return namespaceURI;
325
326    if (XMLString::equals(prefix, XMLUni::fgXMLString))  {
327        if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName))
328            return XMLUni::fgXMLURIName;
329        throw DOMException(DOMException::NAMESPACE_ERR, 0);
330    } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, XMLUni::fgXMLNSString)) {
331        if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName))
332            return XMLUni::fgXMLNSURIName;
333        throw DOMException(DOMException::NAMESPACE_ERR, 0);
334    } else if (namespaceURI == 0 || *namespaceURI == 0)
335        throw DOMException(DOMException::NAMESPACE_ERR, 0);
336    return namespaceURI;
337}
338
339//Introduced in DOM Level 3
340void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
341{
342   if (!data && !hasUserData())
343       return 0;
344
345    hasUserData(true);
346    return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler);
347}
348
349void* DOMNodeImpl::getUserData(const XMLCh* key) const
350{
351   if (hasUserData())
352       return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key);
353    return 0;
354}
355
356void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
357                                       const DOMNode* src,
358                                       DOMNode* dst) const
359{
360    DOMDocumentImpl* doc=(DOMDocumentImpl*)getOwnerDocument();
361    if (doc)
362        doc->callUserDataHandlers(this, operation, src, dst);
363}
364
365bool DOMNodeImpl::isSameNode(const DOMNode* other) const
366{
367    return (castToNode(this) == other);
368}
369
370bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const
371{
372    if (!arg)
373        return false;
374
375    if (isSameNode(arg)) {
376        return true;
377    }
378
379    DOMNode* thisNode = castToNode(this);
380
381    if (arg->getNodeType() != thisNode->getNodeType()) {
382        return false;
383    }
384
385    // the compareString will check null string as well
386    if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) {
387        return false;
388    }
389
390    if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) {
391        return false;
392    }
393
394    if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) {
395        return false;
396    }
397
398    if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) {
399        return false;
400    }
401
402    if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) {
403        return false;
404    }
405
406    return true;
407}
408
409const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* namespaceURI) const {
410    // REVISIT: When Namespaces 1.1 comes out this may not be true
411    // Prefix can't be bound to null namespace
412    if (namespaceURI == 0) {
413        return 0;
414    }
415
416    DOMNode *thisNode = castToNode(this);
417
418    short type = thisNode->getNodeType();
419
420    switch (type) {
421    case DOMNode::ELEMENT_NODE: {
422        return lookupPrefix(namespaceURI, (DOMElement*)thisNode);
423    }
424    case DOMNode::DOCUMENT_NODE:{
425        return ((DOMDocument*)thisNode)->getDocumentElement()->lookupPrefix(namespaceURI);
426    }
427
428    case DOMNode::ENTITY_NODE :
429    case DOMNode::NOTATION_NODE:
430    case DOMNode::DOCUMENT_FRAGMENT_NODE:
431    case DOMNode::DOCUMENT_TYPE_NODE:
432        // type is unknown
433        return 0;
434    case DOMNode::ATTRIBUTE_NODE:{
435        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
436            return fOwnerNode->lookupPrefix(namespaceURI);
437        }
438        return 0;
439    }
440    default:{
441        DOMNode *ancestor = getElementAncestor(thisNode);
442        if (ancestor != 0) {
443            return ancestor->lookupPrefix(namespaceURI);
444        }
445        return 0;
446    }
447    }
448}
449
450
451DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const {
452    DOMNode* parent = currentNode->getParentNode();
453    while(parent != 0) {
454        short type = parent->getNodeType();
455        if (type == DOMNode::ELEMENT_NODE) {
456            return parent;
457        }
458        parent=parent->getParentNode();
459    }
460    return 0;
461}
462
463
464const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* const namespaceURI, DOMElement *originalElement) const {
465    DOMNode *thisNode = castToNode(this);
466
467    const XMLCh* ns = thisNode->getNamespaceURI();
468    // REVISIT: if no prefix is available is it null or empty string, or
469    //          could be both?
470    const XMLCh* prefix = thisNode->getPrefix();
471
472    if (ns != 0 && XMLString::equals(ns,namespaceURI) && prefix != 0) {
473        const XMLCh* foundNamespace =  originalElement->lookupNamespaceURI(prefix);
474        if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
475            return prefix;
476        }
477    }
478    if (thisNode->hasAttributes()) {
479        DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
480
481        if(nodeMap != 0) {
482            XMLSize_t length = nodeMap->getLength();
483
484            for (XMLSize_t i = 0;i < length;i++) {
485                DOMNode *attr = nodeMap->item(i);
486                const XMLCh* attrPrefix = attr->getPrefix();
487                const XMLCh* value = attr->getNodeValue();
488
489                ns = attr->getNamespaceURI();
490
491                if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
492                    // DOM Level 2 nodes
493                    if ((attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) &&
494                        XMLString::equals(value, namespaceURI)) {
495                        const XMLCh* localname= attr->getLocalName();
496                        const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(localname);
497                        if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
498                            return localname;
499                        }
500                    }
501                }
502            }
503        }
504    }
505    DOMNode *ancestor = getElementAncestor(thisNode);
506    if (ancestor != 0) {
507        return castToNodeImpl(ancestor)->lookupPrefix(namespaceURI, originalElement);
508    }
509    return 0;
510}
511
512const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const  {
513    DOMNode *thisNode = castToNode(this);
514
515    short type = thisNode->getNodeType();
516    switch (type) {
517    case DOMNode::ELEMENT_NODE : {
518        const XMLCh* ns = thisNode->getNamespaceURI();
519        const XMLCh* prefix = thisNode->getPrefix();
520        if (ns != 0) {
521            // REVISIT: is it possible that prefix is empty string?
522            if (specifiedPrefix == 0 && prefix == specifiedPrefix) {
523                // looking for default namespace
524                return ns;
525            } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) {
526                // non default namespace
527                return ns;
528            }
529        }
530        if (thisNode->hasAttributes()) {
531            DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
532            if(nodeMap != 0) {
533                XMLSize_t length = nodeMap->getLength();
534                for (XMLSize_t i = 0;i < length;i++) {
535                    DOMNode *attr = nodeMap->item(i);
536                    const XMLCh *attrPrefix = attr->getPrefix();
537                    const XMLCh *value = attr->getNodeValue();
538                    ns = attr->getNamespaceURI();
539
540                    if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) {
541                        // at this point we are dealing with DOM Level 2 nodes only
542                        if (specifiedPrefix == 0 &&
543                            XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) {
544                            // default namespace
545                            return value;
546                        } else if (attrPrefix != 0 &&
547                                   XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) &&
548                                   XMLString::equals(attr->getLocalName(), specifiedPrefix)) {
549                            // non default namespace
550                            return value;
551                        }
552                    }
553                }
554            }
555        }
556        DOMNode *ancestor = getElementAncestor(thisNode);
557        if (ancestor != 0) {
558            return ancestor->lookupNamespaceURI(specifiedPrefix);
559        }
560        return 0;
561    }
562    case DOMNode::DOCUMENT_NODE : {
563        return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix);
564    }
565    case DOMNode::ENTITY_NODE :
566    case DOMNode::NOTATION_NODE:
567    case DOMNode::DOCUMENT_FRAGMENT_NODE:
568    case DOMNode::DOCUMENT_TYPE_NODE:
569        // type is unknown
570        return 0;
571    case DOMNode::ATTRIBUTE_NODE:{
572        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
573            return fOwnerNode->lookupNamespaceURI(specifiedPrefix);
574        }
575        return 0;
576    }
577    default:{
578        DOMNode *ancestor = getElementAncestor(castToNode(this));
579        if (ancestor != 0) {
580            return ancestor->lookupNamespaceURI(specifiedPrefix);
581        }
582        return 0;
583    }
584    }
585}
586
587
588const XMLCh*     DOMNodeImpl::getBaseURI() const{
589    DOMNode *thisNode = castToNode(this);
590    DOMNode* parent = thisNode->getParentNode();
591    if (parent)
592        return parent->getBaseURI();
593    else
594        return 0;
595}
596
597const DOMNode*   DOMNodeImpl::getTreeParentNode(const DOMNode* node) const {
598    const DOMNode* parent=node->getParentNode();
599    if(parent)
600        return parent;
601    short nodeType=node->getNodeType();
602    switch(nodeType)
603    {
604    case DOMNode::ATTRIBUTE_NODE: return ((const DOMAttr*)node)->getOwnerElement();
605    case DOMNode::NOTATION_NODE:
606    case DOMNode::ENTITY_NODE:    return node->getOwnerDocument()->getDoctype();
607    }
608    return 0;
609}
610
611short            DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const {
612    DOMNode* thisNode = castToNode(this);
613
614    // If the two nodes being compared are the same node, then no flags are set on the return.
615    if (thisNode == other)
616        return 0;
617
618    //if this is a custom node, we don't really know what to do, just return
619    //user should provide its own compareDocumentPosition logic, and shouldn't reach here
620    if(thisNode->getNodeType() > 12) {
621        return 0;
622    }
623
624    //if it is a custom node we must ask it for the order
625    if(other->getNodeType() > 12) {
626        return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode));
627    }
628
629    // Otherwise, the order of two nodes is determined by looking for common containers --
630    // containers which contain both. A node directly contains any child nodes.
631    // A node also directly contains any other nodes attached to it such as attributes
632    // contained in an element or entities and notations contained in a document type.
633    // Nodes contained in contained nodes are also contained, but less-directly as
634    // the number of intervening containers increases.
635
636    // If one of the nodes being compared contains the other node, then the container precedes
637    // the contained node, and reversely the contained node follows the container. For example,
638    // when comparing an element against its own attribute or child, the element node precedes
639    // its attribute node and its child node, which both follow it.
640
641    const DOMNode* tmpNode;
642    const DOMNode* myRoot = castToNode(this);
643    int myDepth=0;
644    while((tmpNode=getTreeParentNode(myRoot))!=0)
645    {
646        myRoot=tmpNode;
647        if(myRoot==other)
648            return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING;
649        myDepth++;
650    }
651
652    const DOMNode* hisRoot = other;
653    int hisDepth=0;
654    while((tmpNode=getTreeParentNode(hisRoot))!=0)
655    {
656        hisRoot=tmpNode;
657        if(hisRoot==thisNode)
658            return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING;
659        hisDepth++;
660    }
661
662    // If there is no common container node, then the order is based upon order between the
663    // root container of each node that is in no container. In this case, the result is
664    // disconnected and implementation-specific. This result is stable as long as these
665    // outer-most containing nodes remain in memory and are not inserted into some other
666    // containing node. This would be the case when the nodes belong to different documents
667    // or fragments, and cloning the document or inserting a fragment might change the order.
668
669    if(myRoot!=hisRoot)
670        return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
671              (myRoot<hisRoot?DOMNode::DOCUMENT_POSITION_PRECEDING:DOMNode::DOCUMENT_POSITION_FOLLOWING);
672
673    // If neither of the previous cases apply, then there exists a most-direct container common
674    // to both nodes being compared. In this case, the order is determined based upon the two
675    // determining nodes directly contained in this most-direct common container that either
676    // are or contain the corresponding nodes being compared.
677
678    // if the two depths are different, go to the same one
679    myRoot = castToNode(this);
680    hisRoot = other;
681    if (myDepth > hisDepth) {
682        for (int i= 0 ; i < myDepth - hisDepth; i++)
683            myRoot = getTreeParentNode(myRoot);
684    }
685    else {
686        for (int i = 0; i < hisDepth - myDepth; i++)
687            hisRoot = getTreeParentNode(hisRoot);
688    }
689
690    // We now have nodes at the same depth in the tree.  Find a common ancestor.
691    const DOMNode *myNodeP=myRoot;
692        const DOMNode *hisNodeP=hisRoot;
693    while(myRoot!=hisRoot)
694    {
695        myNodeP = myRoot;
696        hisNodeP = hisRoot;
697        myRoot = getTreeParentNode(myRoot);
698        hisRoot = getTreeParentNode(hisRoot);
699    }
700
701    short myNodeType=myNodeP->getNodeType();
702    short hisNodeType=hisNodeP->getNodeType();
703    bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE);
704    bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE);
705
706    // If these two determining nodes are both child nodes, then the natural DOM order of these
707    // determining nodes within the containing node is returned as the order of the corresponding nodes.
708    // This would be the case, for example, when comparing two child elements of the same element.
709    if(bMyNodeIsChild && bHisNodeIsChild)
710    {
711        while(myNodeP != 0)
712        {
713            myNodeP = myNodeP->getNextSibling();
714            if(myNodeP == hisNodeP)
715                return DOMNode::DOCUMENT_POSITION_FOLLOWING;
716        }
717        return DOMNode::DOCUMENT_POSITION_PRECEDING;
718    }
719
720    // If one of the two determining nodes is a child node and the other is not, then the corresponding
721    // node of the child node follows the corresponding node of the non-child node. This would be the case,
722    // for example, when comparing an attribute of an element with a child element of the same element.
723    else if(!bMyNodeIsChild && bHisNodeIsChild)
724        return DOMNode::DOCUMENT_POSITION_FOLLOWING;
725    else if(bMyNodeIsChild && !bHisNodeIsChild)
726        return DOMNode::DOCUMENT_POSITION_PRECEDING;
727
728    else
729    {
730        // If neither of the two determining node is a child node and one determining node has a greater value
731        // of nodeType than the other, then the corresponding node precedes the other. This would be the case,
732        // for example, when comparing an entity of a document type against a notation of the same document type.
733        if(myNodeType!=hisNodeType)
734            return (myNodeType<hisNodeType)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING;
735
736        // If neither of the two determining node is a child node and nodeType is the same for both determining
737        // nodes, then an implementation-dependent order between the determining nodes is returned. This order
738        // is stable as long as no nodes of the same nodeType are inserted into or removed from the direct container.
739        // This would be the case, for example, when comparing two attributes of the same element, and inserting
740        // or removing additional attributes might change the order between existing attributes.
741        return DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | ((myNodeP<hisNodeP)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING);
742    }
743    // REVISIT:  shouldn't get here.   Should probably throw an
744    // exception
745    return 0;
746}
747
748short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const {
749
750    if(pattern & DOMNode::DOCUMENT_POSITION_PRECEDING) {
751        pattern &= !DOMNode::DOCUMENT_POSITION_PRECEDING;
752        pattern |= DOMNode::DOCUMENT_POSITION_FOLLOWING;
753    }
754    else if(pattern & DOMNode::DOCUMENT_POSITION_FOLLOWING) {
755        pattern &= !DOMNode::DOCUMENT_POSITION_FOLLOWING;
756        pattern |= DOMNode::DOCUMENT_POSITION_PRECEDING;
757    }
758
759    if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) {
760        pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
761        pattern |= DOMNode::DOCUMENT_POSITION_CONTAINS;
762    }
763    else if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINS) {
764        pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINS;
765        pattern |= DOMNode::DOCUMENT_POSITION_CONTAINED_BY;
766    }
767
768    return pattern;
769}
770
771/***
772 *
773 *   Excerpt from http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/core.html#Node3-textContent
774 *
775 *   textContent of type DOMString, introduced in DOM Level 3
776 *
777 *   This attribute returns the text content of this node and its descendants. When it is defined
778 *   to be null, setting it has no effect.
779 *
780 *   When set, any possible children this node may have are removed and replaced by a single Text node
781 *   containing the string this attribute is set to.
782 *
783 *   On getting, no serialization is performed, the returned string does not contain any markup.
784 *   No whitespace normalization is performed, the returned string does not contain the element content
785 *   whitespaces Fundamental Interfaces.
786 *
787 *   Similarly, on setting, no parsing is performed either, the input string is taken as pure textual content.
788 *
789 *   The string returned is made of the text content of this node depending on its type,
790 *   as defined below:
791 *
792 *       Node type                                           Content
793 *   ====================       ========================================================================
794 *     ELEMENT_NODE               concatenation of the textContent attribute value of every child node,
795 *     ENTITY_NODE                            excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes.
796 *     ENTITY_REFERENCE_NODE      This is the empty string if the node has no children.
797 *     DOCUMENT_FRAGMENT_NODE
798 *    --------------------------------------------------------------------------------------------------
799 *     ATTRIBUTE_NODE
800 *     TEXT_NODE
801 *     CDATA_SECTION_NODE
802 *     COMMENT_NODE,
803 *     PROCESSING_INSTRUCTION_NODE   nodeValue
804 *    --------------------------------------------------------------------------------------------------
805 *     DOCUMENT_NODE,
806 *     DOCUMENT_TYPE_NODE,
807 *     NOTATION_NODE                 null
808 *
809 ***/
810
811const XMLCh*     DOMNodeImpl::getTextContent() const
812{
813        XMLSize_t nBufferLength = 0;
814
815        getTextContent(NULL, nBufferLength);
816        XMLCh* pzBuffer = (XMLCh*)((DOMDocumentImpl*)getOwnerDocument())->allocate((nBufferLength+1) * sizeof(XMLCh));
817        getTextContent(pzBuffer, nBufferLength);
818        pzBuffer[nBufferLength] = 0;
819
820        return pzBuffer;
821
822}
823
824const XMLCh*    DOMNodeImpl::getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const
825{
826        XMLSize_t nRemainingBuffer = rnBufferLength;
827        rnBufferLength = 0;
828
829        if (pzBuffer)
830                *pzBuffer = 0;
831
832        DOMNode *thisNode = castToNode(this);
833
834        switch (thisNode->getNodeType())
835        {
836        case DOMNode::ELEMENT_NODE:
837    case DOMNode::ENTITY_NODE:
838    case DOMNode::ENTITY_REFERENCE_NODE:
839    case DOMNode::DOCUMENT_FRAGMENT_NODE:
840    {
841                DOMNode* current = thisNode->getFirstChild();
842
843                while (current != NULL)
844                {
845                        if (current->getNodeType() != DOMNode::COMMENT_NODE &&
846                                current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE)
847                        {
848
849                                if (pzBuffer)
850                                {
851                                        XMLSize_t nContentLength = nRemainingBuffer;
852                                        castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength);
853                                        rnBufferLength += nContentLength;
854                                        nRemainingBuffer -= nContentLength;
855                                }
856                                else
857                                {
858                                        XMLSize_t nContentLength = 0;
859                                        castToNodeImpl(current)->getTextContent(NULL, nContentLength);
860                                        rnBufferLength += nContentLength;
861                                }
862                        }
863
864                        current = current->getNextSibling();
865
866                }
867    }
868
869    break;
870
871    case DOMNode::ATTRIBUTE_NODE:
872    case DOMNode::TEXT_NODE:
873    case DOMNode::CDATA_SECTION_NODE:
874    case DOMNode::COMMENT_NODE:
875    case DOMNode::PROCESSING_INSTRUCTION_NODE:
876    {
877                const XMLCh* pzValue = thisNode->getNodeValue();
878                XMLSize_t nStrLen = XMLString::stringLen(pzValue);
879
880                if (pzBuffer)
881                {
882                        XMLSize_t nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer;
883                        XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength);
884                        rnBufferLength += nContentLength;
885                        nRemainingBuffer -= nContentLength;
886                }
887                else
888                {
889                        rnBufferLength += nStrLen;
890                }
891
892    }
893
894    break;
895
896        /***
897         DOCUMENT_NODE
898                 DOCUMENT_TYPE_NODE
899                 NOTATION_NODE
900        ***/
901        default:
902
903                break;
904        }
905
906        return pzBuffer;
907
908}
909
910void DOMNodeImpl::setTextContent(const XMLCh* textContent){
911    DOMNode *thisNode = castToNode(this);
912    switch (thisNode->getNodeType())
913    {
914        case DOMNode::ELEMENT_NODE:
915        case DOMNode::ENTITY_NODE:
916        case DOMNode::ENTITY_REFERENCE_NODE:
917        case DOMNode::DOCUMENT_FRAGMENT_NODE:
918            {
919                if (isReadOnly())
920                  throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
921
922                // Remove all childs
923                DOMNode* current = thisNode->getFirstChild();
924                while (current != NULL)
925                {
926                    thisNode->removeChild(current);
927                    current = thisNode->getFirstChild();
928                }
929                if (textContent != NULL)
930                {
931                    // Add textnode containing data
932                    current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent);
933                    thisNode->appendChild(current);
934                }
935            }
936            break;
937
938        case DOMNode::ATTRIBUTE_NODE:
939        case DOMNode::TEXT_NODE:
940        case DOMNode::CDATA_SECTION_NODE:
941        case DOMNode::COMMENT_NODE:
942        case DOMNode::PROCESSING_INSTRUCTION_NODE:
943            if (isReadOnly())
944                throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager);
945
946            thisNode->setNodeValue(textContent);
947            break;
948
949        case DOMNode::DOCUMENT_NODE:
950        case DOMNode::DOCUMENT_TYPE_NODE:
951        case DOMNode::NOTATION_NODE:
952            break;
953
954        default:
955            throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager);
956    }
957}
958
959
960bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{
961        DOMNode *thisNode = castToNode(this);
962    short type = thisNode->getNodeType();
963    switch (type) {
964    case DOMNode::ELEMENT_NODE: {
965        const XMLCh *prefix = thisNode->getPrefix();
966
967        // REVISIT: is it possible that prefix is empty string?
968        if (prefix == 0 || !*prefix) {
969            return XMLString::equals(namespaceURI, thisNode->getNamespaceURI());
970        }
971
972        if (thisNode->hasAttributes()) {
973            DOMElement *elem = (DOMElement *)thisNode;
974            DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString);
975            if (attr != 0) {
976                const XMLCh *value = attr->getNodeValue();
977                return XMLString::equals(namespaceURI, value);
978            }
979        }
980        DOMNode *ancestor = getElementAncestor(thisNode);
981        if (ancestor != 0) {
982            return ancestor->isDefaultNamespace(namespaceURI);
983        }
984
985        return false;
986    }
987    case DOMNode::DOCUMENT_NODE:{
988        return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI);
989    }
990
991    case DOMNode::ENTITY_NODE :
992    case DOMNode::NOTATION_NODE:
993    case DOMNode::DOCUMENT_FRAGMENT_NODE:
994    case DOMNode::DOCUMENT_TYPE_NODE:
995        // type is unknown
996        return false;
997    case DOMNode::ATTRIBUTE_NODE:{
998        if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
999            return fOwnerNode->isDefaultNamespace(namespaceURI);
1000
1001        }
1002        return false;
1003    }
1004    default:{
1005        DOMNode *ancestor = getElementAncestor(thisNode);
1006        if (ancestor != 0) {
1007            return ancestor->isDefaultNamespace(namespaceURI);
1008        }
1009        return false;
1010    }
1011
1012    }
1013}
1014
1015void* DOMNodeImpl::getFeature(const XMLCh*, const XMLCh*) const {
1016    return 0;
1017}
1018
1019
1020// non-standard extension
1021void DOMNodeImpl::release()
1022{
1023    // shouldn't reach here
1024    throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager);
1025}
1026
1027XERCES_CPP_NAMESPACE_END
1028
Note: See TracBrowser for help on using the repository browser.