#ifndef JEZUK_SimpleDOM_ELEMENTBYTAGIMPL_H #define JEZUK_SimpleDOM_ELEMENTBYTAGIMPL_H #include namespace SimpleDOM { template class ElementByTagList : public DOM::NodeList_impl { public: ElementByTagList(DocumentImpl* ownerDoc, DOM::Node_impl* rootNode, const stringT& tagName) : DOM::NodeList_impl(), rootNode_(rootNode), ownerDoc_(ownerDoc), tagName_(tagName), useNamespace_(false), allNamespaces_(false), allNames_(false), changes_(0), refCount_(0) { string_adaptorT SA; allNames_ = (tagName_ == SA.makeStringT("*")); populate(); } // ElementByTagList ElementByTagList(DocumentImpl* ownerDoc, DOM::Node_impl* rootNode, const stringT& namespaceURI, const stringT& localName) : DOM::NodeList_impl(), rootNode_(rootNode), ownerDoc_(ownerDoc), namespaceURI_(namespaceURI), tagName_(localName), useNamespace_(true), allNamespaces_(false), allNames_(false), changes_(0), refCount_(0) { string_adaptorT SA; allNames_ = (tagName_ == SA.makeStringT("*")); allNamespaces_ = (namespaceURI_ == SA.makeStringT("*")); populate(); } // ElementByTagList virtual ~ElementByTagList() { } ////////////////////////////////////////////////// // Ref counting virtual void addRef() { ++refCount_; ownerDoc_->addRef(); } // addRef virtual void releaseRef() { ownerDoc_->releaseRef(); if(--refCount_ == 0) delete this; } // releaseRef ///////////////////////////////////////////////// // DOM::NodeList methods virtual DOM::Node_impl* item(unsigned int index) const { if(index >= nodes_.size()) return 0; if(changes_ != ownerDoc_->changes()) populate(); return nodes_[index]; } // item virtual unsigned int getLength() const { if(changes_ != ownerDoc_->changes()) populate(); return static_cast(nodes_.size()); } // getLength private: void populate() const { NodeListT dummy; nodes_.swap(dummy); checkNode(rootNode_); changes_ = ownerDoc_->changes(); } // populate void checkNode(DOM::Node_impl* node) const { if(useNamespace_) { if((node->hasNamespaceURI() && namespaceURI_ == node->getNamespaceURI()) || allNamespaces_) { if((tagName_ == node->getLocalName()) || (allNames_ && node->getNodeType() == DOM::Node::ELEMENT_NODE)) nodes_.push_back(node); } } else if((tagName_ == node->getNodeName()) || (allNames_ && node->getNodeType() == DOM::Node::ELEMENT_NODE)) nodes_.push_back(node); for(DOM::Node_impl* child = node->getFirstChild(); child != 0; child = child->getNextSibling()) if(child->getNodeType() == DOM::Node::ELEMENT_NODE) checkNode(child); } // checkNode typedef std::deque*> NodeListT; mutable NodeListT nodes_; DOM::Node_impl* rootNode_; DocumentImpl* ownerDoc_; stringT namespaceURI_; stringT tagName_; bool useNamespace_; bool allNamespaces_; bool allNames_; mutable unsigned int changes_; unsigned int refCount_; }; // class ElementByTagList } // namespace SimpleDOM #endif