diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp index 6dd541dd0389444556bb6caaa1cdfd09cd7b12de..2b49cd462288ccaae10e57e8b20d186d59169498 100644 --- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp +++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp @@ -118,6 +118,7 @@ DOMDocumentImpl::DOMDocumentImpl() fNamePool(0), fNodeIDMap(0), fRanges(0), + fNodeIterators(0), fChanges(0), fNodeListPool(0), fActualEncoding(0), @@ -148,6 +149,7 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI, fNamePool(0), fNodeIDMap(0), fRanges(0), + fNodeIterators(0), fChanges(0), fNodeListPool(0), fActualEncoding(0), @@ -207,6 +209,9 @@ DOMDocumentImpl::~DOMDocumentImpl() if (fRanges) fRanges->cleanup(); + if (fNodeIterators) + fNodeIterators->cleanup(); + if (fUserDataTable) fUserDataTable->cleanup(); @@ -386,12 +391,49 @@ DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data) DOMNodeIterator* DOMDocumentImpl::createNodeIterator ( DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion) { - return new (this) DOMNodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion); + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0); + return 0; + } + + DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion); + + if (fNodeIterators == 0L) { + fNodeIterators = new (this) NodeIterators(1, false); + } + fNodeIterators->addElement(nodeIterator); + + return nodeIterator; } +NodeIterators* DOMDocumentImpl::getNodeIterators() const +{ + return fNodeIterators; +} + +void DOMDocumentImpl::removeNodeIterator(DOMNodeIteratorImpl* nodeIterator) +{ + if (fNodeIterators != 0) { + XMLSize_t sz = fNodeIterators->size(); + if (sz !=0) { + for (XMLSize_t i =0; i<sz; i++) { + if (fNodeIterators->elementAt(i) == nodeIterator) { + fNodeIterators->removeElementAt(i); + break; + } + } + } + } +} + DOMTreeWalker* DOMDocumentImpl::createTreeWalker (DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion) { + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0); + return 0; + } + return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion); } diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.hpp b/src/xercesc/dom/impl/DOMDocumentImpl.hpp index 0f0b95a9ab55880912e9d83a479399f0cc7f4e7b..d052077ed51a3568e91d3cae57e7007b7d3fba71 100644 --- a/src/xercesc/dom/impl/DOMDocumentImpl.hpp +++ b/src/xercesc/dom/impl/DOMDocumentImpl.hpp @@ -112,6 +112,7 @@ class DOMStringPool; class DOMBuffer; typedef RefVectorOf<DOMRangeImpl> Ranges; +typedef RefVectorOf<DOMNodeIteratorImpl> NodeIterators; typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord; typedef RefHashTableOf<DOMUserDataRecord> DOMNodeUserDataTable; typedef RefStackOf<DOMNode> DOMNodePtr; @@ -190,7 +191,9 @@ public: virtual DOMRange* createRange(); virtual Ranges* getRanges() const; //non-standard api + virtual NodeIterators* getNodeIterators() const; //non-standard api virtual void removeRange(DOMRangeImpl* range); //non-standard api + virtual void removeNodeIterator(DOMNodeIteratorImpl* nodeIterator); //non-standard api // @@ -367,6 +370,7 @@ private: DOMStringPool* fNamePool; Ranges* fRanges; + NodeIterators* fNodeIterators; int fChanges; bool errorChecking; // Bypass error checking. diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp index cd2e8311b9da74398c64c7943c041c83a209e474..bcd8fb411ed63f7074f64d71340ffa6da931c6b7 100644 --- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp +++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp @@ -75,25 +75,7 @@ XERCES_CPP_NAMESPACE_BEGIN // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DOMNodeIteratorImpl::DOMNodeIteratorImpl () -: fDetached(false), - fNodeFilter(0) -{ -} - -DOMNodeIteratorImpl::~DOMNodeIteratorImpl () -{ - fDetached = false; -} - - -void DOMNodeIteratorImpl::detach () -{ - fDetached = true; -} - - -DOMNodeIteratorImpl::DOMNodeIteratorImpl ( +DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc, DOMNode* root, unsigned long whatToShow, DOMNodeFilter* nodeFilter, @@ -104,7 +86,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl ( fWhatToShow(whatToShow), fNodeFilter(nodeFilter), fForward(true), - fExpandEntityReferences(expandEntityRef) + fExpandEntityReferences(expandEntityRef), + fDocument(doc) { } @@ -117,7 +100,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy) fWhatToShow(toCopy.fWhatToShow), fNodeFilter(toCopy.fNodeFilter), fForward(toCopy.fForward), - fExpandEntityReferences(toCopy.fExpandEntityReferences) + fExpandEntityReferences(toCopy.fExpandEntityReferences), + fDocument(toCopy.fDocument) { } @@ -130,9 +114,23 @@ DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl& fForward = other.fForward; fDetached = other.fDetached; fExpandEntityReferences = other.fExpandEntityReferences; + fDocument = other.fDocument; return *this; } +DOMNodeIteratorImpl::~DOMNodeIteratorImpl () +{ + fDetached = false; +} + + +void DOMNodeIteratorImpl::detach () +{ + fDetached = true; + ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this); +} + + DOMNode* DOMNodeIteratorImpl::getRoot() { return fRoot; } diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp index 255a8410fac2614ed6514f9a5fda0afb3eec542e..578b229a66a600b2f7591bb4d6ec503614e1703a 100644 --- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp +++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp @@ -88,6 +88,9 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { // The root. DOMNode* fRoot; + // The Document used to create this iterator + DOMDocument* fDocument; + // The whatToShow mask. unsigned long fWhatToShow; @@ -120,12 +123,10 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { // </pre> bool fForward; - protected: - DOMNodeIteratorImpl (); - public: virtual ~DOMNodeIteratorImpl (); DOMNodeIteratorImpl ( + DOMDocument* fDocument, DOMNode* root, unsigned long whatToShow, DOMNodeFilter* nodeFilter, @@ -145,12 +146,12 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { virtual void detach (); virtual void release(); + void removeNode (DOMNode* node); private: DOMNode* matchNodeOrParent (DOMNode* node); DOMNode* nextNode (DOMNode* node, bool visitChildren); DOMNode* previousNode (DOMNode* node); - void removeNode (DOMNode* node); bool acceptNode (DOMNode* node); }; diff --git a/src/xercesc/dom/impl/DOMParentNode.cpp b/src/xercesc/dom/impl/DOMParentNode.cpp index bd3999137ad945763396022c258ee0f8608b2a28..f87c65c46b995614b6bf2ab7e354fe92efc1e0c2 100644 --- a/src/xercesc/dom/impl/DOMParentNode.cpp +++ b/src/xercesc/dom/impl/DOMParentNode.cpp @@ -65,6 +65,7 @@ #include "DOMDocumentImpl.hpp" #include "DOMNodeListImpl.hpp" #include "DOMRangeImpl.hpp" +#include "DOMNodeIteratorImpl.hpp" #include "DOMParentNode.hpp" #include "DOMCasts.hpp" @@ -310,8 +311,20 @@ DOMNode *DOMParentNode::removeChild(DOMNode *oldChild) if (oldChild != 0 && oldChild->getParentNode() != castToNode(this)) throw DOMException(DOMException::NOT_FOUND_ERR, 0); - //fix other ranges for change before deleting the node 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();