domrangeimpl.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 2,115 行 · 第 1/5 页
CPP
2,115 行
void DOMRangeImpl::detach(){ if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } ((DOMDocumentImpl *)fDocument)->removeRange(this); fDetached = true; //0ify nodes fStartContainer = 0; fStartOffset = 0; fEndContainer = 0; fEndOffset = 0; fCollapsed = true; fRemoveChild = 0;}void DOMRangeImpl::collapse(bool toStart){ if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } if (toStart) { fEndContainer = fStartContainer; fEndOffset = fStartOffset; } else { fStartContainer = fEndContainer; fStartOffset = fEndOffset; } fCollapsed = true;}void DOMRangeImpl::selectNode(const DOMNode* refNode){ validateNode(refNode); if ( !isLegalContainedNode(refNode)) { throw DOMRangeException( DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); } //First check for the text type node short type = refNode->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { //The node itself is the container. fStartContainer = (DOMNode*) refNode; fEndContainer = (DOMNode*) refNode; //Select all the contents of the node fStartOffset = 0; if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)refNode)->getData()); else fEndOffset = ((DOMText *)refNode)->getLength(); return; } DOMNode* parent = refNode->getParentNode(); if (parent != 0 ) // REVIST: what to do if it IS 0? { fStartContainer = parent; fEndContainer = parent; XMLSize_t i = 0; for (DOMNode* n = parent->getFirstChild(); n!=0 && n!=refNode; n = n->getNextSibling()) { i++; } fStartOffset = i; fEndOffset = fStartOffset+1; }}void DOMRangeImpl::selectNodeContents(const DOMNode* node){ validateNode(node); fStartContainer = (DOMNode*) node; fEndContainer = (DOMNode*) node; fStartOffset = 0; short type = node->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE)) { fEndOffset = ((DOMText *)node)->getLength(); return; } if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) { fEndOffset = XMLString::stringLen(((DOMProcessingInstruction*)node)->getData()); return; } DOMNode* first = node->getFirstChild(); if (first == 0) { fEndOffset = 0; return; } XMLSize_t i = 0; for (DOMNode* n = first; n!=0; n = n->getNextSibling()) { i++; } fEndOffset = i;}void DOMRangeImpl::surroundContents(DOMNode* newParent){ if (newParent==0) return; //check for elimination criteria if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } if (newParent->getOwnerDocument() !=fDocument) { throw DOMException( DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); } int type = newParent->getNodeType(); if ( !isLegalContainedNode(newParent) || type == DOMNode::DOCUMENT_TYPE_NODE) { throw DOMRangeException( DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); } DOMNode* realStart = fStartContainer; DOMNode* realEnd = fEndContainer; type = fStartContainer->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { realStart = fStartContainer->getParentNode(); } type = fEndContainer->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { realEnd = fEndContainer->getParentNode(); } if (realStart != realEnd) { throw DOMRangeException( DOMRangeException::BAD_BOUNDARYPOINTS_ERR, 0, fMemoryManager); } DOMDocumentFragment* frag = (DOMDocumentFragment*) extractContents(); insertNode(newParent); newParent->appendChild(frag); selectNode(newParent);}short DOMRangeImpl::compareBoundaryPoints(DOMRange::CompareHow how, const DOMRange* srcRange) const{ if (fDocument != ((DOMRangeImpl*)srcRange)->fDocument) { throw DOMException( DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); } if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } DOMNode* pointA; DOMNode* pointB; int offsetA, offsetB; switch (how) { case (DOMRange::START_TO_START) : pointB = srcRange->getStartContainer(); pointA = fStartContainer; offsetB = srcRange->getStartOffset(); offsetA = fStartOffset; break; case (DOMRange::START_TO_END) : pointB = srcRange->getStartContainer(); pointA = fEndContainer; offsetB = srcRange->getStartOffset(); offsetA = fEndOffset; break; case (DOMRange::END_TO_START) : pointB = srcRange->getEndContainer(); pointA = fStartContainer; offsetB = srcRange->getEndOffset(); offsetA = fStartOffset; break; case (DOMRange::END_TO_END) : pointB = srcRange->getEndContainer(); pointA = fEndContainer; offsetB = srcRange->getEndOffset(); offsetA = fEndOffset; break; } // case 1: same container if (pointA == pointB) { if (offsetA < offsetB) return -1; //A before B if (offsetA == offsetB) return 0; //A equal to B return 1; // A after B } // case 2: Child C of container A is ancestor of B for (DOMNode* node = pointA->getFirstChild(); node != 0; node=node->getNextSibling()) { if (isAncestorOf(node, pointB)) { int index = indexOf(node, pointA); if (offsetA <= index) return -1; return 1; } } // case 3: Child C of container B is ancestor of A for (DOMNode* nd = pointB->getFirstChild(); nd != 0; nd=nd->getNextSibling()) { if (isAncestorOf(nd, pointA)) { int index = indexOf(nd, pointB); if (index < offsetB ) return -1; return 1; //B strictly before A } } // case 4: preorder traversal of context tree. // Instead of literally walking the context tree in pre-order, // we use relative node depth walking which is usually faster int depthDiff = 0; DOMNode* n = 0; for ( n = pointB; n != 0; n = n->getParentNode() ) depthDiff++; for ( n = pointA; n != 0; n = n->getParentNode() ) depthDiff--; while (depthDiff > 0) { pointB = pointB->getParentNode(); depthDiff--; } while (depthDiff < 0) { pointA = pointA->getParentNode(); depthDiff++; } for (DOMNode* pB = pointB->getParentNode(), *pA = pointA->getParentNode(); pB != pA; pB = pB->getParentNode(), pA = pA->getParentNode() ) { pointB = pB; pointA = pA; } for ( n = pointB->getNextSibling(); n != 0; n = n->getNextSibling() ) { if (n == pointA) { return 1; } } return -1;}void DOMRangeImpl:: deleteContents(){ traverseContents(DELETE_CONTENTS);}DOMDocumentFragment* DOMRangeImpl::extractContents(){ checkReadOnly(fStartContainer, fEndContainer, fStartOffset, fEndOffset); return traverseContents(EXTRACT_CONTENTS);}DOMDocumentFragment* DOMRangeImpl::cloneContents() const{ // cast off const. return ((DOMRangeImpl *)this)->traverseContents(CLONE_CONTENTS);}void DOMRangeImpl::insertNode(DOMNode* newNode){ if (newNode == 0) return; //don't have to do anything if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } int type = newNode->getNodeType(); if (type == DOMNode::ATTRIBUTE_NODE || type == DOMNode::ENTITY_NODE || type == DOMNode::NOTATION_NODE || type == DOMNode::DOCUMENT_NODE) { throw DOMRangeException( DOMRangeException::INVALID_NODE_TYPE_ERR, 0, fMemoryManager); } // Prevent cycles in the tree. //isKidOK() is not checked here as its taken care by insertBefore() function if (isAncestorOf( newNode, fStartContainer)) { throw DOMException( DOMException::HIERARCHY_REQUEST_ERR, 0, fMemoryManager); } for (DOMNode* aNode = fStartContainer; aNode!=0; aNode = aNode->getParentNode()) { if (castToNodeImpl(newNode)->isReadOnly()) { throw DOMException( DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, fMemoryManager); } } if (fDocument != newNode->getOwnerDocument()) { throw DOMException( DOMException::WRONG_DOCUMENT_ERR, 0, fMemoryManager); } DOMNode* parent; DOMNode* next; type = fStartContainer->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { //set 'parent' and 'next' here parent = fStartContainer->getParentNode(); //split the text nodes if (fStartOffset > 0) { if (type == DOMNode::COMMENT_NODE) ((DOMCommentImpl*)fStartContainer)->splitText(fStartOffset); else if (type == DOMNode::PROCESSING_INSTRUCTION_NODE) ((DOMProcessingInstructionImpl*)fStartContainer)->splitText(fStartOffset); else ((DOMText*)fStartContainer)->splitText(fStartOffset); } //update the new start information later. After inserting the first newNode if (fStartOffset == 0) next = fStartContainer; else next = fStartContainer->getNextSibling(); } // end of text handling else { parent = fStartContainer; next = fStartContainer->getFirstChild(); for(XMLSize_t i = 0; (i < fStartOffset) && (next != 0); i++) { next=next->getNextSibling(); } } if (parent != 0) { if (next != 0) parent->insertBefore(newNode, next); else parent->appendChild(newNode); }}DOMRange* DOMRangeImpl::cloneRange() const{ if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } DOMRange* range = fDocument->createRange(); range->setStart(fStartContainer, fStartOffset); range->setEnd(fEndContainer, fEndOffset); return range;}const XMLCh* DOMRangeImpl::toString() const{ if( fDetached) { throw DOMException( DOMException::INVALID_STATE_ERR, 0, fMemoryManager); } if ((fStartContainer == fEndContainer) && (fEndOffset == fStartOffset)) return XMLUni::fgZeroLenString; DOMNode* node = fStartContainer; DOMNode* stopNode = fEndContainer; XMLBuffer retStringBuf(1023, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); short type = fStartContainer->getNodeType(); if((type == DOMNode::TEXT_NODE || type == DOMNode::CDATA_SECTION_NODE || type == DOMNode::COMMENT_NODE || type == DOMNode::PROCESSING_INSTRUCTION_NODE)) { if (fStartContainer == fEndContainer) { XMLCh* tempString; XMLCh temp[4000]; if ((fEndOffset-fStartOffset) >= 3999) tempString = (XMLCh*) fMemoryManager->allocate ( (fEndOffset - fStartOffset + 1) * sizeof(XMLCh) );//new XMLCh[fEndOffset-fStartOffset+1]; else tempString = temp; XMLString::subString(tempString, fStartContainer->getNodeValue(), fStartOffset, fEndOffset, ((DOMDocumentImpl *)fDocument)->getMemoryManager()); const XMLCh* retString = ((DOMDocumentImpl *)fDocument)->getPooledString(tempString); if ((fEndOffset-fStartOffset) >= 3999)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?