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

词法分析

开发平台:

Visual C++

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