Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/xml/tree is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_xml_tree
0005 #define tools_xml_tree
0006 
0007 #include "element"
0008 
0009 #include "../sout"
0010 #include "../strip"
0011 #include "../S_STRING"
0012 #include "../forit"
0013 
0014 #include <list>
0015 #include <ostream>
0016 
0017 namespace tools {
0018 namespace xml {
0019 
0020 //  A tree is :
0021 //    <tree atb1="" atb2="" ...>
0022 //      ...
0023 //      <tree...>
0024 //      </tree>
0025 //      ...
0026 //      <element atb1="" atb2="" ...> value </element>
0027 //      ...
0028 //    </tree>
0029 //
0030 //   tree.attribute_value(<name>,s)
0031 //     retrieve the value of atb <name> of a <tag>
0032 //   tree.attribute_value(<element>,<name>,s)
0033 //     retrieve the value of an atb <name> of a <element> of a <tree>
0034 //
0035 
0036 class tree;
0037 
0038 class factory {
0039 public:
0040   virtual ~factory(){}
0041 public:
0042   typedef std::pair<std::string,std::string> atb;
0043 public:
0044   virtual tree* create(const std::string& a_tag_name,const std::vector<atb>& a_atbs,tree* a_parent) = 0;
0045 };
0046 
0047 class tree : public virtual ielem {
0048 public:
0049   TOOLS_SCLASS(tools::xml::tree)
0050 public:
0051   static cid id_class() {return 1;}
0052   virtual void* cast(cid a_class) const {
0053     if(void* p = cmp_cast<tree>(this,a_class)) {return p;}
0054     else return 0;
0055   }
0056 public:
0057   typedef std::pair<std::string,std::string> atb;
0058   typedef bool (*exec_func)(tree&,void*);
0059   enum copy_what { copy_attributes, copy_elements, copy_children, copy_all };
0060 public:
0061   tree(const std::string& a_tag_name,factory& a_factory,tree* a_parent)
0062   :m_tag_name(a_tag_name)
0063   ,m_factory(a_factory)
0064   ,m_parent(a_parent)
0065   ,m_save(true)
0066   ,m_data_1(0)
0067   ,m_data_2(0)
0068   ,m_data_int(0)
0069   ,m_depth(0)
0070   {
0071 #ifdef TOOLS_MEM
0072     mem::increment(s_class().c_str());
0073 #endif
0074   }
0075 
0076   virtual ~tree(){
0077     clear();
0078 #ifdef TOOLS_MEM
0079     mem::decrement(s_class().c_str());
0080 #endif
0081   }
0082 
0083 protected:
0084   tree(const tree& a_from)
0085   :ielem(a_from)
0086   ,m_tag_name(a_from.m_tag_name)
0087   ,m_factory(a_from.m_factory)
0088   ,m_parent(0)
0089   ,m_save(0)
0090   ,m_data_1(0)
0091   ,m_data_2(0)
0092   ,m_data_int(0)
0093   ,m_depth(0)
0094   {
0095 #ifdef TOOLS_MEM
0096     mem::increment(s_class().c_str());
0097 #endif
0098   }
0099 
0100   tree& operator=(const tree&){return *this;}
0101 
0102 public:
0103   virtual bool invalidate() {return true;}
0104 
0105   const std::list<ielem*>& childs() const {return m_childs;}
0106 
0107   ///////////////////////////////////////////////////////
0108   /// attributes ////////////////////////////////////////
0109   ///////////////////////////////////////////////////////
0110   const std::vector<atb>& attributes() const {return m_atbs;}
0111 
0112   void add_attribute(const std::string& a_name,const std::string& a_value){
0113     // No check is done about an existing a_name.
0114     m_atbs.push_back(atb(a_name,a_value));
0115   }
0116 
0117   bool is_attribute(const std::string& a_name) const {
0118     size_t number = m_atbs.size();
0119     for(size_t index=0;index<number;index++) {
0120       if(m_atbs[index].first==a_name) return true;
0121     }
0122     return false;
0123   }
0124 
0125   void set_attributes(const std::vector<atb>& a_atbs) {
0126     m_atbs = a_atbs;
0127   }
0128   const std::string& tag_name() const {return m_tag_name;}
0129 
0130   bool attribute_value(const std::string& a_atb,std::string& a_value) const {
0131     a_value.clear();
0132     size_t linen = m_atbs.size();
0133     for(size_t count=0;count<linen;count++) {
0134       if(m_atbs[count].first==a_atb) {
0135         a_value = m_atbs[count].second;
0136         return true;
0137       }
0138     }
0139     return false;
0140   }
0141 
0142   template <class T>
0143   bool attribute_value(const std::string& a_atb,T& a_value) const {
0144     std::string sv;
0145     if(!attribute_value(a_atb,sv)) {a_value=T();return false;}
0146     return to<T>(sv,a_value);
0147   }
0148 
0149   void remove_attributes(const std::string& a_atb) {
0150     std::vector<atb>::iterator it;
0151     for(it=m_atbs.begin();it!=m_atbs.end();) {
0152       if((*it).first==a_atb) {
0153         it = m_atbs.erase(it);
0154       } else {
0155         ++it;
0156       }
0157     }
0158   }
0159 
0160   bool remove_attribute(const std::string& a_name){
0161     //TOOLS_STL : to be checked :
0162     std::vector<atb>::iterator it = m_atbs.begin();
0163     size_t linen = m_atbs.size();
0164     for(size_t count=0;count<linen;count++,++it) {
0165       if(m_atbs[count].first==a_name) {
0166         m_atbs.erase(it);
0167         return true; //Found and removed.
0168       }
0169     }
0170     return false; //Not found.
0171   }
0172 
0173   ///////////////////////////////////////////////////////
0174   /// elements //////////////////////////////////////////
0175   ///////////////////////////////////////////////////////
0176   void add_element(const std::string& a_name,const std::vector<atb>& a_atbs,const std::string& a_value){
0177     m_childs.push_back(new element(a_name,a_atbs,a_value));
0178   }
0179 
0180   bool element_value(const std::string& a_name,std::string& a_value) const {
0181     tools_lforcit(ielem*,m_childs,it) {
0182       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0183         if(a_name==_elem->name()) {
0184           a_value = _elem->value();
0185           return true;
0186         }
0187       }
0188     }
0189     a_value.clear();
0190     return false;
0191   }
0192 
0193 /*
0194   //NOTE : print is a Python keyword.
0195   void dump(std::ostream& a_out){
0196     a_out << "dump :"
0197           << " -----> " << this << " parent : " << m_parent << std::endl;
0198     a_out << " data1 : " << m_data_1
0199           << " data2 : " << m_data_2
0200           << " dataInt : " << m_data_int
0201           << std::endl;
0202 
0203    {size_t atbn = m_atbs.size();
0204     for(size_t index=0;index<atbn;index++) {
0205       a_out << " attribute : " << sout(m_atbs[index].first) << " "
0206             << sout(m_atbs[index].second) << std::endl;
0207     }}
0208 
0209    {tools_lforit(element*,m_elems,it) {
0210       a_out << " element : \"" << (*it)->name() << "\" \""
0211             << (*it)->value() << "\"" << std::endl;
0212     }}
0213 
0214    {tools_lforit(tree*,m_children,it) {
0215       (*it)->dump(a_out);
0216     }}
0217   }
0218 
0219   const std::list<element*>& elements() const {return m_elems;}
0220 
0221 */
0222 
0223   bool element_atb_value(const std::string& a_elem,const std::string& a_atb,std::string& a_value) const {
0224     a_value.clear();
0225     tools_lforcit(ielem*,m_childs,it) {
0226       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0227         if(a_elem==_elem->name()) {
0228           if(_elem->attribute_value(a_atb,a_value)) return true;
0229         }
0230       }
0231     }
0232     return false;
0233   }
0234 
0235   template <class T>
0236   bool element_atb_value(const std::string& a_elem,const std::string& a_atb,T& a_value) const {
0237     std::string sv;
0238     if(!element_atb_value(a_elem,a_atb,sv)) {a_value=T();return false;}
0239     return to<T>(sv,a_value);
0240   }
0241 
0242   //////////////////////////////////////////////////
0243   /// for osc //////////////////////////////////////
0244   //////////////////////////////////////////////////
0245   bool is_element(const std::string& a_name) const {
0246     tools_lforcit(ielem*,m_childs,it) {
0247       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0248         if(a_name==_elem->name()) return true;
0249       }
0250     }
0251     return false;
0252   }
0253 
0254   bool set_element_value(const std::string& a_name,const std::string& a_value,int a_index = 0){
0255     int index = 0;
0256     tools_lforcit(ielem*,m_childs,it) {
0257       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0258         if(a_name==_elem->name()) {
0259           if(index==a_index) {
0260             _elem->set_value(a_value);
0261             return true;
0262           } else {
0263             index ++;
0264           }
0265         }
0266       }
0267     }
0268     // Not found, add one :
0269     std::vector<atb> atts;
0270     add_element(a_name,atts,a_value);
0271     return true;
0272   }
0273 
0274   bool set_attribute_value(const std::string& a_atb,const std::string& a_value) {
0275     tools_vforit(atb,m_atbs,it) {
0276       if((*it).first==a_atb) {
0277         (*it).second = a_value;
0278         return true;
0279       }
0280     }
0281     // Not found, add one :
0282     m_atbs.push_back(atb(a_atb,a_value));
0283     return true;
0284   }
0285 
0286   bool has_empty_attribute_value(std::ostream& a_out) const{
0287     empty_visitor visitor(a_out);
0288     visitor.m_status = true;
0289     const_cast<tree*>(this)->post_execute(check_item,&visitor);
0290     return visitor.m_status;
0291   }
0292 
0293   class empty_visitor {
0294   public:
0295     empty_visitor(std::ostream& a_out)
0296     :f_out(a_out),m_status(true){}
0297   public:
0298     std::ostream& f_out;
0299     bool m_status;
0300   };
0301 
0302   void post_execute(exec_func a_function,void* a_tag) {
0303     if(!a_function) return;
0304 
0305     if(!a_function(*this,a_tag)) return;
0306 
0307     tools_lforcit(ielem*,m_childs,it) {
0308       if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0309         _tree->post_execute(a_function,a_tag);
0310       }
0311     }
0312   }
0313 
0314   static bool check_item(tree& a_tree,void* a_tag){
0315     empty_visitor* visitor = (empty_visitor*)a_tag;
0316 
0317    {const std::vector<atb>& atbs = a_tree.attributes();
0318     size_t atbn = atbs.size();
0319     for(size_t index=0;index<atbn;index++) {
0320       const std::string& _atb = atbs[index].first;
0321       const std::string& atbv = atbs[index].second;
0322       if(atbv.empty()) {
0323         visitor->f_out << "check_item :"
0324             << " for XML item " << sout(a_tree.tag_name())
0325             << ", attribute " << sout(_atb) << " has an empty value."
0326             << std::endl;
0327         visitor->m_status = false;
0328       }
0329     }}
0330 
0331    {tools_lforcit(ielem*,a_tree.m_childs,it) {
0332     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0333       const std::vector<atb>& atbs = _elem->attributes();
0334       size_t atbn = atbs.size();
0335       for(size_t index=0;index<atbn;index++) {
0336         const std::string& _atb = atbs[index].first;
0337         const std::string& atbv = atbs[index].second;
0338         if(atbv.empty()) {
0339           visitor->f_out << "ItemM::check_item :"
0340               << " for XML item " << sout(a_tree.tag_name())
0341               << ", attribute " << sout(_atb) << " has an empty value."
0342               << std::endl;
0343           visitor->m_status = false;
0344         }
0345       }
0346     }}}
0347 
0348     return true;
0349   }
0350 
0351   static void collect_by_tag(tree& a_tree,const std::string& a_tag,std::vector<tree*>& a_items) {
0352     if(a_tree.tag_name()==a_tag) a_items.push_back(&a_tree);
0353     tools_lforcit(ielem*,a_tree.m_childs,it) {
0354       if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0355         collect_by_tag(*_tree,a_tag,a_items);
0356       }
0357     }
0358   }
0359 
0360   tree* find_by_tag(const std::string& a_tag) const {
0361     if(tag_name()==a_tag) return const_cast<tree*>(this);
0362     // Look children :
0363     tools_lforcit(ielem*,m_childs,it) {
0364     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0365       tree* itemML = _tree->find_by_tag(a_tag);
0366       if(itemML) return itemML;
0367     }}
0368     return 0;
0369   }
0370 
0371   static void unique(std::vector<tree*>& a_items) {
0372     std::vector<tree*> items2;
0373 
0374     tools_vforcit(tree*,a_items,it) {
0375       std::string name;
0376       if(!(*it)->attribute_value("name",name)) continue;
0377       if(name.empty()) continue;
0378 
0379       bool found = false;
0380      {tools_vforit(tree*,items2,it2) {
0381         std::string name2;
0382         (*it2)->attribute_value("name",name2);
0383         if(name2==name) {
0384           found = true;
0385           break;
0386         }
0387       }}
0388       if(!found) {
0389         items2.push_back(*it);
0390       }
0391     }
0392 
0393     a_items = items2;
0394   }
0395 
0396   tree* find_item(const std::string& a_name) const {
0397    {size_t linen = m_atbs.size();
0398     for(unsigned int count=0;count<linen;count++) {
0399       if(m_atbs[count].first=="name") {
0400         if(m_atbs[count].second==a_name) return const_cast<tree*>(this);
0401         break;
0402       }
0403     }}
0404 
0405     // Look children :
0406     tools_lforcit(ielem*,m_childs,it) {
0407     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0408       tree* item = _tree->find_item(a_name);
0409       if(item) return item;
0410     }}
0411     return 0;
0412   }
0413 
0414   tree* find_item_with_tag(const std::string& a_tag,
0415                            const std::string& a_name) const {
0416     if(a_tag==tag_name()) {
0417       std::string _s;
0418       attribute_value("name",_s);
0419       if(a_name==_s) return const_cast<tree*>(this);
0420     }
0421 
0422     // Look children :
0423     tools_lforcit(ielem*,m_childs,it) {
0424     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0425       tree* item = _tree->find_item_with_tag(a_tag,a_name);
0426       if(item) return item;
0427     }}
0428     return 0;
0429   }
0430 
0431   void remove_elements(const std::string& a_name){
0432     // TOOLS_STL : to be checked :
0433     std::list<ielem*>::iterator it;
0434     for(it=m_childs.begin();it!=m_childs.end();) {
0435       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0436         if(a_name==_elem->name()) {
0437           it = m_childs.erase(it);
0438           delete _elem;
0439         } else {
0440           ++it;
0441         }
0442       } else {
0443         ++it;
0444       }
0445     }
0446   }
0447 
0448   void add_child(tree* a_tree) {m_childs.push_back(a_tree);}
0449 
0450   tree* create_copy(tree* a_parent) {
0451     tree* itemML = m_factory.create(m_tag_name,m_atbs,a_parent);
0452     if(!itemML) return 0;
0453     itemML->m_atbs = m_atbs;
0454     //FIXME : m_save
0455 
0456    {tools_lforcit(ielem*,m_childs,it) {
0457     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0458       itemML->m_childs.push_back(new element(*_elem));
0459     }}}
0460 
0461    {tools_lforcit(ielem*,m_childs,it) {
0462     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0463       //FIXME : could we have mismatch parent/child ?
0464       tree* obj = _tree->create_copy(itemML);
0465       if(!obj) {
0466         delete itemML;
0467         return 0;
0468       }
0469       itemML->add_child(obj);
0470     }}}
0471 
0472     return itemML;
0473   }
0474 
0475   bool copy(const tree& a_from,
0476             copy_what a_what = copy_all,
0477             bool a_clear = true){
0478 
0479     // Copy data (atbs, propertis, children) of a_from onto this.
0480     if((a_what==copy_all)||(a_what==copy_attributes)) {
0481       if(a_clear) m_atbs.clear();
0482       tools_vforcit(atb,a_from.m_atbs,it) m_atbs.push_back(*it);
0483     }
0484 
0485     if((a_what==copy_all)||(a_what==copy_elements)) {
0486       if(a_clear) delete_sub_elems();
0487       tools_lforcit(ielem*,a_from.m_childs,it) {
0488         if(element* _elem = id_cast<ielem,element>(*(*it))) {
0489           m_childs.push_back(new element(*_elem));
0490         }
0491       }
0492     }
0493 
0494     if((a_what==copy_all)||(a_what==copy_children)) {
0495       if(a_clear) delete_sub_trees();
0496       tools_lforcit(ielem*,a_from.m_childs,it) {
0497         if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0498           //FIXME : could we have mismatch parent/child ?
0499           tree* obj = _tree->create_copy(this);
0500           if(!obj) {
0501             // Something wrong, cleanup this.
0502             clear();
0503             return false;
0504           }
0505           add_child(obj);
0506         }
0507       }
0508     }
0509 
0510     //FIXME : m_save
0511 
0512     return true;
0513   }
0514 
0515 
0516   void replace(const std::string& a_old,const std::string& a_new) {
0517     // Used by the obuild template system.
0518    {size_t atbn = m_atbs.size();
0519     for(size_t index=0;index<atbn;index++) {
0520       std::string& value = m_atbs[index].second;
0521       replace_(value,a_old,a_new);
0522     }}
0523 
0524     tools_lforit(ielem*,m_childs,it) {
0525       if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0526         _tree->replace(a_old,a_new);
0527       } else if(element* _elem = id_cast<ielem,element>(*(*it))) {
0528         _elem->replace(a_old,a_new);
0529       }
0530     }
0531   }
0532 
0533   static void collect_by_attribute(tree& a_tree,
0534                                    const std::string& a_tag,
0535                                    std::vector<tree*>& a_items) {
0536     std::string value;
0537     if(a_tree.attribute_value(a_tag,value)) a_items.push_back(&a_tree);
0538     tools_lforcit(ielem*,a_tree.m_childs,it) {
0539       if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0540         collect_by_attribute(*_tree,a_tag,a_items);
0541       }
0542     }
0543   }
0544 
0545   bool element_values(const std::string& a_name,
0546                       std::vector<std::string>& a_values) const {
0547     a_values.clear();
0548     tools_lforcit(ielem*,m_childs,it) {
0549       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0550         if(a_name==_elem->name()) {
0551           a_values.push_back(_elem->value());
0552         }
0553       }
0554     }
0555     return true;
0556   }
0557 
0558   void post_execute_backward(exec_func a_function,void* a_tag){
0559     if(!a_function) return;
0560     tools_lforcit(ielem*,m_childs,it) {
0561       if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0562         _tree->post_execute_backward(a_function,a_tag);
0563       }
0564     }
0565     if(!a_function(*this,a_tag)) return;
0566   }
0567 
0568   tree* find_by_attribute(const std::string& a_atb,const std::string& a_value,
0569                         bool a_up_down = true,bool a_left_right = true) const {
0570     if(a_up_down) {
0571       std::string _s;
0572       attribute_value(a_atb,_s);
0573       if(_s==a_value) return const_cast<tree*>(this);
0574 
0575       if(a_left_right) {
0576         tools_lforcit(ielem*,m_childs,it) {
0577           if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0578             tree* itemML =
0579               _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0580             if(itemML) return itemML;
0581           }
0582         }
0583       } else {
0584         std::list<ielem*>::const_reverse_iterator it;
0585         for(it=m_childs.rbegin();it!=m_childs.rend();++it) {
0586         if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0587           tree* itemML =
0588             _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0589           if(itemML) return itemML;
0590         }}
0591       }
0592     } else {
0593       if(a_left_right) {
0594         tools_lforcit(ielem*,m_childs,it) {
0595         if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0596           tree* itemML =
0597             _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0598           if(itemML) return itemML;
0599         }}
0600       } else {
0601         std::list<ielem*>::const_reverse_iterator it;
0602         for(it=m_childs.rbegin();it!=m_childs.rend();++it) {
0603         if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0604           tree* itemML =
0605             _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0606           if(itemML) return itemML;
0607         }}
0608       }
0609 
0610       std::string _s;
0611       attribute_value(a_atb,_s);
0612       if(_s==a_value) return const_cast<tree*>(this);
0613 
0614     }
0615     return 0;
0616   }
0617 
0618   void dump_xml(std::ostream& a_out,const std::string& a_spaces = "") {
0619 
0620     // begin tag :
0621     a_out << a_spaces << "<" << m_tag_name;
0622    {size_t atbn = m_atbs.size();
0623     for(size_t index=0;index<atbn;index++) {
0624       a_out << " " << m_atbs[index].first << "="
0625             << sout(m_atbs[index].second);
0626     }}
0627     a_out << ">" << std::endl;
0628 
0629    {tools_lforcit(ielem*,m_childs,it) {
0630     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0631 
0632       const std::vector<atb>& atbs = _elem->attributes();
0633 
0634       bool isCallback = false;
0635 
0636       a_out << a_spaces << "  <" << _elem->name();
0637       size_t atbn = atbs.size();
0638       for(size_t index=0;index<atbn;index++) {
0639         a_out << " " << atbs[index].first << "="
0640               << sout(atbs[index].second);
0641         if(atbs[index].first=="exec") isCallback = true;
0642       }
0643       if(_elem->value().empty()) {
0644         a_out << "/>" << std::endl;
0645       } else {
0646         a_out << ">";
0647         std::string value = to_xml(_elem->value());
0648         if(isCallback) {
0649           if(value.find("\\n\\")==std::string::npos) {
0650             a_out << value;
0651           } else {
0652             a_out << std::endl;
0653             replace_(value,"\\n\\","@OnX@");
0654             replace_(value,"@OnX@","\\n\\\n");
0655             strip(value,trailing,' ');
0656             a_out << value;
0657             size_t l = value.size();
0658             if(l && value[l-1]!='\n') a_out << std::endl;
0659             a_out << a_spaces << "  ";
0660           }
0661         } else {
0662           a_out << value;
0663         }
0664         a_out << "</" << _elem->name() << ">" << std::endl;
0665       }
0666     }}}
0667 
0668     // End tag :
0669     a_out << a_spaces << "</" << m_tag_name << ">" << std::endl;
0670   }
0671 
0672   bool set_element_atb_value(const std::string& a_elem,
0673                             const std::string& a_atb,
0674                             const std::string& a_value,int a_index = 0){
0675     if(a_elem.empty()) {
0676       size_t linen = m_atbs.size();
0677       for(size_t count=0;count<linen;count++) {
0678         if(m_atbs[count].first==a_atb) {
0679           m_atbs[count].second = a_value;
0680           return true;
0681         }
0682       }
0683       // Not found, add it :
0684       m_atbs.push_back(atb(a_atb,a_value));
0685       return true;
0686     } else {
0687       int index = 0;
0688       tools_lforcit(ielem*,m_childs,it) {
0689       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0690         if(a_elem==_elem->name()) {
0691           if(index==a_index) {
0692             _elem->set_attribute_value(a_atb,a_value);
0693             return true;
0694           } else {
0695             index++;
0696           }
0697         }
0698       }}
0699       return false;
0700     }
0701   }
0702 
0703   // NOTE : used in osc. Should be removed.
0704   void sub_trees(std::list<tree*>& a_list) const {
0705     a_list.clear();
0706     tools_lforcit(ielem*,m_childs,it) {
0707     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0708       a_list.push_back(_tree);
0709     }}
0710   }
0711   void sub_elems(std::list<element*>& a_list) const {
0712     a_list.clear();
0713     tools_lforcit(ielem*,m_childs,it) {
0714     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0715       a_list.push_back(_elem);
0716     }}
0717   }
0718 
0719   bool replace_child(tree* a_old,tree* a_new) {
0720     tools_lforit(ielem*,m_childs,it) {
0721     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0722       if(_tree==a_old) {
0723         (*it) = a_new;
0724         return true; //replacement done.
0725       }
0726     }}
0727     return false; //no replacement done.
0728   }
0729 
0730   // used in OnX/Widget.
0731   virtual void* cast(const std::string& a_class) const {
0732     if(void* p = cmp_cast<tree>(this,a_class)) {return p;}
0733     else return 0;
0734   }
0735 
0736   void delete_element(const std::string& a_name) {
0737     tools_lforit(ielem*,m_childs,it) {
0738     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0739       if(a_name==_elem->name()) {
0740         m_childs.erase(it);
0741         delete _elem;
0742         break;
0743       }
0744     }}
0745   }
0746 
0747   void delete_element(element* a_element) {
0748     tools_lforit(ielem*,m_childs,it) {
0749     if(element* _elem = id_cast<ielem,element>(*(*it))) {
0750       if(_elem==a_element) {
0751         m_childs.erase(it);
0752         delete _elem;
0753         break;
0754       }
0755     }}
0756   }
0757 
0758   void delete_sub_trees(){
0759     std::list<ielem*>::iterator it;
0760     for(it=m_childs.begin();it!=m_childs.end();) {
0761        if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0762          it = m_childs.erase(it);
0763          delete _tree;
0764        } else {
0765          it++;
0766        }
0767     }
0768   }
0769 
0770   void delete_sub_elems(){
0771     std::list<ielem*>::iterator it;
0772     for(it=m_childs.begin();it!=m_childs.end();) {
0773       if(element* _elem = id_cast<ielem,element>(*(*it))) {
0774         it = m_childs.erase(it);
0775         delete _elem;
0776       } else {
0777         it++;
0778       }
0779     }
0780   }
0781 
0782   const tree* find_by_element_in_same_level(const std::string& a_name,
0783                                             const std::string& a_value) const {
0784     // Look children :
0785     tools_lforcit(ielem*,m_childs,it) {
0786     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0787       std::string _s;
0788       if(_tree->element_value(a_name,_s) && (a_value==_s)) return _tree;
0789     }}
0790     return 0;
0791   }
0792 
0793   bool element_value_boolean(const std::string& a_name,bool& a_value) const {
0794     std::string value;
0795     if(!element_value(a_name,value)) return false;
0796     return to(value,a_value);
0797   }
0798 
0799   void update_tree(const tree& a_old) {
0800     // We map the opened elements in the old tree within this tree.
0801     // Algorithm based on the existence of a "label" element.
0802     tools_lforit(ielem*,m_childs,it) {
0803     if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0804       std::string slabel;
0805       if(_tree->element_value("label",slabel)) {
0806         // Try to find a same label in the same level :
0807         const tree* item =
0808           a_old.find_by_element_in_same_level("label",slabel);
0809         if(item) {
0810           bool sopened;
0811           if(item->element_value_boolean("opened",sopened) && sopened) {
0812             _tree->set_element_value("opened","true");
0813           }
0814           if(a_old.number_of_trees()) _tree->update_tree(*item);
0815         }
0816       }
0817     }}
0818   }
0819 
0820   //////////////////////////////////////////////////
0821   /// end osc //////////////////////////////////////
0822   //////////////////////////////////////////////////
0823 
0824   ///////////////////////////////////////////////////////
0825   /// sub trees /////////////////////////////////////////
0826   ///////////////////////////////////////////////////////
0827 
0828   tree* parent() const {return m_parent;}
0829 
0830   void set_parent(tree* a_parent) {m_parent = a_parent;}
0831 
0832   unsigned int number_of_trees() const {
0833     unsigned int number = 0;
0834     tools_lforcit(ielem*,m_childs,it) {
0835       if(id_cast<ielem,tree>(*(*it))) number++;
0836     }
0837     return number;
0838   }
0839 
0840   void remove_child(tree*& a_tree,bool a_delete = true){
0841     m_childs.remove(a_tree);
0842     if(a_delete) {
0843       delete a_tree;
0844       a_tree = 0;
0845     }
0846   }
0847 
0848 /*
0849 
0850   bool is_first_child(const tree& a_tree) {
0851     if(m_children.empty()) return false;
0852     return ( (*(m_children.begin()))==&a_tree) ? true : false;
0853   }
0854 
0855   bool is_last_child(const tree& a_tree) {
0856     if(m_children.empty()) return false;
0857     return ( m_children.back()==&a_tree) ? true : false;
0858   }
0859 */
0860 
0861 /* TOOLS_STL : no std::list::insert.
0862   void add_after(tree* a_tree,tree* a_entry){
0863     tools_lforit(tree*,m_children,it) {
0864       if((*it)==a_tree) {
0865         m_children.insert(it,a_entry);
0866         return;
0867       }
0868     }
0869   }
0870 
0871   //TOOLS_STL : no std::list::iterator::operator--.
0872 
0873   tree* previous_child(const tree& a_tree){
0874     tools_lforit(tree*,m_children,it) {
0875       if((*it)==&a_tree) {
0876         if(it==m_children.begin()) return 0;
0877         --it;
0878         return *it;
0879       }
0880     }
0881     return 0;
0882   }
0883 
0884   tree* next_child(const tree& a_tree){
0885     tools_lforit(tree*,m_children,it) {
0886       if((*it)==&a_tree) {
0887         std::list<tree*>::iterator last = m_children.end();
0888         --last;
0889         if(it==last) return 0;
0890         ++it;
0891         return *it;
0892       }
0893     }
0894     return 0;
0895   }
0896 */
0897 
0898   void set_data(void* a_data_1,void* a_data_2,int a_data_int) {
0899     m_data_1 = a_data_1;
0900     m_data_2 = a_data_2;
0901     m_data_int = a_data_int;
0902   }
0903   void get_data(void*& a_data_1,void*& a_data_2,int& a_data_int) const {
0904     a_data_1 = m_data_1;
0905     a_data_2 = m_data_2;
0906     a_data_int = m_data_int;
0907   }
0908   void* get_data1() const {return m_data_1;}
0909   void* get_data2() const {return m_data_2;}
0910   int get_data_int() const {return m_data_int;}
0911   void set_depth(unsigned int a_depth) {m_depth = a_depth;}
0912   unsigned int depth() const {return m_depth;}
0913   void set_save_flag(bool a_value) {m_save = a_value;}
0914   bool save_flag() const {return m_save;}
0915   void set_file(const std::string& a_file) {m_file = a_file;}
0916   const std::string& file() const {return m_file;}
0917 
0918 protected:
0919   void clear(){
0920     m_atbs.clear();
0921 
0922    // TOOLS_STL : no std::list::erase.
0923    //{std::list<tree*>::iterator it;
0924    // for(it=m_children.begin();
0925    //     it!=m_children.end();
0926    //     it = m_children.erase(it))
0927    //   delete (*it);}
0928    //
0929    //{std::list<element*>::iterator it;
0930    // for(it=m_elems.begin();it!=m_elems.end();it = m_elems.erase(it))
0931    //   delete (*it);}
0932 
0933     while(!m_childs.empty()) {
0934       ielem* item = m_childs.front();
0935       m_childs.remove(item);
0936       delete item;
0937     }
0938   }
0939 
0940 protected:
0941   std::string m_tag_name;
0942   factory& m_factory;
0943   tree* m_parent;
0944   //std::list<tree*> m_children;
0945   //std::list<element*> m_elems;
0946   std::list<ielem*> m_childs;
0947   std::vector<atb> m_atbs;
0948   std::string m_file;
0949   bool m_save;
0950   void* m_data_1;
0951   void* m_data_2;
0952   int m_data_int;
0953   int m_depth;
0954 };
0955 
0956 class looper {
0957 public:
0958   looper(const tree& a_tree)
0959   :m_it(a_tree.childs().begin())
0960   ,m_end(a_tree.childs().end())
0961   {}
0962   virtual ~looper(){}
0963 protected:
0964   looper(const looper& a_from)
0965   :m_it(a_from.m_it)
0966   ,m_end(a_from.m_end)
0967   {}
0968   looper& operator=(const looper&){return *this;}
0969 public:
0970   tree* next_tree() {
0971     for(;m_it!=m_end;++m_it) {
0972       tree* _tree = id_cast<ielem,tree>(*(*m_it));
0973       if(_tree) {m_it++;return _tree;}
0974     }
0975     return 0;
0976   }
0977   element* next_element() {
0978     for(;m_it!=m_end;++m_it) {
0979       element* _elem = id_cast<ielem,element>(*(*m_it));
0980       if(_elem) {m_it++;return _elem;}
0981     }
0982     return 0;
0983   }
0984 protected:
0985   std::list<ielem*>::const_iterator m_it;
0986   std::list<ielem*>::const_iterator m_end;
0987 };
0988 
0989 class default_factory : public virtual factory {
0990 #ifdef TOOLS_MEM
0991   TOOLS_SCLASS(tools::xml::default_factory)
0992 #endif
0993 public:
0994   virtual tree* create(const std::string& a_tag_name,const std::vector<tree::atb>& a_atbs,tree* a_parent) {
0995     // It does not add the new tree in parent.
0996     tree* itemML = new tree(a_tag_name,*this,a_parent);
0997     itemML->set_attributes(a_atbs);
0998     return itemML;
0999   }
1000 public:
1001   default_factory(){
1002 #ifdef TOOLS_MEM
1003     mem::increment(s_class().c_str());
1004 #endif
1005   }
1006   virtual ~default_factory(){
1007 #ifdef TOOLS_MEM
1008     mem::decrement(s_class().c_str());
1009 #endif
1010   }
1011 public:
1012   default_factory(const default_factory& a_from)
1013   :factory(a_from){
1014 #ifdef TOOLS_MEM
1015     mem::increment(s_class().c_str());
1016 #endif
1017   }
1018   default_factory& operator=(const default_factory&){return *this;}
1019 };
1020 
1021 }}
1022 
1023 #endif