DOMNodeImpl.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:38k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: DOMNodeImpl.cpp,v 1.24 2003/04/03 19:25:50 peiyongz Exp $
  58.  */
  59. // This class doesn't support having any children, and implements the behavior
  60. // of an empty NodeList as far getChildNodes is concerned.
  61. // The ParentNode subclass overrides this behavior.
  62. #include "DOMCasts.hpp"
  63. #include "DOMDocumentTypeImpl.hpp"
  64. #include "DOMElementImpl.hpp"
  65. #include "DOMAttrImpl.hpp"
  66. #include <xercesc/dom/DOMImplementation.hpp>
  67. #include <xercesc/dom/DOMException.hpp>
  68. #include <xercesc/util/XMLUniDefs.hpp>
  69. #include <xercesc/util/XMLRegisterCleanup.hpp>
  70. #include <xercesc/util/PlatformUtils.hpp>
  71. #include <stdio.h>
  72. #include <assert.h>
  73. XERCES_CPP_NAMESPACE_BEGIN
  74. const unsigned short DOMNodeImpl::READONLY     = 0x1<<0;
  75. const unsigned short DOMNodeImpl::SYNCDATA     = 0x1<<1;
  76. const unsigned short DOMNodeImpl::SYNCCHILDREN = 0x1<<2;
  77. const unsigned short DOMNodeImpl::OWNED        = 0x1<<3;
  78. const unsigned short DOMNodeImpl::FIRSTCHILD   = 0x1<<4;
  79. const unsigned short DOMNodeImpl::SPECIFIED    = 0x1<<5;
  80. const unsigned short DOMNodeImpl::IGNORABLEWS  = 0x1<<6;
  81. const unsigned short DOMNodeImpl::SETVALUE     = 0x1<<7;
  82. const unsigned short DOMNodeImpl::ID_ATTR      = 0x1<<8;
  83. const unsigned short DOMNodeImpl::USERDATA     = 0x1<<9;
  84. const unsigned short DOMNodeImpl::LEAFNODETYPE = 0x1<<10;
  85. const unsigned short DOMNodeImpl::CHILDNODE    = 0x1<<11;
  86. const unsigned short DOMNodeImpl::TOBERELEASED = 0x1<<12;
  87. // -----------------------------------------------------------------------
  88. //  Reset the singleton gEmptyNodeList
  89. // -----------------------------------------------------------------------
  90. static DOMNodeListImpl *gEmptyNodeList;  // make a singleton empty node list
  91. static void reinitEmptyNodeList()
  92. {
  93.     delete gEmptyNodeList;
  94.     gEmptyNodeList = 0;
  95. }
  96. // -----------------------------------------------------------------------
  97. //  DOMNodeImpl Functions
  98. // -----------------------------------------------------------------------
  99. DOMNodeImpl::DOMNodeImpl(DOMNode *ownerNode)
  100. {
  101.     this->flags = 0;
  102.     // as long as we do not have any owner, fOwnerNode is our ownerDocument
  103.     fOwnerNode  = ownerNode;
  104. };
  105. // This only makes a shallow copy, cloneChildren must also be called for a
  106. // deep clone
  107. DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other)
  108. {
  109.     this->flags = other.flags;
  110.     this->isReadOnly(false);
  111.     // Need to break the association w/ original parent
  112.     this->fOwnerNode = other.getOwnerDocument();
  113.     this->isOwned(false);
  114. };
  115. DOMNodeImpl::~DOMNodeImpl() {
  116. };
  117. DOMNode * DOMNodeImpl::appendChild(DOMNode *newChild)
  118. {
  119.     // Only node types that don't allow children will use this default function.
  120.     //   Others will go to DOMParentNode::appendChild.
  121.     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0);
  122.     return 0;
  123.     //  return insertBefore(newChild, 0);
  124. };
  125. DOMNamedNodeMap * DOMNodeImpl::getAttributes() const {
  126.     return 0;                   // overridden in ElementImpl
  127. };
  128. DOMNodeList *DOMNodeImpl::getChildNodes() const {
  129.     static XMLRegisterCleanup emptyNodeListCleanup;
  130.     if (gEmptyNodeList == 0)
  131.     {
  132.         DOMNodeList *t = new DOMNodeListImpl(0);
  133.         if (XMLPlatformUtils::compareAndSwap((void **)&gEmptyNodeList, t, 0) != 0)
  134.         {
  135.             delete t;
  136.         }
  137.         else
  138.         {
  139.             emptyNodeListCleanup.registerCleanup(reinitEmptyNodeList);
  140.         }
  141.     }
  142.     return (DOMNodeList *)gEmptyNodeList;
  143. };
  144. DOMNode * DOMNodeImpl::getFirstChild() const {
  145.     return 0;                   // overridden in ParentNode
  146. };
  147. DOMNode * DOMNodeImpl::getLastChild() const
  148. {
  149.     return 0;                   // overridden in ParentNode
  150. };
  151. DOMNode * DOMNodeImpl::getNextSibling() const {
  152.     return 0;                // overridden in ChildNode
  153. };
  154. const XMLCh * DOMNodeImpl::getNodeValue() const {
  155.     return 0;                    // Overridden by anything that has a value
  156. }
  157. //
  158. //  Unlike the external getOwnerDocument, this one returns the owner document
  159. //     for document nodes as well as all of the other node types.
  160. //
  161. DOMDocument *DOMNodeImpl::getOwnerDocument() const
  162. {
  163.     if (!this->isLeafNode())
  164.     {
  165.         DOMElementImpl *ep = (DOMElementImpl *)castToNode(this);
  166.         return ep->fParent.fOwnerDocument;
  167.     }
  168.     //  Leaf node types - those that cannot have children, like Text.
  169.     if (isOwned()) {
  170.         DOMDocument* ownerDoc = fOwnerNode->getOwnerDocument();
  171.         if (!ownerDoc) {
  172.             assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
  173.             return  (DOMDocument *)fOwnerNode;
  174.         }
  175.         else {
  176.             return ownerDoc;
  177.         }
  178.     } else {
  179.         assert (fOwnerNode->getNodeType() == DOMNode::DOCUMENT_NODE);
  180.         return  (DOMDocument *)fOwnerNode;
  181.     }
  182. };
  183. void DOMNodeImpl::setOwnerDocument(DOMDocument *doc) {
  184.     // if we have an owner we rely on it to have it right
  185.     // otherwise fOwnerNode is our ownerDocument
  186.     if (!isOwned()) {
  187.         // revisit.  Problem with storage for doctype nodes that were created
  188.         //                on the system heap in advance of having a document.
  189.         fOwnerNode = doc;
  190.     }
  191. }
  192. DOMNode * DOMNodeImpl::getParentNode() const
  193. {
  194.     return 0;                // overridden in ChildNode
  195. };
  196. DOMNode*  DOMNodeImpl::getPreviousSibling() const
  197. {
  198.     return 0;                // overridden in ChildNode
  199. };
  200. bool DOMNodeImpl::hasChildNodes() const
  201. {
  202.     return false;
  203. };
  204. DOMNode *DOMNodeImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) {
  205.     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0);
  206.     return 0;
  207. };
  208. DOMNode *DOMNodeImpl::removeChild(DOMNode *oldChild)
  209. {
  210.     throw DOMException(DOMException::NOT_FOUND_ERR, 0);
  211.     return 0;
  212. };
  213. DOMNode *DOMNodeImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild)
  214. {
  215.     throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0);
  216.     return 0;
  217. };
  218. void DOMNodeImpl::setNodeValue(const XMLCh *val)
  219. {
  220.     // Default behavior is to do nothing, overridden in some subclasses
  221. };
  222. void DOMNodeImpl::setReadOnly(bool readOnl, bool deep)
  223. {
  224.     this->isReadOnly(readOnl);
  225.     if (deep) {
  226.         for (DOMNode *mykid = castToNode(this)->getFirstChild();
  227.             mykid != 0;
  228.             mykid = mykid->getNextSibling()) {
  229.             short kidNodeType = mykid->getNodeType();
  230.             switch (kidNodeType) {
  231.             case DOMNode::ENTITY_REFERENCE_NODE:
  232.                 break;
  233.             case DOMNode::ELEMENT_NODE:
  234.                 ((DOMElementImpl*) mykid)->setReadOnly(readOnl, true);
  235.                 break;
  236.             case DOMNode::DOCUMENT_TYPE_NODE:
  237.                ((DOMDocumentTypeImpl*) mykid)->setReadOnly(readOnl, true);
  238.                break;
  239.             default:
  240.                 castToNodeImpl(mykid)->setReadOnly(readOnl, true);
  241.                 break;
  242.             }
  243.         }
  244.     }
  245. }
  246. //Introduced in DOM Level 2
  247. void DOMNodeImpl::normalize()
  248. {
  249.     // does nothing by default, overridden by subclasses
  250. };
  251. bool DOMNodeImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
  252. {
  253.     return DOMImplementation::getImplementation()->hasFeature(feature, version);
  254. }
  255. const XMLCh *DOMNodeImpl::getNamespaceURI() const
  256. {
  257.     return 0;
  258. }
  259. const XMLCh *DOMNodeImpl::getPrefix() const
  260. {
  261.     return 0;
  262. }
  263. const XMLCh *DOMNodeImpl::getLocalName() const
  264. {
  265.     return 0;
  266. }
  267. void DOMNodeImpl::setPrefix(const XMLCh *fPrefix)
  268. {
  269.     throw DOMException(DOMException::NAMESPACE_ERR, 0);
  270. }
  271. bool DOMNodeImpl::hasAttributes() const {
  272.     return 0;                   // overridden in ElementImpl
  273. };
  274. static const XMLCh s_xml[] = {chLatin_x, chLatin_m, chLatin_l, chNull};
  275. static const XMLCh s_xmlURI[] =    // "http://www.w3.org/XML/1998/namespace"
  276.     { chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,
  277.       chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod,
  278.       chLatin_o, chLatin_r, chLatin_g, chForwardSlash, chLatin_X, chLatin_M, chLatin_L, chForwardSlash,
  279.       chDigit_1, chDigit_9, chDigit_9, chDigit_8, chForwardSlash,
  280.       chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e,
  281.       chNull};
  282. static const XMLCh s_xmlns[] = {chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull};
  283. static const XMLCh s_xmlnsURI[] = // "http://www.w3.org/2000/xmlns/"
  284.     {  chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,
  285.        chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod,
  286.        chLatin_o, chLatin_r, chLatin_g, chForwardSlash,
  287.        chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash,
  288.        chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chForwardSlash, chNull};
  289. const XMLCh *DOMNodeImpl::getXmlString()      {return s_xml;};
  290. const XMLCh *DOMNodeImpl::getXmlURIString()   {return s_xmlURI;};
  291. const XMLCh *DOMNodeImpl::getXmlnsString()    {return s_xmlns;};
  292. const XMLCh *DOMNodeImpl::getXmlnsURIString() {return s_xmlnsURI;};
  293. //Return a URI mapped from the given prefix and namespaceURI as below
  294. //    prefix   namespaceURI    output
  295. //---------------------------------------------------
  296. //    "xml"     xmlURI          xmlURI
  297. //    "xml"     otherwise       NAMESPACE_ERR
  298. //    "xmlns"   xmlnsURI        xmlnsURI (nType = ATTRIBUTE_NODE only)
  299. //    "xmlns"   otherwise       NAMESPACE_ERR (nType = ATTRIBUTE_NODE only)
  300. //    != null   null or ""      NAMESPACE_ERR
  301. //    else      any             namesapceURI
  302. const XMLCh* DOMNodeImpl::mapPrefix(const XMLCh *prefix,
  303.                                      const XMLCh *namespaceURI, short nType)
  304. {
  305.     static const XMLCh s_xml[] = {chLatin_x, chLatin_m, chLatin_l, chNull};
  306.     static const XMLCh s_xmlURI[] =    // "http://www.w3.org/XML/1998/namespace"
  307.     { chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,
  308.       chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod,
  309.       chLatin_o, chLatin_r, chLatin_g, chForwardSlash, chLatin_X, chLatin_M, chLatin_L, chForwardSlash,
  310.       chDigit_1, chDigit_9, chDigit_9, chDigit_8, chForwardSlash,
  311.       chLatin_n, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e,
  312.       chNull};
  313.     static const XMLCh s_xmlns[] = {chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull};
  314.     static const XMLCh s_xmlnsURI[] = // "http://www.w3.org/2000/xmlns/"
  315.     {  chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,
  316.        chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod,
  317.        chLatin_o, chLatin_r, chLatin_g, chForwardSlash,
  318.        chDigit_2, chDigit_0, chDigit_0, chDigit_0, chForwardSlash,
  319.        chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chForwardSlash, chNull};
  320.     if (prefix == 0)
  321.         return namespaceURI;
  322.     if (XMLString::equals(prefix, s_xml))  {
  323.         if (XMLString::equals(namespaceURI, s_xmlURI))
  324.             return s_xmlURI;
  325.         throw DOMException(DOMException::NAMESPACE_ERR, 0);
  326.     } else if (nType == DOMNode::ATTRIBUTE_NODE && XMLString::equals(prefix, s_xmlns)) {
  327.         if (XMLString::equals(namespaceURI, s_xmlnsURI))
  328.             return s_xmlnsURI;
  329.         throw DOMException(DOMException::NAMESPACE_ERR, 0);
  330.     } else if (namespaceURI == 0 || *namespaceURI == 0) {
  331.         throw DOMException(DOMException::NAMESPACE_ERR, 0);
  332.     } else
  333.         return namespaceURI;
  334.     return namespaceURI;
  335. }
  336. //Introduced in DOM Level 3
  337. void* DOMNodeImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
  338. {
  339.    if (!data && !hasUserData())
  340.        return 0;
  341.     hasUserData(true);
  342.     return ((DOMDocumentImpl*)getOwnerDocument())->setUserData(this, key, data, handler);
  343. }
  344. void* DOMNodeImpl::getUserData(const XMLCh* key) const
  345. {
  346.    if (hasUserData())
  347.        return ((DOMDocumentImpl*)getOwnerDocument())->getUserData(this, key);
  348.     return 0;
  349. }
  350. void DOMNodeImpl::callUserDataHandlers(DOMUserDataHandler::DOMOperationType operation,
  351.                                        const DOMNode* src,
  352.                                        const DOMNode* dst) const
  353. {
  354.     if (((DOMDocumentImpl*)getOwnerDocument()))
  355.         ((DOMDocumentImpl*)getOwnerDocument())->callUserDataHandlers(this, operation, src, dst);
  356. }
  357. bool DOMNodeImpl::isSameNode(const DOMNode* other) const
  358. {
  359.     return (castToNode(this) == other);
  360. }
  361. bool DOMNodeImpl::isEqualNode(const DOMNode* arg) const
  362. {
  363.     if (!arg)
  364.         return false;
  365.     if (isSameNode(arg)) {
  366.         return true;
  367.     }
  368.     DOMNode* thisNode = castToNode(this);
  369.     if (arg->getNodeType() != thisNode->getNodeType()) {
  370.         return false;
  371.     }
  372.     // the compareString will check null string as well
  373.     if (!XMLString::equals(thisNode->getNodeName(), arg->getNodeName())) {
  374.         return false;
  375.     }
  376.     if (!XMLString::equals(thisNode->getLocalName(),arg->getLocalName())) {
  377.         return false;
  378.     }
  379.     if (!XMLString::equals(thisNode->getNamespaceURI(), arg->getNamespaceURI())) {
  380.         return false;
  381.     }
  382.     if (!XMLString::equals(thisNode->getPrefix(), arg->getPrefix())) {
  383.         return false;
  384.     }
  385.     if (!XMLString::equals(thisNode->getNodeValue(), arg->getNodeValue())) {
  386.         return false;
  387.     }
  388.     if (!XMLString::equals(thisNode->getBaseURI(), arg->getBaseURI())) {
  389.         return false;
  390.     }
  391.     return true;
  392. }
  393. const XMLCh* DOMNodeImpl::lookupNamespacePrefix(const XMLCh* namespaceURI,
  394.                                                 bool useDefault) const {
  395.     // REVISIT: When Namespaces 1.1 comes out this may not be true
  396.     // Prefix can't be bound to null namespace
  397.     if (namespaceURI == 0) {
  398.         return 0;
  399.     }
  400.     DOMNode *thisNode = castToNode(this);
  401.     short type = thisNode->getNodeType();
  402.     switch (type) {
  403.     case DOMNode::ELEMENT_NODE: {
  404.         return lookupNamespacePrefix(namespaceURI, useDefault, (DOMElement*)thisNode);
  405.     }
  406.     case DOMNode::DOCUMENT_NODE:{
  407.         return ((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespacePrefix(namespaceURI, useDefault);
  408.     }
  409.     case DOMNode::ENTITY_NODE :
  410.     case DOMNode::NOTATION_NODE:
  411.     case DOMNode::DOCUMENT_FRAGMENT_NODE:
  412.     case DOMNode::DOCUMENT_TYPE_NODE:
  413.         // type is unknown
  414.         return 0;
  415.     case DOMNode::ATTRIBUTE_NODE:{
  416.         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
  417.             return fOwnerNode->lookupNamespacePrefix(namespaceURI, useDefault);
  418.         }
  419.         return 0;
  420.     }
  421.     default:{
  422.         DOMNode *ancestor = getElementAncestor(thisNode);
  423.         if (ancestor != 0) {
  424.             return ancestor->lookupNamespacePrefix(namespaceURI, useDefault);
  425.         }
  426.         return 0;
  427.     }
  428.     }
  429. }
  430. DOMNode* DOMNodeImpl::getElementAncestor (const DOMNode* currentNode) const {
  431.     DOMNode* parent = currentNode->getParentNode();
  432.     if (parent != 0) {
  433.         short type = parent->getNodeType();
  434.         if (type == DOMNode::ELEMENT_NODE) {
  435.             return parent;
  436.         }
  437.         return getElementAncestor(parent);
  438.     }
  439.     return 0;
  440. }
  441. const XMLCh* DOMNodeImpl::lookupNamespacePrefix(const XMLCh* const namespaceURI, bool useDefault, DOMElement *el) const {
  442.     DOMNode *thisNode = castToNode(this);
  443.     const XMLCh* ns = thisNode->getNamespaceURI();
  444.     // REVISIT: if no prefix is available is it null or empty string, or
  445.     //          could be both?
  446.     const XMLCh* prefix = thisNode->getPrefix();
  447.     if (ns != 0 && XMLString::equals(ns,namespaceURI)) {
  448.         if (useDefault || prefix != 0) {
  449.             const XMLCh* foundNamespace =  el->lookupNamespaceURI(prefix);
  450.             if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
  451.                 return prefix;
  452.             }
  453.         }
  454.     }
  455.     if (thisNode->hasAttributes()) {
  456.         DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
  457.         if(nodeMap != 0) {
  458.             int length = nodeMap->getLength();
  459.             for (int i = 0;i < length;i++) {
  460.                 DOMNode *attr = nodeMap->item(i);
  461.                 const XMLCh* attrPrefix = attr->getPrefix();
  462.                 const XMLCh* value = attr->getNodeValue();
  463.                 ns = attr->getNamespaceURI();
  464.                 if (ns != 0 && XMLString::equals(ns, s_xmlnsURI)) {
  465.                     // DOM Level 2 nodes
  466.                     if ((useDefault && XMLString::equals(attr->getNodeName(), s_xmlns)) ||
  467.                         (attrPrefix != 0 && XMLString::equals(attrPrefix, s_xmlns)) &&
  468.                         XMLString::equals(value, namespaceURI)) {
  469.                         const XMLCh* localname= attr->getLocalName();
  470.                         const XMLCh* foundNamespace = el->lookupNamespaceURI(localname);
  471.                         if (foundNamespace != 0 && XMLString::equals(foundNamespace, namespaceURI)) {
  472.                             return localname;
  473.                         }
  474.                     }
  475.                 }
  476.             }
  477.         }
  478.     }
  479.     DOMNode *ancestor = getElementAncestor(thisNode);
  480.     if (ancestor != 0) {
  481.         return castToNodeImpl(ancestor)->lookupNamespacePrefix(namespaceURI, useDefault, el);
  482.     }
  483.     return 0;
  484. }
  485. const XMLCh* DOMNodeImpl::lookupNamespaceURI(const XMLCh* specifiedPrefix) const  {
  486.     DOMNode *thisNode = castToNode(this);
  487.     short type = thisNode->getNodeType();
  488.     switch (type) {
  489.     case DOMNode::ELEMENT_NODE : {
  490.         const XMLCh* ns = thisNode->getNamespaceURI();
  491.         const XMLCh* prefix = thisNode->getPrefix();
  492.         if (ns != 0) {
  493.             // REVISIT: is it possible that prefix is empty string?
  494.             if (specifiedPrefix == 0 && prefix == specifiedPrefix) {
  495.                 // looking for default namespace
  496.                 return ns;
  497.             } else if (prefix != 0 && XMLString::equals(prefix, specifiedPrefix)) {
  498.                 // non default namespace
  499.                 return ns;
  500.             }
  501.         }
  502.         if (thisNode->hasAttributes()) {
  503.             DOMNamedNodeMap *nodeMap = thisNode->getAttributes();
  504.             if(nodeMap != 0) {
  505.                 int length = nodeMap->getLength();
  506.                 for (int i = 0;i < length;i++) {
  507.                     DOMNode *attr = nodeMap->item(i);
  508.                     const XMLCh *attrPrefix = attr->getPrefix();
  509.                     const XMLCh *value = attr->getNodeValue();
  510.                     ns = attr->getNamespaceURI();
  511.                     if (ns != 0 && XMLString::equals(ns, s_xmlnsURI)) {
  512.                         // at this point we are dealing with DOM Level 2 nodes only
  513.                         if (specifiedPrefix == 0 &&
  514.                             XMLString::equals(attr->getNodeName(), s_xmlns)) {
  515.                             // default namespace
  516.                             return value;
  517.                         } else if (attrPrefix != 0 &&
  518.                                    XMLString::equals(attrPrefix, s_xmlns) &&
  519.                                    XMLString::equals(attr->getLocalName(), specifiedPrefix)) {
  520.                             // non default namespace
  521.                             return value;
  522.                         }
  523.                     }
  524.                 }
  525.             }
  526.         }
  527.         DOMNode *ancestor = getElementAncestor(thisNode);
  528.         if (ancestor != 0) {
  529.             return ancestor->lookupNamespaceURI(specifiedPrefix);
  530.         }
  531.         return 0;
  532.     }
  533.     case DOMNode::DOCUMENT_NODE : {
  534.         return((DOMDocument*)thisNode)->getDocumentElement()->lookupNamespaceURI(specifiedPrefix);
  535.     }
  536.     case DOMNode::ENTITY_NODE :
  537.     case DOMNode::NOTATION_NODE:
  538.     case DOMNode::DOCUMENT_FRAGMENT_NODE:
  539.     case DOMNode::DOCUMENT_TYPE_NODE:
  540.         // type is unknown
  541.         return 0;
  542.     case DOMNode::ATTRIBUTE_NODE:{
  543.         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
  544.             return fOwnerNode->lookupNamespaceURI(specifiedPrefix);
  545.         }
  546.         return 0;
  547.     }
  548.     default:{
  549.         DOMNode *ancestor = getElementAncestor(castToNode(this));
  550.         if (ancestor != 0) {
  551.             return ancestor->lookupNamespaceURI(specifiedPrefix);
  552.         }
  553.         return 0;
  554.     }
  555.     }
  556. }
  557. const XMLCh*     DOMNodeImpl::getBaseURI() const{
  558.     DOMNode *thisNode = castToNode(this);
  559.     DOMNode* parent = thisNode->getParentNode();
  560.     if (parent)
  561.         return parent->getBaseURI();
  562.     else
  563.         return 0;
  564. }
  565. short            DOMNodeImpl::compareTreePosition(const DOMNode* other) const {
  566.     // Questions of clarification for this method - to be answered by the
  567.     // DOM WG.   Current assumptions listed - LM
  568.     //
  569.     // 1. How do ENTITY nodes compare?
  570.     //    Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
  571.     //    aren't really 'in the tree'
  572.     //
  573.     // 2. How do NOTATION nodes compare?
  574.     //    Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
  575.     //    aren't really 'in the tree'
  576.     //
  577.     // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
  578.     //    only relevant for nodes that are "part of the document tree"?
  579.     //     <outer>
  580.     //         <inner  myattr="true"/>
  581.     //     </outer>
  582.     //    Is the element node "outer" considered an ancestor of "myattr"?
  583.     //    Current assumption: No.
  584.     //
  585.     // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
  586.     //    with children of other attribute nodes with the same element)
  587.     //    Current assumption: Children of ATTRIBUTE nodes are treated as if
  588.     //    they are the attribute node itself, unless the 2 nodes
  589.     //    are both children of the same attribute.
  590.     //
  591.     // 5. How does an ENTITY_REFERENCE node compare with it's children?
  592.     //    Given the DOM, it should precede its children as an ancestor.
  593.     //    Given "document order",  does it represent the same position?
  594.     //    Current assumption: An ENTITY_REFERENCE node is an ancestor of its
  595.     //    children.
  596.     //
  597.     // 6. How do children of a DocumentFragment compare?
  598.     //    Current assumption: If both nodes are part of the same document
  599.     //    fragment, there are compared as if they were part of a document.
  600.     DOMNode* thisNode = castToNode(this);
  601.     // If the nodes are the same...
  602.     if (thisNode == other)
  603.         return (DOMNode::TREE_POSITION_SAME_NODE | DOMNode::TREE_POSITION_EQUIVALENT);
  604.     // If either node is of type ENTITY or NOTATION, compare as disconnected
  605.     short thisType = thisNode->getNodeType();
  606.     short otherType = other->getNodeType();
  607.     // If either node is of type ENTITY or NOTATION, compare as disconnected
  608.     if (thisType == DOMNode::ENTITY_NODE ||
  609.             thisType == DOMNode::NOTATION_NODE ||
  610.             otherType == DOMNode::ENTITY_NODE ||
  611.             otherType == DOMNode::NOTATION_NODE ) {
  612.         return DOMNode::TREE_POSITION_DISCONNECTED;
  613.     }
  614.     //if this is a custom node, we don't really know what to do, just return
  615.     //user should provide its own compareTreePosition logic, and shouldn't reach here
  616.     if(thisType > 12) {
  617.         return 0;
  618.     }
  619.     //if it is a custom node we must ask it for the order
  620.     if(otherType > 12) {
  621.         return reverseTreeOrderBitPattern(other->compareTreePosition(castToNode(this)));
  622.     }
  623.     // Find the ancestor of each node, and the distance each node is from
  624.     // its ancestor.
  625.     // During this traversal, look for ancestor/descendent relationships
  626.     // between the 2 nodes in question.
  627.     // We do this now, so that we get this info correct for attribute nodes
  628.     // and their children.
  629.     const DOMNode *node;
  630.     const DOMNode *thisAncestor = castToNode(this);
  631.     const DOMNode *otherAncestor = other;
  632.     int thisDepth=0;
  633.     int otherDepth=0;
  634.     for (node = castToNode(this); node != 0; node = node->getParentNode()) {
  635.         thisDepth +=1;
  636.         if (node == other)
  637.             // The other node is an ancestor of this one.
  638.             return (DOMNode::TREE_POSITION_ANCESTOR | DOMNode::TREE_POSITION_PRECEDING);
  639.         thisAncestor = node;
  640.     }
  641.     for (node=other; node != 0; node = node->getParentNode()) {
  642.         otherDepth +=1;
  643.         if (node == castToNode(this))
  644.             // The other node is a descendent of the reference node.
  645.             return (DOMNode::TREE_POSITION_DESCENDANT | DOMNode::TREE_POSITION_FOLLOWING);
  646.         otherAncestor = node;
  647.     }
  648.     const DOMNode *otherNode = other;
  649.     short thisAncestorType = thisAncestor->getNodeType();
  650.     short otherAncestorType = otherAncestor->getNodeType();
  651.     // if the ancestor is an attribute, get owning element.
  652.     // we are now interested in the owner to determine position.
  653.     if (thisAncestorType == DOMNode::ATTRIBUTE_NODE)  {
  654.         thisNode = ((DOMAttrImpl *)thisAncestor)->getOwnerElement();
  655.     }
  656.     if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) {
  657.         otherNode = ((DOMAttrImpl *)otherAncestor)->getOwnerElement();
  658.     }
  659.     // Before proceeding, we should check if both ancestor nodes turned
  660.     // out to be attributes for the same element
  661.     if (thisAncestorType == DOMNode::ATTRIBUTE_NODE &&
  662.             otherAncestorType == DOMNode::ATTRIBUTE_NODE &&
  663.             thisNode==otherNode)
  664.         return DOMNode::TREE_POSITION_EQUIVALENT;
  665.     // Now, find the ancestor of the owning element, if the original
  666.     // ancestor was an attribute
  667.     if (thisAncestorType == DOMNode::ATTRIBUTE_NODE) {
  668.         thisDepth=0;
  669.         for (node=thisNode; node != 0; node = node->getParentNode()) {
  670.             thisDepth +=1;
  671.             if (node == otherNode)
  672.                 // The other node is an ancestor of the owning element
  673.                 return DOMNode::TREE_POSITION_PRECEDING;
  674.             thisAncestor = node;
  675.         }
  676.         for (node=otherNode; node != 0; node = node->getParentNode()) {
  677.             if (node == thisNode)
  678.                 // The other node is an ancestor of the owning element
  679.                 return DOMNode::TREE_POSITION_FOLLOWING;
  680.         }
  681.     }
  682.     // Now, find the ancestor of the owning element, if the original
  683.     // ancestor was an attribute
  684.     if (otherAncestorType == DOMNode::ATTRIBUTE_NODE) {
  685.         otherDepth=0;
  686.         for (node=otherNode; node != 0; node = node->getParentNode()) {
  687.             otherDepth +=1;
  688.             if (node == thisNode)
  689.                 // The other node is a descendent of the reference
  690.                 // node's element
  691.                 return DOMNode::TREE_POSITION_FOLLOWING;
  692.             otherAncestor = node;
  693.         }
  694.         for (node=thisNode; node != 0; node = node->getParentNode()) {
  695.             if (node == otherNode)
  696.                 // The other node is an ancestor of the owning element
  697.                 return DOMNode::TREE_POSITION_PRECEDING;
  698.         }
  699.     }
  700.     // thisAncestor and otherAncestor must be the same at this point,
  701.     // otherwise, we are not in the same tree or document fragment
  702.     if (thisAncestor != otherAncestor)
  703.         return DOMNode::TREE_POSITION_DISCONNECTED;
  704.     // Determine which node is of the greatest depth.
  705.     if (thisDepth > otherDepth) {
  706.         for (int i= 0 ; i < thisDepth - otherDepth; i++)
  707.             thisNode = thisNode->getParentNode();
  708.     }
  709.     else {
  710.         for (int i = 0; i < otherDepth - thisDepth; i++)
  711.             otherNode = otherNode->getParentNode();
  712.     }
  713.     // We now have nodes at the same depth in the tree.  Find a common
  714.     // ancestor.
  715.     DOMNode *thisNodeP, *otherNodeP;
  716.     for (thisNodeP = thisNode->getParentNode(),
  717.                  otherNodeP = otherNode->getParentNode();
  718.              thisNodeP != otherNodeP;) {
  719.         thisNode = thisNodeP;
  720.         otherNode = otherNodeP;
  721.         thisNodeP = thisNodeP->getParentNode();
  722.         otherNodeP = otherNodeP->getParentNode();
  723.     }
  724.     // See whether thisNode or otherNode is the leftmost
  725.     for (DOMNode *current = thisNodeP->getFirstChild();
  726.              current != 0;
  727.              current = current->getNextSibling()) {
  728.         if (current == otherNode) {
  729.             return DOMNode::TREE_POSITION_PRECEDING;
  730.         }
  731.         else if (current == thisNode) {
  732.             return DOMNode::TREE_POSITION_FOLLOWING;
  733.         }
  734.     }
  735.     // REVISIT:  shouldn't get here.   Should probably throw an
  736.     // exception
  737.     return 0;
  738. }
  739. short DOMNodeImpl::reverseTreeOrderBitPattern(short pattern) const {
  740.     if(pattern & DOMNode::TREE_POSITION_PRECEDING) {
  741.         pattern &= !DOMNode::TREE_POSITION_PRECEDING;
  742.         pattern |= DOMNode::TREE_POSITION_FOLLOWING;
  743.     }
  744.     else if(pattern & DOMNode::TREE_POSITION_FOLLOWING) {
  745.         pattern &= !DOMNode::TREE_POSITION_FOLLOWING;
  746.         pattern |= DOMNode::TREE_POSITION_PRECEDING;
  747.     }
  748.     if(pattern & DOMNode::TREE_POSITION_ANCESTOR) {
  749.         pattern &= !DOMNode::TREE_POSITION_ANCESTOR;
  750.         pattern |= DOMNode::TREE_POSITION_DESCENDANT;
  751.     }
  752.     else if(pattern & DOMNode::TREE_POSITION_DESCENDANT) {
  753.         pattern &= !DOMNode::TREE_POSITION_DESCENDANT;
  754.         pattern |= DOMNode::TREE_POSITION_ANCESTOR;
  755.     }
  756.     return pattern;
  757. }
  758. /***
  759.  *
  760.  *   Excerpt from http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/core.html#Node3-textContent
  761.  *
  762.  *   textContent of type DOMString, introduced in DOM Level 3 
  763.  *   
  764.  *   This attribute returns the text content of this node and its descendants. When it is defined 
  765.  *   to be null, setting it has no effect. 
  766.  *   
  767.  *   When set, any possible children this node may have are removed and replaced by a single Text node 
  768.  *   containing the string this attribute is set to. 
  769.  *
  770.  *   On getting, no serialization is performed, the returned string does not contain any markup. 
  771.  *   No whitespace normalization is performed, the returned string does not contain the element content 
  772.  *   whitespaces Fundamental Interfaces. 
  773.  *
  774.  *   Similarly, on setting, no parsing is performed either, the input string is taken as pure textual content.
  775.  *
  776.  *   The string returned is made of the text content of this node depending on its type, 
  777.  *   as defined below: 
  778.  *
  779.  *       Node type                                           Content          
  780.  *   ====================       ========================================================================
  781.  *     ELEMENT_NODE               concatenation of the textContent attribute value of every child node, 
  782.  *     ENTITY_NODE       excluding COMMENT_NODE and PROCESSING_INSTRUCTION_NODE nodes. 
  783.  *     ENTITY_REFERENCE_NODE   This is the empty string if the node has no children. 
  784.  *     DOCUMENT_FRAGMENT_NODE 
  785.  *    --------------------------------------------------------------------------------------------------
  786.  *     ATTRIBUTE_NODE
  787.  *     TEXT_NODE
  788.  *     CDATA_SECTION_NODE
  789.  *     COMMENT_NODE, 
  790.  *     PROCESSING_INSTRUCTION_NODE   nodeValue 
  791.  *    --------------------------------------------------------------------------------------------------
  792.  *     DOCUMENT_NODE, 
  793.  *     DOCUMENT_TYPE_NODE, 
  794.  *     NOTATION_NODE                 null 
  795.  *
  796.  ***/
  797. const XMLCh*     DOMNodeImpl::getTextContent() const
  798. {
  799. unsigned int nBufferLength = 0;
  800. getTextContent(NULL, nBufferLength);
  801. XMLCh* pzBuffer = (XMLCh*)((DOMDocumentImpl*)getOwnerDocument())->allocate(nBufferLength+1);
  802. getTextContent(pzBuffer, nBufferLength);
  803. pzBuffer[nBufferLength] = 0;
  804. return pzBuffer;
  805. }
  806. const XMLCh*    DOMNodeImpl::getTextContent(XMLCh* pzBuffer, unsigned int& rnBufferLength) const
  807. {
  808. unsigned int nRemainingBuffer = rnBufferLength;
  809. rnBufferLength = 0;
  810. if (pzBuffer)   
  811. *pzBuffer = 0;
  812. DOMNode *thisNode = castToNode(this);
  813. switch (thisNode->getNodeType())
  814. {
  815. case DOMNode::ELEMENT_NODE:
  816.     case DOMNode::ENTITY_NODE:
  817.     case DOMNode::ENTITY_REFERENCE_NODE:
  818.     case DOMNode::DOCUMENT_FRAGMENT_NODE:
  819.     {
  820. DOMNode* current = thisNode->getFirstChild();
  821. while (current != NULL) 
  822. {
  823. if (current->getNodeType() != DOMNode::COMMENT_NODE &&
  824. current->getNodeType() != DOMNode::PROCESSING_INSTRUCTION_NODE)
  825. {
  826. if (pzBuffer)
  827. {
  828. unsigned int nContentLength = nRemainingBuffer;
  829. castToNodeImpl(current)->getTextContent(pzBuffer + rnBufferLength, nContentLength);
  830. rnBufferLength += nContentLength;
  831. nRemainingBuffer -= nContentLength;
  832. }
  833. else 
  834. {
  835. unsigned int nContentLength = 0;
  836. castToNodeImpl(current)->getTextContent(NULL, nContentLength);
  837. rnBufferLength += nContentLength;
  838. }
  839. }
  840. current = current->getNextSibling();
  841. }
  842.     }
  843.     break;
  844.     case DOMNode::ATTRIBUTE_NODE:
  845.     case DOMNode::TEXT_NODE:
  846.     case DOMNode::CDATA_SECTION_NODE:
  847.     case DOMNode::COMMENT_NODE:
  848.     case DOMNode::PROCESSING_INSTRUCTION_NODE:
  849.     {
  850. const XMLCh* pzValue = thisNode->getNodeValue();
  851. unsigned int nStrLen = XMLString::stringLen(pzValue);
  852. if (pzBuffer) 
  853. {
  854. unsigned int nContentLength = (nRemainingBuffer >= nStrLen) ? nStrLen : nRemainingBuffer;
  855. XMLString::copyNString(pzBuffer + rnBufferLength, pzValue, nContentLength);
  856. rnBufferLength += nContentLength;
  857. nRemainingBuffer -= nContentLength;
  858. }
  859. else 
  860. {
  861. rnBufferLength += nStrLen;
  862. }
  863.     }
  864.     break;
  865. /***
  866.          DOCUMENT_NODE
  867.  DOCUMENT_TYPE_NODE
  868.  NOTATION_NODE
  869. ***/
  870. default:
  871. break;
  872. }
  873. return pzBuffer;
  874. }
  875. void DOMNodeImpl::setTextContent(const XMLCh* textContent){
  876.     throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  877. }
  878. bool DOMNodeImpl::isDefaultNamespace(const XMLCh* namespaceURI) const{
  879. DOMNode *thisNode = castToNode(this);
  880.     short type = thisNode->getNodeType();
  881.     switch (type) {
  882.     case DOMNode::ELEMENT_NODE: {
  883.         const XMLCh *prefix = thisNode->getPrefix();
  884.         // REVISIT: is it possible that prefix is empty string?
  885.         if (prefix == 0 || !*prefix) {
  886.             return XMLString::equals(namespaceURI, thisNode->getNamespaceURI());
  887.         }
  888.         if (thisNode->hasAttributes()) {
  889.             DOMElement *elem = (DOMElement *)thisNode;
  890.             DOMNode *attr = elem->getAttributeNodeNS(s_xmlnsURI, s_xmlns);
  891.             if (attr != 0) {
  892.                 const XMLCh *value = attr->getNodeValue();
  893.                 return XMLString::equals(namespaceURI, value);
  894.             }
  895.         }
  896.         DOMNode *ancestor = getElementAncestor(thisNode);
  897.         if (ancestor != 0) {
  898.             return ancestor->isDefaultNamespace(namespaceURI);
  899.         }
  900.         return false;
  901.     }
  902.     case DOMNode::DOCUMENT_NODE:{
  903.         return ((DOMDocument*)thisNode)->getDocumentElement()->isDefaultNamespace(namespaceURI);
  904.     }
  905.     case DOMNode::ENTITY_NODE :
  906.     case DOMNode::NOTATION_NODE:
  907.     case DOMNode::DOCUMENT_FRAGMENT_NODE:
  908.     case DOMNode::DOCUMENT_TYPE_NODE:
  909.         // type is unknown
  910.         return false;
  911.     case DOMNode::ATTRIBUTE_NODE:{
  912.         if (fOwnerNode->getNodeType() == DOMNode::ELEMENT_NODE) {
  913.             return fOwnerNode->isDefaultNamespace(namespaceURI);
  914.         }
  915.         return false;
  916.     }
  917.     default:{
  918.         DOMNode *ancestor = getElementAncestor(thisNode);
  919.         if (ancestor != 0) {
  920.             return ancestor->isDefaultNamespace(namespaceURI);
  921.         }
  922.         return false;
  923.     }
  924.     }
  925. }
  926. DOMNode*         DOMNodeImpl::getInterface(const XMLCh* feature)      {
  927.     throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  928.     return 0;
  929. }
  930. // non-standard extension
  931. void DOMNodeImpl::release()
  932. {
  933.     // shouldn't reach here
  934.     throw DOMException(DOMException::INVALID_ACCESS_ERR,0);
  935. }
  936. XERCES_CPP_NAMESPACE_END