DocumentImpl.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:25k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 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) 1999, 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: DocumentImpl.cpp,v 1.38 2001/12/07 01:35:28 tng Exp $
  58.  */
  59. //
  60. // file DocumentImpl.cpp
  61. //
  62. #include "DocumentImpl.hpp"
  63. #include "DOM_DOMException.hpp"
  64. #include "DOM_Node.hpp"
  65. #include "DocumentTypeImpl.hpp"
  66. #include "ElementImpl.hpp"
  67. #include "ElementNSImpl.hpp"
  68. #include "AttrImpl.hpp"
  69. #include "AttrNSImpl.hpp"
  70. #include "CDATASectionImpl.hpp"
  71. #include "CommentImpl.hpp"
  72. #include "DocumentFragmentImpl.hpp"
  73. #include "EntityImpl.hpp"
  74. #include "EntityReferenceImpl.hpp"
  75. #include "NotationImpl.hpp"
  76. #include "ProcessingInstructionImpl.hpp"
  77. #include "TextImpl.hpp"
  78. #include "DOM_DOMImplementation.hpp"
  79. #include "DeepNodeListImpl.hpp"
  80. #include "NamedNodeMapImpl.hpp"
  81. #include "DStringPool.hpp"
  82. #include <internal/XMLReader.hpp>
  83. #include "TreeWalkerImpl.hpp"
  84. #include "NodeIteratorImpl.hpp"
  85. #include "NodeIDMap.hpp"
  86. #include "DOM_Document.hpp"
  87. #include <util/HashPtr.hpp>
  88. #include "RangeImpl.hpp"
  89. #include "DOM_Document.hpp"
  90. static DOMString *nam = 0;  // will be lazily initialized to "#document"
  91. static XMLRegisterCleanup namCleanup;
  92. DocumentImpl::DocumentImpl()
  93.     : ParentNode(this)
  94. {
  95.     docType     = null;
  96.     docElement  = null;
  97.     namePool    = new DStringPool(257);
  98.     iterators   = 0L;
  99.     treeWalkers = 0L;
  100.     fNodeIDMap  = 0;
  101.     userData    = 0;
  102.     ranges      = 0;
  103.     fChanges = 0;
  104.     errorChecking = true;
  105. };
  106. //DOM Level 2
  107. DocumentImpl::DocumentImpl(const DOMString &fNamespaceURI,
  108.                            const DOMString &qualifiedName,
  109.                            DocumentTypeImpl *doctype)
  110.     : ParentNode(this)
  111. {
  112.     docType=null;
  113. setDocumentType(doctype);
  114.     docElement=null;
  115.     appendChild(createElementNS(fNamespaceURI, qualifiedName));  //root element
  116.     namePool    = new DStringPool(257);
  117.     iterators   = 0;
  118.     treeWalkers = 0;
  119.     fNodeIDMap  = 0;
  120.     userData    = 0;
  121.     ranges      = 0;
  122.     fChanges = 0;
  123.     errorChecking = true;
  124. }
  125. void DocumentImpl::setDocumentType(DocumentTypeImpl *doctype)
  126. {
  127. if (!doctype)
  128. return;
  129. if (doctype->getOwnerDocument() != null)
  130.         throw DOM_DOMException( //one doctype can belong to only one DocumentImpl
  131.         DOM_DOMException::WRONG_DOCUMENT_ERR, null);
  132.     doctype->setOwnerDocument(this);
  133.     doctype->getEntities()->ownerNode->setOwnerDocument(this);
  134.     doctype->getNotations()->ownerNode->setOwnerDocument(this);
  135.     doctype -> referenced();         // Warning, tricky!  An external (DOM_Node) reference
  136.                                      //  to a node normally bumps the reference count to its
  137.                                      //  document also.  But this could not happen when the
  138.                                      //  user created the DOM_DocumentType because there was
  139.                                      //  no document yet.  Now we have the document, and
  140.                                      //  the docs ref count must be got back in sync.
  141. appendChild(doctype);
  142. }
  143. DocumentImpl::~DocumentImpl()
  144. {
  145.     if (iterators != 0L) {
  146.         // The data in the vector is pointers owned by smart pointers, and will be cleaned up when they go away.
  147.         delete iterators;
  148.     }
  149.     if (treeWalkers != 0L) {
  150.         // The data in the vector is pointers owned by smart pointers, and will be cleaned up when they go away.
  151.         delete treeWalkers;
  152.     }
  153.     if (ranges != 0L) {
  154.         delete ranges;
  155.         ranges = 0;
  156.     }
  157.     if (userData) {
  158.         // make sure we won't access userData any further
  159.         hasUserData(false);
  160.         delete userData;
  161.     }
  162.     delete namePool;
  163.     // Do not delete docType and docElement pointers here.
  164.     //  These are also normal child nodes of the document,
  165.     //  and refcounting will take them out in the usual way.
  166.     delete fNodeIDMap;
  167. };
  168. NodeImpl *DocumentImpl::cloneNode(bool deep) {
  169.     // clone the node itself
  170.     DocumentImpl *newdoc = new DocumentImpl();
  171.     // then the children by _importing_ them
  172.     if (deep) {
  173.         for (ChildNode *n = firstChild; n != null; n = n->nextSibling) {
  174.             newdoc->appendChild(newdoc->importNode(n, true));
  175. }
  176.     }
  177.     newdoc->setErrorChecking(errorChecking);
  178.     return newdoc;
  179. };
  180. DOMString DocumentImpl::getNodeName() {
  181.     return DStringPool::getStaticString("#document"
  182.                                        , &nam
  183.                                        , reinitDocumentImpl
  184.                                        , namCleanup);
  185. }
  186. short DocumentImpl::getNodeType() {
  187.     return DOM_Node::DOCUMENT_NODE;
  188. };
  189. // even though ownerDocument refers to this in this implementation
  190. // the DOM Level 2 spec says it must be null, so make it appear so
  191. DocumentImpl * DocumentImpl::getOwnerDocument() {
  192.     return null;
  193. }
  194. bool DocumentImpl::isDocumentImpl() {
  195.     return true;
  196. };
  197. AttrImpl *DocumentImpl::createAttribute(const DOMString &nam)
  198. {
  199.     if (errorChecking && !isXMLName(nam)) {
  200.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR,null);
  201.     }
  202.     return new AttrImpl(this,nam);
  203. };
  204. CDATASectionImpl *DocumentImpl::createCDATASection(const DOMString &data) {
  205.     return new CDATASectionImpl(this,data);
  206. };
  207. CommentImpl *DocumentImpl::createComment(const DOMString &data)
  208. {
  209.     return new CommentImpl(this,data);
  210. };
  211. DocumentFragmentImpl *DocumentImpl::createDocumentFragment()
  212. {
  213.     return new DocumentFragmentImpl(this);
  214. };
  215. DocumentTypeImpl *DocumentImpl::createDocumentType(const DOMString &nam)
  216. {
  217.     if (errorChecking && !isXMLName(nam)) {
  218.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR, null);
  219.     }
  220.     return new DocumentTypeImpl(this, nam);
  221. };
  222. DocumentTypeImpl *
  223.     DocumentImpl::createDocumentType(const DOMString &qualifiedName,
  224.                                      const DOMString &publicId,
  225.                                      const DOMString &systemId)
  226. {
  227.     if (errorChecking && !isXMLName(qualifiedName)) {
  228.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR, null);
  229.     }
  230.     return new DocumentTypeImpl(this, qualifiedName, publicId, systemId);
  231. };
  232. ElementImpl *DocumentImpl::createElement(const DOMString &tagName)
  233. {
  234.     if (errorChecking && !isXMLName(tagName)) {
  235.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR,null);
  236.     }
  237.     DOMString pooledTagName = this->namePool->getPooledString(tagName);
  238.     return new ElementImpl(this,pooledTagName);
  239. };
  240. ElementImpl *DocumentImpl::createElement(const XMLCh *tagName)
  241. {
  242.     DOMString pooledTagName = this->namePool->getPooledString(tagName);
  243.     return new ElementImpl(this,pooledTagName);
  244. };
  245. EntityImpl *DocumentImpl::createEntity(const DOMString &nam)
  246. {
  247.     if (errorChecking && !isXMLName(nam)) {
  248.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR, null);
  249.     }
  250.     return new EntityImpl(this, nam);
  251. };
  252. EntityReferenceImpl *DocumentImpl::createEntityReference(const DOMString &nam)
  253. {
  254.     if (errorChecking && !isXMLName(nam)) {
  255.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR, null);
  256.     }
  257.     return new EntityReferenceImpl(this, nam);
  258. };
  259. NotationImpl *DocumentImpl::createNotation(const DOMString &nam)
  260. {
  261.     if (errorChecking && !isXMLName(nam)) {
  262.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR, null);
  263.     }
  264.     return new NotationImpl(this, nam);
  265. };
  266. ProcessingInstructionImpl *DocumentImpl::createProcessingInstruction(
  267.                                           const DOMString &target, const DOMString &data)
  268. {
  269.     if (errorChecking && !isXMLName(target)) {
  270.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR,null);
  271.     }
  272.     return new ProcessingInstructionImpl(this,target,data);
  273. };
  274. TextImpl *DocumentImpl::createTextNode(const DOMString &data)
  275. {
  276.     return new TextImpl(this,data);
  277. };
  278. NodeIteratorImpl* DocumentImpl::createNodeIterator (DOM_Node root, unsigned long whatToShow, DOM_NodeFilter* filter, bool entityReferenceExpansion)
  279. {
  280. // Create the node iterator implementation object.
  281. // Add it to the vector of iterators that must be synchronized when a node is deleted.
  282. // The vector of iterators is kept in the "owner document" if there is one. If there isn't one, I assume that root is the
  283. // owner document.
  284.     NodeIteratorImpl* iter = new NodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion);
  285.     DOM_Document doc = root.getOwnerDocument();
  286.     DocumentImpl* impl;
  287.     if (! doc.isNull()) {
  288.         impl = (DocumentImpl *) doc.fImpl;
  289.     }
  290.     else
  291.         impl = (DocumentImpl *) root.fImpl;
  292.     if (impl->iterators == 0L) {
  293.         impl->iterators = new NodeIterators(1, false);
  294.         impl->iterators->addElement(iter);
  295.     }
  296.     return iter;
  297. }
  298. TreeWalkerImpl* DocumentImpl::createTreeWalker (DOM_Node root, unsigned long whatToShow, DOM_NodeFilter* filter, bool entityReferenceExpansion)
  299. {
  300. // See notes for createNodeIterator...
  301.     TreeWalkerImpl* twi = new TreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  302.     DOM_Document doc = root.getOwnerDocument();
  303.     DocumentImpl* impl;
  304.     if (! doc.isNull()) {
  305.         impl = (DocumentImpl *) doc.fImpl;
  306.     }
  307.     else
  308.         impl = (DocumentImpl *) root.fImpl;
  309.     if (impl->treeWalkers == 0L) {
  310.         impl->treeWalkers = new TreeWalkers(1, false);
  311.         impl->treeWalkers->addElement(twi);
  312.     }
  313.     return twi;
  314. }
  315. DocumentTypeImpl *DocumentImpl::getDoctype()
  316. {
  317.     return docType;
  318. };
  319. ElementImpl *DocumentImpl::getDocumentElement()
  320. {
  321.     return docElement;
  322. };
  323. DeepNodeListImpl *DocumentImpl::getElementsByTagName(const DOMString &tagname)
  324. {
  325.     return new DeepNodeListImpl(this,tagname);
  326. };
  327. NodeImpl *DocumentImpl::insertBefore(NodeImpl *newChild, NodeImpl *refChild)
  328. {
  329.     // Only one such child permitted
  330.     if (errorChecking &&
  331.         ((newChild->isElementImpl() && docElement!=null) ||
  332.          (newChild->isDocumentTypeImpl() && docType!=null))) {
  333.         throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR,null);
  334.     }
  335.     ParentNode::insertBefore(newChild,refChild);
  336.     // If insert succeeded, cache the kid appropriately
  337.     if(newChild->isElementImpl())
  338.         docElement=(ElementImpl *)newChild;
  339.     else if(newChild->isDocumentTypeImpl())
  340.         docType=(DocumentTypeImpl *)newChild;
  341.     return newChild;
  342. };
  343. bool DocumentImpl::isXMLName(const DOMString &s)
  344. {
  345.     const XMLCh   *nam;
  346.     int           length;
  347.     int           i;
  348.     length = s.length();
  349.     if (length == 0)
  350.         return false;
  351.     nam = s.rawBuffer();
  352.     if (!XMLReader::isFirstNameChar(nam[0]))
  353.         return false;
  354.     for (i=1; i<length; i++)
  355.     {
  356.         if (!XMLReader::isNameChar(nam[i]))
  357.             return false;
  358.     }
  359.     return true;
  360. };
  361. //  referenced().   Override this function here in class DocumentImpl because
  362. //                  we don't want the action taken in NodeImpl, which is
  363. //                  to add a reference to the node's owning document.
  364. //
  365. void DocumentImpl::referenced()
  366. {
  367.     // Intentionally empty.
  368. };
  369. NodeImpl *DocumentImpl::removeChild(NodeImpl *oldChild)
  370. {
  371.     ParentNode::removeChild(oldChild);
  372.     // If remove succeeded, un-cache the kid appropriately
  373.     if(oldChild->isElementImpl())
  374.         docElement=null;
  375.     else if(oldChild->isDocumentTypeImpl())
  376.         docType=null;
  377.     return oldChild;
  378. };
  379. //
  380. //    unreferenced()  will be called whenever the refernce count on
  381. //          this document goes from 1 to 0.  In all cases, when this
  382. //          happens to a document node (which is the case here), it
  383. //          is time to actually delete the document.
  384. //
  385. //          See also NodeImpl::referenced() and unreferenced(), which
  386. //          update document node ref counts based on references coming
  387. //          or going to nodes owned by the document.
  388. //
  389. void DocumentImpl::unreferenced()
  390. {
  391.     deleteIf(this);
  392. };
  393. //Introduced in DOM Level 2
  394. NodeImpl *DocumentImpl::importNode(NodeImpl *source, bool deep)
  395. {
  396.     NodeImpl *newnode=null;
  397.     switch (source->getNodeType())
  398.     {
  399.     case DOM_Node::ELEMENT_NODE :
  400.         {
  401.             ElementImpl *newelement;
  402.     if (source->getLocalName() == null)
  403. newelement = createElement(source->getNodeName());
  404.     else
  405. newelement = createElementNS(source->getNamespaceURI(),
  406.                                              source->getNodeName());
  407.             NamedNodeMapImpl *srcattr=source->getAttributes();
  408.             if(srcattr!=null)
  409.                 for(unsigned int i=0;i<srcattr->getLength();++i)
  410. {
  411.     AttrImpl *attr = (AttrImpl *) srcattr->item(i);
  412.     if (attr -> getSpecified()) { // not a default attribute
  413.                         AttrImpl *nattr = (AttrImpl *) importNode(attr, true);
  414. if (attr -> getLocalName() == null)
  415.     newelement->setAttributeNode(nattr);
  416. else
  417.     newelement->setAttributeNodeNS(nattr);
  418.                     }
  419. }
  420.             newnode=newelement;
  421.         }
  422.         break;
  423.     case DOM_Node::ATTRIBUTE_NODE :
  424.         {
  425.             if (source->getLocalName() == null)
  426.                 newnode = createAttribute(source->getNodeName());
  427.             else
  428.                 newnode = createAttributeNS(source->getNamespaceURI(),
  429.                                         source->getNodeName());
  430.         // if source is an AttrImpl from this very same implementation
  431.         // avoid creating the child nodes if possible
  432. //        if (source instanceof AttrImpl) {
  433.             AttrImpl *attr = (AttrImpl *) source;
  434.             if (attr->hasStringValue()) {
  435.                 AttrImpl *newattr = (AttrImpl *) newnode;
  436.                 newattr->setValue(attr->getValue());
  437.                 deep = false;
  438.             }
  439.             else {
  440.                 deep = true;
  441.             }
  442. //        }
  443. //        else {
  444. //            // Kids carry value
  445. //            deep = true;
  446. //        }
  447.         }
  448.         break;
  449.     case DOM_Node::TEXT_NODE :
  450.         newnode = createTextNode(source->getNodeValue());
  451.         break;
  452.     case DOM_Node::CDATA_SECTION_NODE :
  453.         newnode = createCDATASection(source->getNodeValue());
  454.         break;
  455.     case DOM_Node::ENTITY_REFERENCE_NODE :
  456.         newnode = createEntityReference(source->getNodeName());
  457. newnode -> isReadOnly(false); //allow deep import temporarily
  458.         break;
  459.     case DOM_Node::ENTITY_NODE :
  460.         {
  461.             EntityImpl *srcentity=(EntityImpl *)source;
  462.             EntityImpl *newentity = createEntity(source->getNodeName());
  463.             newentity->setPublicId(srcentity->getPublicId());
  464.             newentity->setSystemId(srcentity->getSystemId());
  465.             newentity->setNotationName(srcentity->getNotationName());
  466.             // Kids carry additional value
  467.             newnode=newentity;
  468.             newentity->isReadOnly(false);// allow deep import temporarily
  469.         }
  470.         break;
  471.     case DOM_Node::PROCESSING_INSTRUCTION_NODE :
  472.         newnode = createProcessingInstruction(source->getNodeName(),
  473.                                               source->getNodeValue());
  474.         break;
  475.     case DOM_Node::COMMENT_NODE :
  476.         newnode = createComment(source->getNodeValue());
  477.         break;
  478.     case DOM_Node::DOCUMENT_TYPE_NODE :
  479.         {
  480.             DocumentTypeImpl *srcdoctype = (DocumentTypeImpl *)source;
  481.             DocumentTypeImpl *newdoctype = (DocumentTypeImpl *)
  482.                 createDocumentType(srcdoctype->getNodeName(),
  483.                                    srcdoctype->getPublicId(),
  484.                                    srcdoctype->getSystemId());
  485.             // Values are on NamedNodeMaps
  486.             NamedNodeMapImpl *smap = srcdoctype->getEntities();
  487.             NamedNodeMapImpl *tmap = newdoctype->getEntities();
  488.             if(smap != null) {
  489.                 for(unsigned int i = 0; i < smap->getLength(); i++) {
  490.                     tmap->setNamedItem(importNode(smap->item(i), true));
  491.                 }
  492.             }
  493.             smap = srcdoctype->getNotations();
  494.             tmap = newdoctype->getNotations();
  495.             if (smap != null) {
  496.                 for(unsigned int i = 0; i < smap->getLength(); i++) {
  497.                     tmap->setNamedItem(importNode(smap->item(i), true));
  498.                 }
  499.             }
  500.             // NOTE: At this time, the DOM definition of DocumentType
  501.             // doesn't cover Elements and their Attributes. domimpl's
  502.             // extentions in that area will not be preserved, even if
  503.             // copying from domimpl to domimpl. We could special-case
  504.             // that here. Arguably we should. Consider. ?????
  505.             newnode = newdoctype;
  506.         }
  507.         break;
  508.     case DOM_Node::DOCUMENT_FRAGMENT_NODE :
  509.         newnode = createDocumentFragment();
  510.         // No name, kids carry value
  511.         break;
  512.     case DOM_Node::NOTATION_NODE :
  513.         {
  514.             NotationImpl *srcnotation=(NotationImpl *)source;
  515.             NotationImpl *newnotation = createNotation(source->getNodeName());
  516.             newnotation->setPublicId(srcnotation->getPublicId());
  517.             newnotation->setSystemId(srcnotation->getSystemId());
  518.             // Kids carry additional value
  519.             newnode=newnotation;
  520.             // No name, no value
  521.             break;
  522.         }
  523.     case DOM_Node::DOCUMENT_NODE : // Document can't be child of Document
  524.     default:                       // Unknown node type
  525.         throw DOM_DOMException(DOM_DOMException::NOT_SUPPORTED_ERR, null);
  526.     }
  527.     // If deep, replicate and attach the kids.
  528.     if (deep)
  529.         for (NodeImpl *srckid = source->getFirstChild();
  530.              srckid != null;
  531.              srckid = srckid->getNextSibling()) {
  532.             newnode->appendChild(importNode(srckid, true));
  533.         }
  534.     if (newnode->getNodeType() == DOM_Node::ENTITY_REFERENCE_NODE
  535.         || newnode->getNodeType() == DOM_Node::ENTITY_REFERENCE_NODE)
  536. newnode->isReadOnly(true);
  537.     return newnode;
  538. };
  539. ElementImpl *DocumentImpl::createElementNS(const DOMString &fNamespaceURI,
  540. const DOMString &qualifiedName)
  541. {
  542.     if (errorChecking && !isXMLName(qualifiedName)) {
  543.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR,null);
  544.     }
  545.     //DOMString pooledTagName = this->namePool->getPooledString(qualifiedName);
  546.     return new ElementNSImpl(this, fNamespaceURI, qualifiedName);
  547. }
  548. AttrImpl *DocumentImpl::createAttributeNS(const DOMString &fNamespaceURI,
  549. const DOMString &qualifiedName)
  550. {
  551.     if (!isXMLName(qualifiedName)) {
  552.         throw DOM_DOMException(DOM_DOMException::INVALID_CHARACTER_ERR,null);
  553.     }
  554.     return new AttrNSImpl(this, fNamespaceURI, qualifiedName);
  555. }
  556. DeepNodeListImpl *DocumentImpl::getElementsByTagNameNS(const DOMString &fNamespaceURI,
  557. const DOMString &fLocalName)
  558. {
  559.     return new DeepNodeListImpl(this, fNamespaceURI, fLocalName);
  560. }
  561. ElementImpl *DocumentImpl::getElementById(const DOMString &elementId)
  562. {
  563.     if (fNodeIDMap == 0)
  564.         return null;
  565.     AttrImpl *theAttr = fNodeIDMap->find(elementId);
  566.     if (theAttr == null)
  567.     return null;
  568.     return theAttr->getOwnerElement();
  569. }
  570. //Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
  571. //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd".
  572. int DocumentImpl::indexofQualifiedName(const DOMString & qName)
  573. {
  574.     //Check if s = prefix:localName, name or malformed
  575.     const XMLCh *qNameP = qName.rawBuffer();
  576.     int qNameLen = qName.length(); //note: qName[qNameLen] may not be 0
  577.     int index = -1, count = 0;
  578.     for (int i = 0; i < qNameLen; ++i)
  579. if (*qNameP++ == chColon) {
  580.     index = i;
  581.     ++count; //number of ':' found
  582. }
  583.     if (qNameLen == 0 || count > 1 || index == 0 || index == qNameLen-1)
  584.         return -1;
  585.     return count == 0 ? 0 : index;
  586. }
  587. XMLDeclImpl* DocumentImpl::createXMLDecl(const DOMString& version, const DOMString& encoding, const DOMString& standalone)
  588. {
  589.     return new XMLDeclImpl(this, version, encoding, standalone);
  590. }
  591. RangeImpl* DocumentImpl::createRange()
  592. {
  593.     RangeImpl* range = new RangeImpl(DOM_Document(this));
  594.     if (ranges == 0L) {
  595.         ranges = new RangeImpls(1, false);
  596.     }
  597.     ranges->addElement(range);
  598.     return range;
  599. }
  600. RangeImpls* DocumentImpl::getRanges()
  601. {
  602.     return ranges;
  603. }
  604. void DocumentImpl::removeRange(RangeImpl* range)
  605. {
  606.     if (ranges != null) {
  607.         unsigned int sz = ranges->size();
  608.         if (sz !=0) {
  609.             for (unsigned int i =0; i<sz; i++) {
  610.                 if (ranges->elementAt(i) == range) {
  611.                     ranges->removeElementAt(i);
  612.                     delete range;
  613.                     break;
  614.                 }
  615.             }
  616.         }
  617.     }
  618. }
  619. /** Uses the kidOK lookup table to check whether the proposed
  620.     tree structure is legal.
  621.     ????? It feels like there must be a more efficient solution,
  622.     but for the life of me I can't think what it would be.
  623. */
  624. bool DocumentImpl::isKidOK(NodeImpl *parent, NodeImpl *child)
  625. {
  626.       static int kidOK[14];
  627.       if (kidOK[DOM_Node::DOCUMENT_NODE] == 0)
  628.       {
  629.           kidOK[DOM_Node::DOCUMENT_NODE] =
  630.               1 << DOM_Node::ELEMENT_NODE |
  631.               1 << DOM_Node::PROCESSING_INSTRUCTION_NODE |
  632.               1 << DOM_Node::COMMENT_NODE |
  633.               1 << DOM_Node::DOCUMENT_TYPE_NODE |
  634.               1 << DOM_Node::XML_DECL_NODE;
  635.           kidOK[DOM_Node::DOCUMENT_FRAGMENT_NODE] =
  636.               kidOK[DOM_Node::ENTITY_NODE] =
  637.               kidOK[DOM_Node::ENTITY_REFERENCE_NODE] =
  638.               kidOK[DOM_Node::ELEMENT_NODE] =
  639.               1 << DOM_Node::ELEMENT_NODE |
  640.               1 << DOM_Node::PROCESSING_INSTRUCTION_NODE |
  641.               1 << DOM_Node::COMMENT_NODE |
  642.               1 << DOM_Node::TEXT_NODE |
  643.               1 << DOM_Node::CDATA_SECTION_NODE |
  644.               1 << DOM_Node::ENTITY_REFERENCE_NODE |
  645.               1 << DOM_Node::XML_DECL_NODE;
  646.           kidOK[DOM_Node::ATTRIBUTE_NODE] =
  647.               1 << DOM_Node::TEXT_NODE |
  648.               1 << DOM_Node::ENTITY_REFERENCE_NODE;
  649.           kidOK[DOM_Node::PROCESSING_INSTRUCTION_NODE] =
  650.               kidOK[DOM_Node::COMMENT_NODE] =
  651.               kidOK[DOM_Node::TEXT_NODE] =
  652.               kidOK[DOM_Node::CDATA_SECTION_NODE] =
  653.               kidOK[DOM_Node::NOTATION_NODE] =
  654.               0;
  655.       };
  656.       int p=parent->getNodeType();
  657.       int ch = child->getNodeType();
  658.       return (kidOK[p] & 1<<ch) != 0;
  659. }
  660. void DocumentImpl::setUserData(NodeImpl* n, void* data)
  661. {
  662. if (!userData && data)
  663. userData = new RefHashTableOf<void>(29, false, new HashPtr());
  664. if (!data && userData)
  665. userData->removeKey((void*)n);
  666. else
  667. userData->put((void*)n,data);
  668. }
  669. void* DocumentImpl::getUserData(NodeImpl* n)
  670. {
  671. if (userData)
  672. return userData->get((void*)n);
  673. else
  674. return null;
  675. }
  676. void* DocumentImpl::getUserData()
  677. {
  678. return (hasUserData()) ? getUserData(this) : null;
  679. }
  680. void DocumentImpl::setUserData(void* val)
  681. {
  682. setUserData(this, val);
  683. if (val)
  684. hasUserData(true);
  685. else
  686. hasUserData(false);
  687. };
  688. /**
  689.  * Denotes that this node has changed.
  690.  */
  691. void DocumentImpl::changed() {
  692.     fChanges++;
  693. }
  694. /**
  695.  * Returns the number of changes to this node.
  696.  */
  697. int DocumentImpl::changes() {
  698.     return fChanges;
  699. }
  700. // -----------------------------------------------------------------------
  701. //  Notification that lazy data has been deleted
  702. // -----------------------------------------------------------------------
  703. void DocumentImpl::reinitDocumentImpl() {
  704. delete nam;
  705. nam = 0;
  706. }