domdocumentimpl.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,362 行 · 第 1/3 页
CPP
1,362 行
DOMNodeList *DOMDocumentImpl::getElementsByTagName(const XMLCh *tagname) const{ // cast off the const of this because we will update the fNodeListPool return ((DOMDocumentImpl*)this)->getDeepNodeList(this,tagname);}DOMImplementation *DOMDocumentImpl::getImplementation() const { return DOMImplementation::getImplementation();}DOMNode *DOMDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild){ // Only one such child permitted if( (newChild->getNodeType() == DOMNode::ELEMENT_NODE && fDocElement!=0) || (newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE && fDocType!=0) ) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, getMemoryManager()); // if the newChild is a documenttype node created from domimplementation, set the ownerDoc first if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument()) ((DOMDocumentTypeImpl*)newChild)->setOwnerDocument(this); fParent.insertBefore(newChild,refChild); // If insert succeeded, cache the kid appropriately if(newChild->getNodeType() == DOMNode::ELEMENT_NODE) fDocElement=(DOMElement *)newChild; else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) fDocType=(DOMDocumentType *)newChild; return newChild;}DOMNode* DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) { DOMDocumentType* tempDocType = fDocType; DOMElement* tempDocElement = fDocElement; if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) fDocType=0; else if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE) fDocElement=0; try { insertBefore(newChild, oldChild); // changed() already done. if((oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) || (oldChild->getNodeType() == DOMNode::ELEMENT_NODE)) return fParent.removeChild(oldChild); else return removeChild(oldChild); } catch(const OutOfMemoryException&) { throw; } catch(...) { fDocType = tempDocType; fDocElement = tempDocElement; throw; }}bool DOMDocumentImpl::isXMLName(const XMLCh *s){ if (XMLString::equals(fVersion, XMLUni::fgVersion1_1)) return XMLChar1_1::isValidName(s, XMLString::stringLen(s)); else return XMLChar1_0::isValidName(s, XMLString::stringLen(s));}DOMNode *DOMDocumentImpl::removeChild(DOMNode *oldChild){ fParent.removeChild(oldChild); // If remove succeeded, un-cache the kid appropriately if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE) fDocElement=0; else if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) fDocType=0; return oldChild;}void DOMDocumentImpl::setNodeValue(const XMLCh *x){ fNode.setNodeValue(x);}//Introduced in DOM Level 2DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep){ return importNode(source, deep, false);}DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI, const XMLCh *qualifiedName){ if(!qualifiedName || !isXMLName(qualifiedName)) throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); //XMLCh * pooledTagName = this->fNamePool->getPooledString(qualifiedName); return new (this, DOMDocumentImpl::ELEMENT_NS_OBJECT) DOMElementNSImpl(this, fNamespaceURI, qualifiedName);}DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI, const XMLCh *qualifiedName, const XMLSSize_t lineNo, const XMLSSize_t columnNo){ if(!qualifiedName || !isXMLName(qualifiedName)) throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); return new (this) XSDElementNSImpl(this, fNamespaceURI, qualifiedName, lineNo, columnNo);}DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI, const XMLCh *qualifiedName){ if(!qualifiedName || !isXMLName(qualifiedName)) throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager()); return new (this, DOMDocumentImpl::ATTR_NS_OBJECT) DOMAttrNSImpl(this, fNamespaceURI, qualifiedName);}DOMNodeList *DOMDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI, const XMLCh *fLocalName) const{ // cast off the const of this because we will update the fNodeListPool return ((DOMDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName);}DOMElement *DOMDocumentImpl::getElementById(const XMLCh *elementId) const{ if (fNodeIDMap == 0) return 0; DOMAttr *theAttr = fNodeIDMap->find(elementId); if (theAttr == 0) return 0; return theAttr->getOwnerElement();}//Return the index > 0 of ':' in the given qualified name qName="prefix:localName".//Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd" or "abcd:".int DOMDocumentImpl::indexofQualifiedName(const XMLCh * qName){ int qNameLen = XMLString::stringLen(qName); int index = -1, count = 0; for (int i = 0; i < qNameLen; ++i) { if (qName[i] == chColon) { index = i; ++count; //number of ':' found } } if (qNameLen == 0 || count > 1 || index == 0 || index == qNameLen-1) return -1; return count == 0 ? 0 : index;}const XMLCh* DOMDocumentImpl::getBaseURI() const{ return fDocumentURI;}DOMRange* DOMDocumentImpl::createRange(){ DOMRangeImpl* range = new (this) DOMRangeImpl(this, fMemoryManager); if (fRanges == 0L) { //fRanges = new (this) Ranges(1, false); fRanges = new (fMemoryManager) Ranges(1, false, fMemoryManager); // XMemory } fRanges->addElement(range); return range;}Ranges* DOMDocumentImpl::getRanges() const{ return fRanges;}void DOMDocumentImpl::removeRange(DOMRangeImpl* range){ if (fRanges != 0) { XMLSize_t sz = fRanges->size(); if (sz !=0) { for (XMLSize_t i =0; i<sz; i++) { if (fRanges->elementAt(i) == range) { fRanges->removeElementAt(i); break; } } } }}/** Uses the kidOK lookup table to check whether the proposed tree structure is legal. ????? It feels like there must be a more efficient solution, but for the life of me I can't think what it would be.*/bool DOMDocumentImpl::isKidOK(DOMNode *parent, DOMNode *child){ static int kidOK[14]; if (kidOK[DOMNode::ATTRIBUTE_NODE] == 0) { kidOK[DOMNode::DOCUMENT_NODE] = 1 << DOMNode::ELEMENT_NODE | 1 << DOMNode::PROCESSING_INSTRUCTION_NODE | 1 << DOMNode::COMMENT_NODE | 1 << DOMNode::DOCUMENT_TYPE_NODE; kidOK[DOMNode::DOCUMENT_FRAGMENT_NODE] = kidOK[DOMNode::ENTITY_NODE] = kidOK[DOMNode::ENTITY_REFERENCE_NODE] = kidOK[DOMNode::ELEMENT_NODE] = 1 << DOMNode::ELEMENT_NODE | 1 << DOMNode::PROCESSING_INSTRUCTION_NODE | 1 << DOMNode::COMMENT_NODE | 1 << DOMNode::TEXT_NODE | 1 << DOMNode::CDATA_SECTION_NODE | 1 << DOMNode::ENTITY_REFERENCE_NODE; kidOK[DOMNode::ATTRIBUTE_NODE] = 1 << DOMNode::TEXT_NODE | 1 << DOMNode::ENTITY_REFERENCE_NODE; kidOK[DOMNode::PROCESSING_INSTRUCTION_NODE] = kidOK[DOMNode::COMMENT_NODE] = kidOK[DOMNode::TEXT_NODE] = kidOK[DOMNode::CDATA_SECTION_NODE] = kidOK[DOMNode::NOTATION_NODE] = 0; } int p=parent->getNodeType(); int ch = child->getNodeType(); return (kidOK[p] & 1<<ch) != 0;}void DOMDocumentImpl::changed(){ fChanges++;}int DOMDocumentImpl::changes() const{ return fChanges;}//// Delegation for functions inherited from DOMNode// DOMNode* DOMDocumentImpl::appendChild(DOMNode *newChild) {return insertBefore(newChild, 0); } DOMNamedNodeMap* DOMDocumentImpl::getAttributes() const {return fNode.getAttributes (); } DOMNodeList* DOMDocumentImpl::getChildNodes() const {return fParent.getChildNodes (); } DOMNode* DOMDocumentImpl::getFirstChild() const {return fParent.getFirstChild (); } DOMNode* DOMDocumentImpl::getLastChild() const {return fParent.getLastChild (); } const XMLCh* DOMDocumentImpl::getLocalName() const {return fNode.getLocalName (); } const XMLCh* DOMDocumentImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); } DOMNode* DOMDocumentImpl::getNextSibling() const {return fNode.getNextSibling (); } const XMLCh* DOMDocumentImpl::getNodeValue() const {return fNode.getNodeValue (); } const XMLCh* DOMDocumentImpl::getPrefix() const {return fNode.getPrefix (); } DOMNode* DOMDocumentImpl::getParentNode() const {return fNode.getParentNode (); } DOMNode* DOMDocumentImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); } bool DOMDocumentImpl::hasChildNodes() const {return fParent.hasChildNodes (); } void DOMDocumentImpl::normalize() {fParent.normalize (); } bool DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const {return fNode.isSupported (feature, version); } void DOMDocumentImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); } bool DOMDocumentImpl::hasAttributes() const {return fNode.hasAttributes(); } bool DOMDocumentImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other);} bool DOMDocumentImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg);} void* DOMDocumentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler) {return fNode.setUserData(key, data, handler); } void* DOMDocumentImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); } short DOMDocumentImpl::compareTreePosition(const DOMNode* other) const {return fNode.compareTreePosition(other); } const XMLCh* DOMDocumentImpl::getTextContent() const {return fNode.getTextContent(); } void DOMDocumentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); } const XMLCh* DOMDocumentImpl::lookupNamespacePrefix(const XMLCh* namespaceURI, bool useDefault) const {return fNode.lookupNamespacePrefix(namespaceURI, useDefault); } bool DOMDocumentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); } const XMLCh* DOMDocumentImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); } DOMNode* DOMDocumentImpl::getInterface(const XMLCh* feature) {return fNode.getInterface(feature); }//-----------------------------------------------------------------------//// Per Document Heap and Heap Helper functions//// revisit - this stuff should be a class of its own, rather than// just lying around naked in DocumentImpl.////-----------------------------------------------------------------------XMLCh * DOMDocumentImpl::cloneString(const XMLCh *src){ if (!src) return 0; size_t len = XMLString::stringLen(src); len = (len + 1) * sizeof(XMLCh); len = (len % 4) + len; XMLCh *newStr = (XMLCh *)this->allocate(len); XMLString::copyString(newStr, src); return newStr;}const XMLCh * DOMDocumentImpl::getPooledString(const XMLCh *src){ if (!src) return 0; else return this->fNamePool->getPooledString(src);}static const int kHeapAllocSize = 0x10000; // The chunk size to allocate from the // system allocator.static const int kMaxSubAllocationSize = 4096; // Any request for more bytes // than this will be handled by // allocating directly with system.void * DOMDocumentImpl::allocate(size_t amount){ // Align the request size so that suballocated blocks // beyond this one will be maintained at the same alignment. amount = XMLPlatformUtils::alignPointerForNewBlockAllocation(amount); // If the request is for a largish block, hand it off to the system // allocator. The block still must be linked into the list of // allocated blocks so that it will be deleted when the time comes. if (amount > kMaxSubAllocationSize) { // The size of the header we add to our raw blocks size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); // Try to allocate the block void* newBlock; newBlock = fMemoryManager->allocate((sizeOfHeader + amount) * sizeof(char)); //new char[amount + sizeOfHeader]; // Link it into the list beyond current block, as current block // is still being subdivided. If there is no current block // then track that we have no bytes to further divide. if (fCurrentBlock) { *(void **)newBlock = *(void **)fCurrentBlock; *(void **)fCurrentBlock = newBlock; } else { fCurrentBlock = newBlock; fFreePtr = 0; fFreeBytesRemaining = 0; } void *retPtr = (char *)newBlock + sizeOfHeader; return retPtr; } // It's a normal (sub-allocatable) request. // Are we out of room in our current block? if (amount > fFreeBytesRemaining) { // Request doesn't fit in the current block. // The size of the header we add to our raw blocks size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); // Get a new block from the system allocator. void* newBlock; newBlock = fMemoryManager->allocate(kHeapAllocSize * sizeof(char)); //new char[kHeapAllocSize]; *(void **)newBlock = fCurrentBlock; fCurrentBlock = newBlock; fFreePtr = (char *)newBlock + sizeOfHeader; fFreeBytesRemaining = kHeapAllocSize - sizeOfHeader; } // Subdivide the request off current block void *retPtr = fFreePtr; fFreePtr += amount; fFreeBytesRemaining -= amount; return retPtr;}void DOMDocumentImpl::deleteHeap(){ while (fCurrentBlock != 0) { void *nextBlock = *(void **)fCurrentBlock; fMemoryManager->deallocate(fCurrentBlock); //delete [] (char*) fCurrentBlock; fCurrentBlock = nextBlock; }}DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName){ if(!fNodeListPool) { fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false); } DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, tagName, 0); if (!retList) { int id = fNodeListPool->put((void*) rootNode, (XMLCh*) tagName, 0, new (this) DOMDeepNodeListImpl(rootNode, tagName)); retList = fNodeListPool->getById(id); } return retList;}DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, //DOM Level 2 const XMLCh *namespaceURI, const XMLCh *localName){ if(!fNodeListPool) { fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false); } DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, localName, namespaceURI); if (!retList) { // the pool will adopt the DOMDeepNodeListImpl int id = fNodeListPool->put((void*) rootNode, (XMLCh*) localName, (XMLCh*) namespaceURI, new (this) DOMDeepNodeListImpl(rootNode, namespaceURI, localName)); retList = fNodeListPool->getById(id); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?