GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: DOMNodeImpl.cpp 673428 2008-07-02 16:00:35Z amassari $ 00020 */ 00021 00022 // This class doesn't support having any children, and implements the behavior 00023 // of an empty NodeList as far getChildNodes is concerned. 00024 // The ParentNode subclass overrides this behavior. 00025 00026 00027 #include "DOMCasts.hpp" 00028 00029 #include "DOMDocumentTypeImpl.hpp" 00030 #include "DOMElementImpl.hpp" 00031 #include "DOMAttrImpl.hpp" 00032 00033 #include <xercesc/dom/DOMImplementation.hpp> 00034 #include <xercesc/dom/DOMException.hpp> 00035 00036 #include <xercesc/util/XMLUniDefs.hpp> 00037 #include <xercesc/util/PlatformUtils.hpp> 00038 #include <xercesc/util/XMLInitializer.hpp> 00039 #include <stdio.h> 00040 #include <assert.h> 00041 00042 XERCES_CPP_NAMESPACE_BEGIN 00043 00044 //Though DOMNodeImpl does not derivate from DOMNode, it shares 00045 //the same GetDOMNodeMemoryManager 00046 00047 const unsigned short DOMNodeImpl::READONLY = 0x1<<0; 00048 const unsigned short DOMNodeImpl::SYNCDATA = 0x1<<1; 00049 const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2; 00050 const unsigned short DOMNodeImpl::OWNED = 0x1<<3; 00051 const unsigned short DOMNodeImpl::FIRSTCHILD = 0x1<<4; 00052 const unsigned short DOMNodeImpl::SPECIFIED = 0x1<<5; 00053 const unsigned short DOMNodeImpl::IGNORABLEWS = 0x1<<6; 00054 const unsigned short DOMNodeImpl::SETVALUE = 0x1<<7; 00055 const unsigned short DOMNodeImpl::ID_ATTR = 0x1<<8; 00056 const unsigned short DOMNodeImpl::USERDATA = 0x1<<9; 00057 const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10; 00058 const unsigned short DOMNodeImpl::CHILDNODE = 0x1<<11; 00059 const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12; 00060 00061 // 00062 // 00063 static DOMNodeListImpl *gEmptyNodeList = 0; // Singleton empty node list. 00064 00065 void XMLInitializer::initializeDOMNodeListImpl() 00066 { 00067 gEmptyNodeList = new DOMNodeListImpl(0); 00068 } 00069 00070 void XMLInitializer::terminateDOMNodeListImpl() 00071 { 00072 delete gEmptyNodeList; 00073 gEmptyNodeList = 0; 00074 } 00075 00076 // ----------------------------------------------------------------------- 00077 // DOMNodeImpl Functions 00078 // ----------------------------------------------------------------------- 00079 DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode) 00080 : fOwnerNode(ownerNode) 00081 { 00082 this->flags = 0; 00083 // as long as we do not have any owner, fOwnerNode is our ownerDocument 00084 } 00085 00086 // This only makes a shallow copy, cloneChildren must also be called for a 00087 // deep clone 00088 DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other) 00089 { 00090 this->flags = other.flags; 00091 this->isReadOnly(false); 00092 00093 // Need to break the association w/ original parent 00094 this->fOwnerNode = other.getOwnerDocument(); 00095 this->isOwned(false); 00096 } 00097 00098 00099 00100 DOMNodeImpl::~DOMNodeImpl() { 00101 } 00102 00103 00104 DOMNode * DOMNodeImpl::appendChild(DOMNode *) 00105 { 00106 // Only node types that don't allow children will use this default function. 00107 // Others will go to DOMParentNode::appendChild. 00108 throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager); 00109 return 0; 00110 // return insertBefore(newChild, 0); 00111 } 00112 00113 00114 DOMNamedNodeMap * DOMNodeImpl::getAttributes() const { 00115 return 0; // overridden in ElementImpl 00116 } 00117 00118 00119 DOMNodeList *DOMNodeImpl::getChildNodes() const { 00120 return gEmptyNodeList; 00121 } 00122 00123 00124 00125 DOMNode * DOMNodeImpl::getFirstChild() const { 00126 return 0; // overridden in ParentNode 00127 } 00128 00129 00130 DOMNode * DOMNodeImpl::getLastChild() const 00131 { 00132 return 0; // overridden in ParentNode 00133 } 00134 00135 00136 DOMNode * DOMNodeImpl::getNextSibling() const { 00137 return 0; // overridden in ChildNode 00138 } 00139 00140 00141 const XMLCh * DOMNodeImpl::getNodeValue() const { 00142 return 0; // Overridden by anything that has a value 00143 } 00144 00145 00146 // 00147 // Unlike the external getOwnerDocument, this one returns the owner document 00148 // for document nodes as well as all of the other node types. 00149 // 00150 DOMDocument *DOMNodeImpl::getOwnerDocument() const 00151 { 00152 if (!this->isLeafNode()) 00153 { 00154 DOMElementImpl *ep = (DOMElementImpl *)castToNode(this); 00155 return ep->fParent.fOwnerDocument; 00156 } 00157 00158 // Leaf node types - those that cannot have children, like Text. 00159 if (isOwned()) { 00160 00161 DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument(); 00162 00163 if (!ownerDoc) { 00164 00165 assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE); 00166 return (DOMDocument *)fOwnerNode; 00167 } 00168 else { 00169 return ownerDoc; 00170 } 00171 } else { 00172 assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE); 00173 return (DOMDocument *)fOwnerNode; 00174 } 00175 } 00176 00177 00178 void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) { 00179 // if we have an owner we rely on it to have it right 00180 // otherwise fOwnerNode is our ownerDocument 00181 if (!isOwned()) { 00182 // revisit. Problem with storage for doctype nodes that were created 00183 // on the system heap in advance of having a document. 00184 fOwnerNode = doc; 00185 } 00186 } 00187 00188 DOMNode * DOMNodeImpl::getParentNode() const 00189 { 00190 return 0; // overridden in ChildNode 00191 } 00192 00193 00194 DOMNode* DOMNodeImpl::getPreviousSibling() const 00195 { 00196 return 0; // overridden in ChildNode 00197 } 00198 00199 bool DOMNodeImpl::hasChildNodes() const 00200 { 00201 return false; 00202 } 00203 00204 00205 00206 DOMNode *DOMNodeImpl::insertBefore(DOMNode *, DOMNode *) { 00207 throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNodeMemoryManager); 00208 return 0; 00209 } 00210 00211 00212 DOMNode *DOMNodeImpl::removeChild(DOMNode *) 00213 { 00214 throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNodeMemoryManager); 00215 return 0; 00216 } 00217 00218 00219 DOMNode *DOMNodeImpl::replaceChild(DOMNode *, DOMNode *) 00220 { 00221 throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMNodeMemoryManager); 00222 return 0; 00223 } 00224 00225 00226 00227 void DOMNodeImpl::setNodeValue(const XMLCh *) 00228 { 00229 // Default behavior is to do nothing, overridden in some subclasses 00230 } 00231 00232 00233 00234 void DOMNodeImpl::setReadOnly(bool readOnl, bool deep) 00235 { 00236 this->isReadOnly(readOnl); 00237 00238 if (deep) { 00239 for (DOMNode *mykid = castToNode(this)->getFirstChild(); 00240 mykid != 0; 00241 mykid = mykid->getNextSibling()) { 00242 00243 short kidNodeType = mykid->getNodeType(); 00244 00245 switch (kidNodeType) { 00246 case DOMNode::ENTITY_REFERENCE_NODE: 00247 break; 00248 case DOMNode::ELEMENT_NODE: 00249 ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true); 00250 break; 00251 case DOMNode::DOCUMENT_TYPE_NODE: 00252 ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true); 00253 break; 00254 default: 00255 castToNodeImpl(mykid)->setReadOnly(readOnl, true); 00256 break; 00257 } 00258 } 00259 } 00260 } 00261 00262 00263 //Introduced in DOM Level 2 00264 00265 void DOMNodeImpl::normalize() 00266 { 00267 // does nothing by default, overridden by subclasses 00268 } 00269 00270 00271 bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const 00272 { 00273 return DOMImplementation::getImplementation()->hasFeature(feature, version); 00274 } 00275 00276 const XMLCh *DOMNodeImpl::getNamespaceURI() const 00277 { 00278 return 0; 00279 } 00280 00281 const XMLCh *DOMNodeImpl::getPrefix() const 00282 { 00283 return 0; 00284 } 00285 00286 const XMLCh *DOMNodeImpl::getLocalName() const 00287 { 00288 return 0; 00289 } 00290 00291 00292 void DOMNodeImpl::setPrefix(const XMLCh *) 00293 { 00294 throw DOMException(DOMException::NAMESPACE_ERR, 0, GetDOMNodeMemoryManager); 00295 } 00296 00297 00298 bool DOMNodeImpl::hasAttributes() const { 00299 return 0; // overridden in ElementImpl 00300 } 00301 00302 00303 00304 00305 00306 const XMLCh *DOMNodeImpl::getXmlString() {return XMLUni::fgXMLString;} 00307 const XMLCh *DOMNodeImpl::getXmlURIString() {return XMLUni::fgXMLURIName;} 00308 const XMLCh *DOMNodeImpl::getXmlnsString() {return XMLUni::fgXMLNSString;} 00309 const XMLCh *DOMNodeImpl::getXmlnsURIString() {return XMLUni::fgXMLNSURIName;} 00310 00311 //Return a URI mapped from the given prefix and namespaceURI as below 00312 // prefix namespaceURI output 00313 //--------------------------------------------------- 00314 // "xml" xmlURI xmlURI 00315 // "xml" otherwise NAMESPACE_ERR 00316 // "xmlns" xmlnsURI xmlnsURI (nType = ATTRIBUTE_NODE only) 00317 // "xmlns" otherwise NAMESPACE_ERR (nType = ATTRIBUTE_NODE only) 00318 // != null null or "" NAMESPACE_ERR 00319 // else any namesapceURI 00320 const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix, 00321 const XMLCh *namespaceURI, short nType) 00322 { 00323 if (prefix == 0) 00324 return namespaceURI; 00325 00326 if (XMLString::equals(prefix, XMLUni::fgXMLString)) { 00327 if (XMLString::equals(namespaceURI, XMLUni::fgXMLURIName)) 00328 return XMLUni::fgXMLURIName; 00329 throw DOMException(DOMException::NAMESPACE_ERR, 0); 00330 } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, XMLUni::fgXMLNSString)) { 00331 if (XMLString::equals(namespaceURI, XMLUni::fgXMLNSURIName)) 00332 return XMLUni::fgXMLNSURIName; 00333 throw DOMException(DOMException::NAMESPACE_ERR, 0); 00334 } else if (namespaceURI == 0 || *namespaceURI == 0) 00335 throw DOMException(DOMException::NAMESPACE_ERR, 0); 00336 return namespaceURI; 00337 } 00338 00339 //Introduced in DOM Level 3 00340 void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) 00341 { 00342 if (!data && !hasUserData()) 00343 return 0; 00344 00345 hasUserData(true); 00346 return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler); 00347 } 00348 00349 void* DOMNodeImpl::getUserData(const XMLCh* key) const 00350 { 00351 if (hasUserData()) 00352 return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key); 00353 return 0; 00354 } 00355 00356 void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation, 00357 const DOMNode* src, 00358 DOMNode* dst) const 00359 { 00360 DOMDocumentImpl* doc=(DOMDocumentImpl*)getOwnerDocument(); 00361 if (doc) 00362 doc->callUserDataHandlers(this, operation, src, dst); 00363 } 00364 00365 bool DOMNodeImpl::isSameNode(const DOMNode* other) const 00366 { 00367 return (castToNode(this) == other); 00368 } 00369 00370 bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const 00371 { 00372 if (!arg) 00373 return false; 00374 00375 if (isSameNode(arg)) { 00376 return true; 00377 } 00378 00379 DOMNode* thisNode = castToNode(this); 00380 00381 if (arg->getNodeType() != thisNode->getNodeType()) { 00382 return false; 00383 } 00384 00385 // the compareString will check null string as well 00386 if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) { 00387 return false; 00388 } 00389 00390 if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) { 00391 return false; 00392 } 00393 00394 if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) { 00395 return false; 00396 } 00397 00398 if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) { 00399 return false; 00400 } 00401 00402 if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) { 00403 return false; 00404 } 00405 00406 return true; 00407 } 00408 00409 const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* namespaceURI) const { 00410 // REVISIT: When Namespaces 1.1 comes out this may not be true 00411 // Prefix can't be bound to null namespace 00412 if (namespaceURI == 0) { 00413 return 0; 00414 } 00415 00416 DOMNode *thisNode = castToNode(this); 00417 00418 short type = thisNode->getNodeType(); 00419 00420 switch (type) { 00421 case DOMNode::ELEMENT_NODE: { 00422 return lookupPrefix(namespaceURI, (DOMElement*)thisNode); 00423 } 00424 case DOMNode::DOCUMENT_NODE:{ 00425 return ((DOMDocument*)thisNode)->getDocumentElement()->lookupPrefix(namespaceURI); 00426 } 00427 00428 case DOMNode::ENTITY_NODE : 00429 case DOMNode::NOTATION_NODE: 00430 case DOMNode::DOCUMENT_FRAGMENT_NODE: 00431 case DOMNode::DOCUMENT_TYPE_NODE: 00432 // type is unknown 00433 return 0; 00434 case DOMNode::ATTRIBUTE_NODE:{ 00435 if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { 00436 return fOwnerNode->lookupPrefix(namespaceURI); 00437 } 00438 return 0; 00439 } 00440 default:{ 00441 DOMNode *ancestor = getElementAncestor(thisNode); 00442 if (ancestor != 0) { 00443 return ancestor->lookupPrefix(namespaceURI); 00444 } 00445 return 0; 00446 } 00447 } 00448 } 00449 00450 00451 DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const { 00452 DOMNode* parent = currentNode->getParentNode(); 00453 while(parent != 0) { 00454 short type = parent->getNodeType(); 00455 if (type == DOMNode::ELEMENT_NODE) { 00456 return parent; 00457 } 00458 parent=parent->getParentNode(); 00459 } 00460 return 0; 00461 } 00462 00463 00464 const XMLCh* DOMNodeImpl::lookupPrefix(const XMLCh* const namespaceURI, DOMElement *originalElement) const { 00465 DOMNode *thisNode = castToNode(this); 00466 00467 const XMLCh* ns = thisNode->getNamespaceURI(); 00468 // REVISIT: if no prefix is available is it null or empty string, or 00469 // could be both? 00470 const XMLCh* prefix = thisNode->getPrefix(); 00471 00472 if (ns != 0 && XMLString::equals(ns,namespaceURI) && prefix != 0) { 00473 const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(prefix); 00474 if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) { 00475 return prefix; 00476 } 00477 } 00478 if (thisNode->hasAttributes()) { 00479 DOMNamedNodeMap *nodeMap = thisNode->getAttributes(); 00480 00481 if(nodeMap != 0) { 00482 XMLSize_t length = nodeMap->getLength(); 00483 00484 for (XMLSize_t i = 0;i < length;i++) { 00485 DOMNode *attr = nodeMap->item(i); 00486 const XMLCh* attrPrefix = attr->getPrefix(); 00487 const XMLCh* value = attr->getNodeValue(); 00488 00489 ns = attr->getNamespaceURI(); 00490 00491 if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) { 00492 // DOM Level 2 nodes 00493 if ((attrPrefix != 0 && XMLString::equals(attrPrefix, XMLUni::fgXMLNSString)) && 00494 XMLString::equals(value, namespaceURI)) { 00495 const XMLCh* localname= attr->getLocalName(); 00496 const XMLCh* foundNamespace = originalElement->lookupNamespaceURI(localname); 00497 if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) { 00498 return localname; 00499 } 00500 } 00501 } 00502 } 00503 } 00504 } 00505 DOMNode *ancestor = getElementAncestor(thisNode); 00506 if (ancestor != 0) { 00507 return castToNodeImpl(ancestor)->lookupPrefix(namespaceURI, originalElement); 00508 } 00509 return 0; 00510 } 00511 00512 const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const { 00513 DOMNode *thisNode = castToNode(this); 00514 00515 short type = thisNode->getNodeType(); 00516 switch (type) { 00517 case DOMNode::ELEMENT_NODE : { 00518 const XMLCh* ns = thisNode->getNamespaceURI(); 00519 const XMLCh* prefix = thisNode->getPrefix(); 00520 if (ns != 0) { 00521 // REVISIT: is it possible that prefix is empty string? 00522 if (specifiedPrefix == 0 && prefix == specifiedPrefix) { 00523 // looking for default namespace 00524 return ns; 00525 } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) { 00526 // non default namespace 00527 return ns; 00528 } 00529 } 00530 if (thisNode->hasAttributes()) { 00531 DOMNamedNodeMap *nodeMap = thisNode->getAttributes(); 00532 if(nodeMap != 0) { 00533 XMLSize_t length = nodeMap->getLength(); 00534 for (XMLSize_t i = 0;i < length;i++) { 00535 DOMNode *attr = nodeMap->item(i); 00536 const XMLCh *attrPrefix = attr->getPrefix(); 00537 const XMLCh *value = attr->getNodeValue(); 00538 ns = attr->getNamespaceURI(); 00539 00540 if (ns != 0 && XMLString::equals(ns, XMLUni::fgXMLNSURIName)) { 00541 // at this point we are dealing with DOM Level 2 nodes only 00542 if (specifiedPrefix == 0 && 00543 XMLString::equals(attr->getNodeName(), XMLUni::fgXMLNSString)) { 00544 // default namespace 00545 return value; 00546 } else if (attrPrefix != 0 && 00547 XMLString::equals(attrPrefix, XMLUni::fgXMLNSString) && 00548 XMLString::equals(attr->getLocalName(), specifiedPrefix)) { 00549 // non default namespace 00550 return value; 00551 } 00552 } 00553 } 00554 } 00555 } 00556 DOMNode *ancestor = getElementAncestor(thisNode); 00557 if (ancestor != 0) { 00558 return ancestor->lookupNamespaceURI(specifiedPrefix); 00559 } 00560 return 0; 00561 } 00562 case DOMNode::DOCUMENT_NODE : { 00563 return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix); 00564 } 00565 case DOMNode::ENTITY_NODE : 00566 case DOMNode::NOTATION_NODE: 00567 case DOMNode::DOCUMENT_FRAGMENT_NODE: 00568 case DOMNode::DOCUMENT_TYPE_NODE: 00569 // type is unknown 00570 return 0; 00571 case DOMNode::ATTRIBUTE_NODE:{ 00572 if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { 00573 return fOwnerNode->lookupNamespaceURI(specifiedPrefix); 00574 } 00575 return 0; 00576 } 00577 default:{ 00578 DOMNode *ancestor = getElementAncestor(castToNode(this)); 00579 if (ancestor != 0) { 00580 return ancestor->lookupNamespaceURI(specifiedPrefix); 00581 } 00582 return 0; 00583 } 00584 } 00585 } 00586 00587 00588 const XMLCh* DOMNodeImpl::getBaseURI() const{ 00589 DOMNode *thisNode = castToNode(this); 00590 DOMNode* parent = thisNode->getParentNode(); 00591 if (parent) 00592 return parent->getBaseURI(); 00593 else 00594 return 0; 00595 } 00596 00597 const DOMNode* DOMNodeImpl::getTreeParentNode(const DOMNode* node) const { 00598 const DOMNode* parent=node->getParentNode(); 00599 if(parent) 00600 return parent; 00601 short nodeType=node->getNodeType(); 00602 switch(nodeType) 00603 { 00604 case DOMNode::ATTRIBUTE_NODE: return ((const DOMAttr*)node)->getOwnerElement(); 00605 case DOMNode::NOTATION_NODE: 00606 case DOMNode::ENTITY_NODE: return node->getOwnerDocument()->getDoctype(); 00607 } 00608 return 0; 00609 } 00610 00611 short DOMNodeImpl::compareDocumentPosition(const DOMNode* other) const { 00612 DOMNode* thisNode = castToNode(this); 00613 00614 // If the two nodes being compared are the same node, then no flags are set on the return. 00615 if (thisNode == other) 00616 return 0; 00617 00618 //if this is a custom node, we don't really know what to do, just return 00619 //user should provide its own compareDocumentPosition logic, and shouldn't reach here 00620 if(thisNode->getNodeType() > 12) { 00621 return 0; 00622 } 00623 00624 //if it is a custom node we must ask it for the order 00625 if(other->getNodeType() > 12) { 00626 return reverseTreeOrderBitPattern(other->compareDocumentPosition(thisNode)); 00627 } 00628 00629 // Otherwise, the order of two nodes is determined by looking for common containers -- 00630 // containers which contain both. A node directly contains any child nodes. 00631 // A node also directly contains any other nodes attached to it such as attributes 00632 // contained in an element or entities and notations contained in a document type. 00633 // Nodes contained in contained nodes are also contained, but less-directly as 00634 // the number of intervening containers increases. 00635 00636 // If one of the nodes being compared contains the other node, then the container precedes 00637 // the contained node, and reversely the contained node follows the container. For example, 00638 // when comparing an element against its own attribute or child, the element node precedes 00639 // its attribute node and its child node, which both follow it. 00640 00641 const DOMNode* tmpNode; 00642 const DOMNode* myRoot = castToNode(this); 00643 int myDepth=0; 00644 while((tmpNode=getTreeParentNode(myRoot))!=0) 00645 { 00646 myRoot=tmpNode; 00647 if(myRoot==other) 00648 return DOMNode::DOCUMENT_POSITION_CONTAINS | DOMNode::DOCUMENT_POSITION_PRECEDING; 00649 myDepth++; 00650 } 00651 00652 const DOMNode* hisRoot = other; 00653 int hisDepth=0; 00654 while((tmpNode=getTreeParentNode(hisRoot))!=0) 00655 { 00656 hisRoot=tmpNode; 00657 if(hisRoot==thisNode) 00658 return DOMNode::DOCUMENT_POSITION_CONTAINED_BY | DOMNode::DOCUMENT_POSITION_FOLLOWING; 00659 hisDepth++; 00660 } 00661 00662 // If there is no common container node, then the order is based upon order between the 00663 // root container of each node that is in no container. In this case, the result is 00664 // disconnected and implementation-specific. This result is stable as long as these 00665 // outer-most containing nodes remain in memory and are not inserted into some other 00666 // containing node. This would be the case when the nodes belong to different documents 00667 // or fragments, and cloning the document or inserting a fragment might change the order. 00668 00669 if(myRoot!=hisRoot) 00670 return DOMNode::DOCUMENT_POSITION_DISCONNECTED | DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | 00671 (myRoot<hisRoot?DOMNode::DOCUMENT_POSITION_PRECEDING:DOMNode::DOCUMENT_POSITION_FOLLOWING); 00672 00673 // If neither of the previous cases apply, then there exists a most-direct container common 00674 // to both nodes being compared. In this case, the order is determined based upon the two 00675 // determining nodes directly contained in this most-direct common container that either 00676 // are or contain the corresponding nodes being compared. 00677 00678 // if the two depths are different, go to the same one 00679 myRoot = castToNode(this); 00680 hisRoot = other; 00681 if (myDepth > hisDepth) { 00682 for (int i= 0 ; i < myDepth - hisDepth; i++) 00683 myRoot = getTreeParentNode(myRoot); 00684 } 00685 else { 00686 for (int i = 0; i < hisDepth - myDepth; i++) 00687 hisRoot = getTreeParentNode(hisRoot); 00688 } 00689 00690 // We now have nodes at the same depth in the tree. Find a common ancestor. 00691 const DOMNode *myNodeP=myRoot; 00692 const DOMNode *hisNodeP=hisRoot; 00693 while(myRoot!=hisRoot) 00694 { 00695 myNodeP = myRoot; 00696 hisNodeP = hisRoot; 00697 myRoot = getTreeParentNode(myRoot); 00698 hisRoot = getTreeParentNode(hisRoot); 00699 } 00700 00701 short myNodeType=myNodeP->getNodeType(); 00702 short hisNodeType=hisNodeP->getNodeType(); 00703 bool bMyNodeIsChild=(myNodeType!=DOMNode::ATTRIBUTE_NODE && myNodeType!=DOMNode::ENTITY_NODE && myNodeType!=DOMNode::NOTATION_NODE); 00704 bool bHisNodeIsChild=(hisNodeType!=DOMNode::ATTRIBUTE_NODE && hisNodeType!=DOMNode::ENTITY_NODE && hisNodeType!=DOMNode::NOTATION_NODE); 00705 00706 // If these two determining nodes are both child nodes, then the natural DOM order of these 00707 // determining nodes within the containing node is returned as the order of the corresponding nodes. 00708 // This would be the case, for example, when comparing two child elements of the same element. 00709 if(bMyNodeIsChild && bHisNodeIsChild) 00710 { 00711 while(myNodeP != 0) 00712 { 00713 myNodeP = myNodeP->getNextSibling(); 00714 if(myNodeP == hisNodeP) 00715 return DOMNode::DOCUMENT_POSITION_FOLLOWING; 00716 } 00717 return DOMNode::DOCUMENT_POSITION_PRECEDING; 00718 } 00719 00720 // If one of the two determining nodes is a child node and the other is not, then the corresponding 00721 // node of the child node follows the corresponding node of the non-child node. This would be the case, 00722 // for example, when comparing an attribute of an element with a child element of the same element. 00723 else if(!bMyNodeIsChild && bHisNodeIsChild) 00724 return DOMNode::DOCUMENT_POSITION_FOLLOWING; 00725 else if(bMyNodeIsChild && !bHisNodeIsChild) 00726 return DOMNode::DOCUMENT_POSITION_PRECEDING; 00727 00728 else 00729 { 00730 // If neither of the two determining node is a child node and one determining node has a greater value 00731 // of nodeType than the other, then the corresponding node precedes the other. This would be the case, 00732 // for example, when comparing an entity of a document type against a notation of the same document type. 00733 if(myNodeType!=hisNodeType) 00734 return (myNodeType<hisNodeType)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING; 00735 00736 // If neither of the two determining node is a child node and nodeType is the same for both determining 00737 // nodes, then an implementation-dependent order between the determining nodes is returned. This order 00738 // is stable as long as no nodes of the same nodeType are inserted into or removed from the direct container. 00739 // This would be the case, for example, when comparing two attributes of the same element, and inserting 00740 // or removing additional attributes might change the order between existing attributes. 00741 return DOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | ((myNodeP<hisNodeP)?DOMNode::DOCUMENT_POSITION_FOLLOWING:DOMNode::DOCUMENT_POSITION_PRECEDING); 00742 } 00743 // REVISIT: shouldn't get here. Should probably throw an 00744 // exception 00745 return 0; 00746 } 00747 00748 short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const { 00749 00750 if(pattern & DOMNode::DOCUMENT_POSITION_PRECEDING) { 00751 pattern &= !DOMNode::DOCUMENT_POSITION_PRECEDING; 00752 pattern |= DOMNode::DOCUMENT_POSITION_FOLLOWING; 00753 } 00754 else if(pattern & DOMNode::DOCUMENT_POSITION_FOLLOWING) { 00755 pattern &= !DOMNode::DOCUMENT_POSITION_FOLLOWING; 00756 pattern |= DOMNode::DOCUMENT_POSITION_PRECEDING; 00757 } 00758 00759 if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINED_BY) { 00760 pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINED_BY; 00761 pattern |= DOMNode::DOCUMENT_POSITION_CONTAINS; 00762 } 00763 else if(pattern & DOMNode::DOCUMENT_POSITION_CONTAINS) { 00764 pattern &= !DOMNode::DOCUMENT_POSITION_CONTAINS; 00765 pattern |= DOMNode::DOCUMENT_POSITION_CONTAINED_BY; 00766 } 00767 00768 return pattern; 00769 } 00770 00771 /*** 00772 * 00773 * Excerpt from http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/core.html#Node3-textContent 00774 * 00775 * textContent of type DOMString, introduced in DOM Level 3 00776 * 00777 * This attribute returns the text content of this node and its descendants. When it is defined 00778 * to be null, setting it has no effect. 00779 * 00780 * When set, any possible children this node may have are removed and replaced by a single Text node 00781 * containing the string this attribute is set to. 00782 * 00783 * On getting, no serialization is performed, the returned string does not contain any markup. 00784 * No whitespace normalization is performed, the returned string does not contain the element content 00785 * whitespaces Fundamental Interfaces. 00786 * 00787 * Similarly, on setting, no parsing is performed either, the input string is taken as pure textual content. 00788 * 00789 * The string returned is made of the text content of this node depending on its type, 00790 * as defined below: 00791 * 00792 * Node type Content 00793 * ==================== ======================================================================== 00794 * ELEMENT_NODE concatenation of the textContent attribute value of every child node, 00795 * ENTITY_NODE excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes. 00796 * ENTITY_REFERENCE_NODE This is the empty string if the node has no children. 00797 * DOCUMENT_FRAGMENT_NODE 00798 * -------------------------------------------------------------------------------------------------- 00799 * ATTRIBUTE_NODE 00800 * TEXT_NODE 00801 * CDATA_SECTION_NODE 00802 * COMMENT_NODE, 00803 * PROCESSING_INSTRUCTION_NODE nodeValue 00804 * -------------------------------------------------------------------------------------------------- 00805 * DOCUMENT_NODE, 00806 * DOCUMENT_TYPE_NODE, 00807 * NOTATION_NODE null 00808 * 00809 ***/ 00810 00811 const XMLCh* DOMNodeImpl::getTextContent() const 00812 { 00813 XMLSize_t nBufferLength = 0; 00814 00815 getTextContent(NULL, nBufferLength); 00816 XMLCh* pzBuffer = (XMLCh*)((DOMDocumentImpl*)getOwnerDocument())->allocate((nBufferLength+1) * sizeof(XMLCh)); 00817 getTextContent(pzBuffer, nBufferLength); 00818 pzBuffer[nBufferLength] = 0; 00819 00820 return pzBuffer; 00821 00822 } 00823 00824 const XMLCh* DOMNodeImpl::getTextContent(XMLCh* pzBuffer, XMLSize_t& rnBufferLength) const 00825 { 00826 XMLSize_t nRemainingBuffer = rnBufferLength; 00827 rnBufferLength = 0; 00828 00829 if (pzBuffer) 00830 *pzBuffer = 0; 00831 00832 DOMNode *thisNode = castToNode(this); 00833 00834 switch (thisNode->getNodeType()) 00835 { 00836 case DOMNode::ELEMENT_NODE: 00837 case DOMNode::ENTITY_NODE: 00838 case DOMNode::ENTITY_REFERENCE_NODE: 00839 case DOMNode::DOCUMENT_FRAGMENT_NODE: 00840 { 00841 DOMNode* current = thisNode->getFirstChild(); 00842 00843 while (current != NULL) 00844 { 00845 if (current->getNodeType() != DOMNode::COMMENT_NODE && 00846 current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE) 00847 { 00848 00849 if (pzBuffer) 00850 { 00851 XMLSize_t nContentLength = nRemainingBuffer; 00852 castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength); 00853 rnBufferLength += nContentLength; 00854 nRemainingBuffer -= nContentLength; 00855 } 00856 else 00857 { 00858 XMLSize_t nContentLength = 0; 00859 castToNodeImpl(current)->getTextContent(NULL, nContentLength); 00860 rnBufferLength += nContentLength; 00861 } 00862 } 00863 00864 current = current->getNextSibling(); 00865 00866 } 00867 } 00868 00869 break; 00870 00871 case DOMNode::ATTRIBUTE_NODE: 00872 case DOMNode::TEXT_NODE: 00873 case DOMNode::CDATA_SECTION_NODE: 00874 case DOMNode::COMMENT_NODE: 00875 case DOMNode::PROCESSING_INSTRUCTION_NODE: 00876 { 00877 const XMLCh* pzValue = thisNode->getNodeValue(); 00878 XMLSize_t nStrLen = XMLString::stringLen(pzValue); 00879 00880 if (pzBuffer) 00881 { 00882 XMLSize_t nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer; 00883 XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength); 00884 rnBufferLength += nContentLength; 00885 nRemainingBuffer -= nContentLength; 00886 } 00887 else 00888 { 00889 rnBufferLength += nStrLen; 00890 } 00891 00892 } 00893 00894 break; 00895 00896 /*** 00897 DOCUMENT_NODE 00898 DOCUMENT_TYPE_NODE 00899 NOTATION_NODE 00900 ***/ 00901 default: 00902 00903 break; 00904 } 00905 00906 return pzBuffer; 00907 00908 } 00909 00910 void DOMNodeImpl::setTextContent(const XMLCh* textContent){ 00911 DOMNode *thisNode = castToNode(this); 00912 switch (thisNode->getNodeType()) 00913 { 00914 case DOMNode::ELEMENT_NODE: 00915 case DOMNode::ENTITY_NODE: 00916 case DOMNode::ENTITY_REFERENCE_NODE: 00917 case DOMNode::DOCUMENT_FRAGMENT_NODE: 00918 { 00919 if (isReadOnly()) 00920 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); 00921 00922 // Remove all childs 00923 DOMNode* current = thisNode->getFirstChild(); 00924 while (current != NULL) 00925 { 00926 thisNode->removeChild(current); 00927 current = thisNode->getFirstChild(); 00928 } 00929 if (textContent != NULL) 00930 { 00931 // Add textnode containing data 00932 current = ((DOMDocumentImpl*)thisNode->getOwnerDocument())->createTextNode(textContent); 00933 thisNode->appendChild(current); 00934 } 00935 } 00936 break; 00937 00938 case DOMNode::ATTRIBUTE_NODE: 00939 case DOMNode::TEXT_NODE: 00940 case DOMNode::CDATA_SECTION_NODE: 00941 case DOMNode::COMMENT_NODE: 00942 case DOMNode::PROCESSING_INSTRUCTION_NODE: 00943 if (isReadOnly()) 00944 throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNodeMemoryManager); 00945 00946 thisNode->setNodeValue(textContent); 00947 break; 00948 00949 case DOMNode::DOCUMENT_NODE: 00950 case DOMNode::DOCUMENT_TYPE_NODE: 00951 case DOMNode::NOTATION_NODE: 00952 break; 00953 00954 default: 00955 throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, GetDOMNodeMemoryManager); 00956 } 00957 } 00958 00959 00960 bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{ 00961 DOMNode *thisNode = castToNode(this); 00962 short type = thisNode->getNodeType(); 00963 switch (type) { 00964 case DOMNode::ELEMENT_NODE: { 00965 const XMLCh *prefix = thisNode->getPrefix(); 00966 00967 // REVISIT: is it possible that prefix is empty string? 00968 if (prefix == 0 || !*prefix) { 00969 return XMLString::equals(namespaceURI, thisNode->getNamespaceURI()); 00970 } 00971 00972 if (thisNode->hasAttributes()) { 00973 DOMElement *elem = (DOMElement *)thisNode; 00974 DOMNode *attr = elem->getAttributeNodeNS(XMLUni::fgXMLNSURIName, XMLUni::fgXMLNSString); 00975 if (attr != 0) { 00976 const XMLCh *value = attr->getNodeValue(); 00977 return XMLString::equals(namespaceURI, value); 00978 } 00979 } 00980 DOMNode *ancestor = getElementAncestor(thisNode); 00981 if (ancestor != 0) { 00982 return ancestor->isDefaultNamespace(namespaceURI); 00983 } 00984 00985 return false; 00986 } 00987 case DOMNode::DOCUMENT_NODE:{ 00988 return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI); 00989 } 00990 00991 case DOMNode::ENTITY_NODE : 00992 case DOMNode::NOTATION_NODE: 00993 case DOMNode::DOCUMENT_FRAGMENT_NODE: 00994 case DOMNode::DOCUMENT_TYPE_NODE: 00995 // type is unknown 00996 return false; 00997 case DOMNode::ATTRIBUTE_NODE:{ 00998 if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) { 00999 return fOwnerNode->isDefaultNamespace(namespaceURI); 01000 01001 } 01002 return false; 01003 } 01004 default:{ 01005 DOMNode *ancestor = getElementAncestor(thisNode); 01006 if (ancestor != 0) { 01007 return ancestor->isDefaultNamespace(namespaceURI); 01008 } 01009 return false; 01010 } 01011 01012 } 01013 } 01014 01015 void* DOMNodeImpl::getFeature(const XMLCh*, const XMLCh*) const { 01016 return 0; 01017 } 01018 01019 01020 // non-standard extension 01021 void DOMNodeImpl::release() 01022 { 01023 // shouldn't reach here 01024 throw DOMException(DOMException::INVALID_ACCESS_ERR,0, GetDOMNodeMemoryManager); 01025 } 01026 01027 XERCES_CPP_NAMESPACE_END 01028