// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_xml_tree #define tools_xml_tree #include "element" #include "../S_STRING" #include "../forit" #include #include namespace tools { namespace xml { // A tree is : // // ... // // // ... // value // ... // // // tree.attribute_value(,s) // retrieve the value of atb of a // tree.attribute_value(,,s) // retrieve the value of an atb of a of a // class tree; class factory { public: virtual ~factory(){} public: typedef std::pair atb; public: virtual tree* create(const std::string& a_tag_name,const std::vector& a_atbs,tree* a_parent) = 0; }; class tree : public virtual ielem { public: TOOLS_SCLASS(tools::xml::tree) public: static cid id_class() {return 1;} virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} else return 0; } public: typedef std::pair atb; public: tree(const std::string& a_tag_name,factory& a_factory,tree* a_parent) :m_tag_name(a_tag_name) ,m_factory(a_factory) ,m_parent(a_parent) ,m_depth(0) { } virtual ~tree(){ clear(); } protected: tree(const tree& a_from) :ielem(a_from) ,m_tag_name(a_from.m_tag_name) ,m_factory(a_from.m_factory) ,m_parent(0) ,m_depth(0) { } tree& operator=(const tree&){return *this;} public: const std::list& childs() const {return m_childs;} /////////////////////////////////////////////////////// /// attributes //////////////////////////////////////// /////////////////////////////////////////////////////// void set_attributes(const std::vector& a_atbs) { m_atbs = a_atbs; } const std::string& tag_name() const {return m_tag_name;} bool attribute_value(const std::string& a_atb,std::string& a_value) const { a_value.clear(); size_t linen = m_atbs.size(); for(size_t count=0;count bool attribute_value(const std::string& a_atb,T& a_value) const { std::string sv; if(!attribute_value(a_atb,sv)) {a_value=T();return false;} return to(sv,a_value); } /////////////////////////////////////////////////////// /// elements ////////////////////////////////////////// /////////////////////////////////////////////////////// void add_element(const std::string& a_name,const std::vector& a_atbs,const std::string& a_value){ m_childs.push_back(new element(a_name,a_atbs,a_value)); } void add_child(tree* a_tree) {m_childs.push_back(a_tree);} /////////////////////////////////////////////////////// /// sub trees ///////////////////////////////////////// /////////////////////////////////////////////////////// tree* parent() const {return m_parent;} unsigned int number_of_trees() const { unsigned int number = 0; tools_lforcit(ielem*,m_childs,it) { if(id_cast(*(*it))) number++; } return number; } void remove_child(tree*& a_tree,bool a_delete = true){ m_childs.remove(a_tree); if(a_delete) { delete a_tree; a_tree = 0; } } void set_depth(unsigned int a_depth) {m_depth = a_depth;} unsigned int depth() const {return m_depth;} void set_file(const std::string& a_file) {m_file = a_file;} const std::string& file() const {return m_file;} protected: void clear(){ m_atbs.clear(); while(!m_childs.empty()) { ielem* item = m_childs.front(); m_childs.remove(item); delete item; } } protected: std::string m_tag_name; factory& m_factory; tree* m_parent; std::list m_childs; std::vector m_atbs; std::string m_file; int m_depth; }; class looper { public: looper(const tree& a_tree) :m_it(a_tree.childs().begin()) ,m_end(a_tree.childs().end()) {} virtual ~looper(){} protected: looper(const looper& a_from) :m_it(a_from.m_it) ,m_end(a_from.m_end) {} looper& operator=(const looper&){return *this;} public: tree* next_tree() { for(;m_it!=m_end;++m_it) { tree* _tree = id_cast(*(*m_it)); if(_tree) {m_it++;return _tree;} } return 0; } element* next_element() { for(;m_it!=m_end;++m_it) { element* _elem = id_cast(*(*m_it)); if(_elem) {m_it++;return _elem;} } return 0; } protected: std::list::const_iterator m_it; std::list::const_iterator m_end; }; class default_factory : public virtual factory { public: virtual tree* create(const std::string& a_tag_name,const std::vector& a_atbs,tree* a_parent) { // It does not add the new tree in parent. tree* itemML = new tree(a_tag_name,*this,a_parent); itemML->set_attributes(a_atbs); return itemML; } public: default_factory(){ } virtual ~default_factory(){ } public: default_factory(const default_factory& a_from) :factory(a_from){ } default_factory& operator=(const default_factory&){return *this;} }; }} #endif