domparentnode.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 423 行

CPP
423
字号
/* * Copyright 2001-2002,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: DOMParentNode.cpp,v 1.17 2004/09/08 13:55:52 peiyongz Exp $ */#include <xercesc/util/XercesDefs.hpp>#include <xercesc/dom/DOMException.hpp>#include <xercesc/dom/DOMNode.hpp>#include "DOMDocumentImpl.hpp"#include "DOMNodeListImpl.hpp"#include "DOMRangeImpl.hpp"#include "DOMNodeIteratorImpl.hpp"#include "DOMParentNode.hpp"#include "DOMCasts.hpp"XERCES_CPP_NAMESPACE_BEGINDOMParentNode::DOMParentNode(DOMDocument *ownerDoc)    : fOwnerDocument(ownerDoc), fFirstChild(0), fChildNodeList(castToNode(this)){    }// This only makes a shallow copy, cloneChildren must also be called for a// deep cloneDOMParentNode::DOMParentNode(const DOMParentNode &other)  :    fChildNodeList(castToNode(this)){    this->fOwnerDocument = other.fOwnerDocument;    // Need to break the association w/ original kids    this->fFirstChild = 0;}void DOMParentNode::changed(){    DOMDocumentImpl *doc = (DOMDocumentImpl *)this->getOwnerDocument();    doc->changed();}int DOMParentNode::changes() const{    DOMDocumentImpl *doc = (DOMDocumentImpl *)this->getOwnerDocument();    return doc->changes();}DOMNode * DOMParentNode::appendChild(DOMNode *newChild){    return insertBefore(newChild, 0);}void DOMParentNode::cloneChildren(const DOMNode *other) {  //    for (DOMNode *mykid = other.getFirstChild();    for (DOMNode *mykid = other->getFirstChild();         mykid != 0;         mykid = mykid->getNextSibling())    {        appendChild(mykid->cloneNode(true));    }}DOMDocument * DOMParentNode::getOwnerDocument() const {    return fOwnerDocument;}// unlike getOwnerDocument this is not overriden by DocumentImpl to return 0DOMDocument * DOMParentNode::getDocument() const {    return fOwnerDocument;}void DOMParentNode::setOwnerDocument(DOMDocument* doc) {    fOwnerDocument = doc;}DOMNodeList *DOMParentNode::getChildNodes() const {    const DOMNodeList *ret = &fChildNodeList;    return (DOMNodeList *)ret;   // cast off const.}DOMNode * DOMParentNode::getFirstChild() const {    return fFirstChild;}DOMNode * DOMParentNode::getLastChild() const{    return lastChild();}DOMNode * DOMParentNode::lastChild() const{    // last child is stored as the previous sibling of first child    if (fFirstChild == 0) {        return 0;    }    DOMChildNode *firstChild = castToChildImpl(fFirstChild);    DOMNode *ret = firstChild->previousSibling;    return ret;}////  revisit.  Is this function used anywhere?  I don't see it.//void DOMParentNode::lastChild(DOMNode *node) {    // store lastChild as previous sibling of first child    if (fFirstChild != 0) {        DOMChildNode *firstChild = castToChildImpl(fFirstChild);        firstChild->previousSibling = node;    }}bool DOMParentNode::hasChildNodes() const{    return fFirstChild!=0;}DOMNode *DOMParentNode::insertBefore(DOMNode *newChild, DOMNode *refChild) {    DOMNodeImpl *thisNodeImpl = castToNodeImpl(this);    if (thisNodeImpl->isReadOnly())        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager);    if (newChild->getOwnerDocument() != fOwnerDocument)        throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMParentNodeMemoryManager);    // Prevent cycles in the tree    //only need to do this if the node has children    if(newChild->hasChildNodes()) {        bool treeSafe=true;        for(DOMNode *a=castToNode(this)->getParentNode();            treeSafe && a!=0;            a=a->getParentNode())            treeSafe=(newChild!=a);        if(!treeSafe)            throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);    }    // refChild must in fact be a child of this node (or 0)    if (refChild!=0 && refChild->getParentNode() != castToNode(this))        throw DOMException(DOMException::NOT_FOUND_ERR,0, GetDOMParentNodeMemoryManager);    // if the new node has to be placed before itself, we don't have to do anything     // (even worse, we would crash if we continue, as we assume they are two distinct nodes)    if (refChild!=0 && newChild->isSameNode(refChild))        return newChild;    if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE)    {        // SLOW BUT SAFE: We could insert the whole subtree without        // juggling so many next/previous pointers. (Wipe out the        // parent's child-list, patch the parent pointers, set the        // ends of the list.) But we know some subclasses have special-        // case behavior they add to insertBefore(), so we don't risk it.        // This approch also takes fewer bytecodes.        // NOTE: If one of the children is not a legal child of this        // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children        // have been transferred. (Alternative behaviors would be to        // reparent up to the first failure point or reparent all those        // which are acceptable to the target node, neither of which is        // as robust. PR-DOM-0818 isn't entirely clear on which it        // recommends?????        // No need to check kids for right-document; if they weren't,        // they wouldn't be kids of that DocFrag.        for(DOMNode *kid=newChild->getFirstChild(); // Prescan              kid!=0;              kid=kid->getNextSibling())        {            if (!DOMDocumentImpl::isKidOK(castToNode(this), kid))              throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);        }        while(newChild->hasChildNodes())     // Move            insertBefore(newChild->getFirstChild(),refChild);    }    else if (!DOMDocumentImpl::isKidOK(castToNode(this), newChild))        throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager);    else    {        DOMNode *oldparent=newChild->getParentNode();        if(oldparent!=0)            oldparent->removeChild(newChild);        // Attach up        castToNodeImpl(newChild)->fOwnerNode = castToNode(this);        castToNodeImpl(newChild)->isOwned(true);        // Attach before and after        // Note: fFirstChild.previousSibling == lastChild!!        if (fFirstChild == 0) {            // this our first and only child            fFirstChild = newChild;            castToNodeImpl(newChild)->isFirstChild(true);            // castToChildImpl(newChild)->previousSibling = newChild;            DOMChildNode *newChild_ci = castToChildImpl(newChild);            newChild_ci->previousSibling = newChild;        } else {            if (refChild == 0) {                // this is an append                DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling;                castToChildImpl(lastChild)->nextSibling = newChild;                castToChildImpl(newChild)->previousSibling = lastChild;                castToChildImpl(fFirstChild)->previousSibling = newChild;            } else {                // this is an insert                if (refChild == fFirstChild) {                    // at the head of the list                    castToNodeImpl(fFirstChild)->isFirstChild(false);                    castToChildImpl(newChild)->nextSibling = fFirstChild;                    castToChildImpl(newChild)->previousSibling = castToChildImpl(fFirstChild)->previousSibling;                    castToChildImpl(fFirstChild)->previousSibling = newChild;                    fFirstChild = newChild;                    castToNodeImpl(newChild)->isFirstChild(true);                } else {                    // somewhere in the middle                    DOMNode *prev = castToChildImpl(refChild)->previousSibling;                    castToChildImpl(newChild)->nextSibling = refChild;                    castToChildImpl(prev)->nextSibling = newChild;                    castToChildImpl(refChild)->previousSibling = newChild;                    castToChildImpl(newChild)->previousSibling = prev;                }            }        }    }    changed();    if (this->getOwnerDocument() != 0) {        Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();        if ( ranges != 0) {            XMLSize_t sz = ranges->size();            if (sz != 0) {                for (XMLSize_t i =0; i<sz; i++) {                    ranges->elementAt(i)->updateRangeForInsertedNode(newChild);                }            }        }    }    return newChild;}DOMNode *DOMParentNode::removeChild(DOMNode *oldChild){    if (castToNodeImpl(this)->isReadOnly())        throw DOMException(        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager);    if (oldChild == 0 || oldChild->getParentNode() != castToNode(this))        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMParentNodeMemoryManager);    if (this->getOwnerDocument() !=  0  ) {        //notify iterators        NodeIterators* nodeIterators = ((DOMDocumentImpl *)this->getOwnerDocument())->getNodeIterators();        if (nodeIterators != 0) {            XMLSize_t sz = nodeIterators->size();            if (sz != 0) {                for (XMLSize_t i =0; i<sz; i++) {                    if (nodeIterators->elementAt(i) != 0)                        nodeIterators->elementAt(i)->removeNode(oldChild);                }            }        }        //fix other ranges for change before deleting the node        Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges();        if (ranges != 0) {            XMLSize_t sz = ranges->size();            if (sz != 0) {                for (XMLSize_t i =0; i<sz; i++) {                    if (ranges->elementAt(i) != 0)                        ranges->elementAt(i)->updateRangeForDeletedNode(oldChild);                }            }        }    }    // Patch linked list around oldChild    // Note: lastChild == fFirstChild->previousSibling    if (oldChild == fFirstChild) {        // removing first child        castToNodeImpl(oldChild)->isFirstChild(false);        fFirstChild = castToChildImpl(oldChild)->nextSibling;        if (fFirstChild != 0) {            castToNodeImpl(fFirstChild)->isFirstChild(true);            castToChildImpl(fFirstChild)->previousSibling = castToChildImpl(oldChild)->previousSibling;        }    } else {        DOMNode *prev = castToChildImpl(oldChild)->previousSibling;        DOMNode *next = castToChildImpl(oldChild)->nextSibling;        castToChildImpl(prev)->nextSibling = next;        if (next == 0) {            // removing last child            castToChildImpl(fFirstChild)->previousSibling = prev;        } else {            // removing some other child in the middle            castToChildImpl(next)->previousSibling = prev;        }    }    // Remove oldChild's references to tree    castToNodeImpl(oldChild)->fOwnerNode = fOwnerDocument;    castToNodeImpl(oldChild)->isOwned(false);    castToChildImpl(oldChild)->nextSibling = 0;    castToChildImpl(oldChild)->previousSibling = 0;    changed();    return oldChild;}DOMNode *DOMParentNode::replaceChild(DOMNode *newChild, DOMNode *oldChild){    insertBefore(newChild, oldChild);    // changed() already done.    return removeChild(oldChild);}//Introduced in DOM Level 2void DOMParentNode::normalize(){    DOMNode *kid, *next;    for (kid = fFirstChild; kid != 0; kid = next)    {        next = castToChildImpl(kid)->nextSibling;        // If kid and next are both Text nodes (but _not_ CDATASection,        // which is a subclass of Text), they can be merged.        if (next != 0 &&            kid->getNodeType() == DOMNode::TEXT_NODE   &&            next->getNodeType() == DOMNode::TEXT_NODE )        {            ((DOMTextImpl *) kid)->appendData(((DOMTextImpl *) next)->getData());            // revisit:            //   should I release the removed node?            //   not released in case user still referencing it externally            removeChild(next);            next = kid; // Don't advance; there might be another.        }        // Otherwise it might be an Element, which is handled recursively        else            if (kid->getNodeType() == DOMNode::ELEMENT_NODE)                kid->normalize();    }    // changed() will have occurred when the removeChild() was done,    // so does not have to be reissued.}//Introduced in DOM Level 3bool DOMParentNode::isEqualNode(const DOMNode* arg) const{    if (arg && castToNodeImpl(this)->isSameNode(arg))        return true;    if (arg && castToNodeImpl(this)->isEqualNode(arg))    {        DOMNode *kid, *argKid;        for (kid = fFirstChild, argKid = arg->getFirstChild();             kid != 0 && argKid != 0;             kid = kid->getNextSibling(), argKid = argKid->getNextSibling())        {            if (!kid->isEqualNode(argKid))                return false;        }        return (kid || argKid) ? false : true;    }    return false;}//Non-standard extensionvoid DOMParentNode::release(){    DOMNode *kid, *next;    for (kid = fFirstChild; kid != 0; kid = next)    {        next = castToChildImpl(kid)->nextSibling;        // set is Owned false before releasing its child        castToNodeImpl(kid)->isToBeReleased(true);        kid->release();    }}XERCES_CPP_NAMESPACE_END

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?