XmlReader.hpp

00001 // This file is part of the imaging2 class library.
00002 //
00003 // University of Innsbruck, Infmath Imaging, 2009.
00004 // http://infmath.uibk.ac.at
00005 //
00006 // All rights reserved.
00007 
00008 
00009 #ifndef XML_XMLREADER_H
00010 #define XML_XMLREADER_H
00011 
00012 #include <core/cio.hpp>
00013 #include <core/Exception.hpp>
00014 
00015 #include <boost/shared_ptr.hpp>
00016 #include <boost/lexical_cast.hpp>
00017 
00018 typedef struct _xmlDoc xmlDoc;
00019 typedef xmlDoc * xmlDocPtr;
00020 
00021 typedef struct _xmlXPathContext xmlXPathContext;
00022 typedef xmlXPathContext * xmlXPathContextPtr;
00023 
00024 typedef struct _xmlNodeSet xmlNodeSet;
00025 typedef xmlNodeSet * xmlNodeSetPtr;
00026   
00027 namespace imaging
00028 {
00029   
00040   template<class data_t>
00041   class xml_handler;
00042   
00104   class XmlReader
00105   {
00107     class stream_command
00108     {
00109       friend class XmlReader;
00110 
00111     protected:
00112       enum commands { ELEMENT = 0, INDEX, ELEMENT_WITH_INDEX, END_ELEMENT, ATTRIBUTE, CHILD_ELEMENT };
00113 
00114       size_t _cmd_id;
00115       std::string _identifier;
00116       size_t _index;
00117 
00118     public:
00119       stream_command() {}
00120       stream_command(size_t cmd_id, const std::string & identifier, size_t index = 0) : 
00121         _cmd_id(cmd_id), _identifier(identifier), _index(index) {}}
00122     ;
00123     
00126   public:
00128     class element : public stream_command
00129     {
00130     public:
00132       element(const std::string & identifier) : stream_command(ELEMENT, identifier) {}
00133       
00135       element(const std::string & identifier, size_t index) :
00136         stream_command(ELEMENT_WITH_INDEX, identifier, index) {}
00137       
00139       element(size_t index) : stream_command(INDEX, "", index) {}
00140     };
00141     
00143     class child_element : public stream_command
00144     {
00145     public:
00147       child_element(size_t index) : stream_command(CHILD_ELEMENT, "", index) {}
00148     };
00149 
00150     
00152     class attribute : public stream_command
00153     {
00154     public:
00156       attribute(const std::string & identifier) : stream_command(ATTRIBUTE, identifier) {}}
00157     ;
00158 
00165     template <class data_t>
00166     class default_value
00167     {
00168       friend class XmlReader;
00169 
00170       data_t & _object;
00171       const data_t & _default_object;
00172 
00173     public:
00176       default_value(data_t & object, const data_t & default_object) : _object(object), _default_object(default_object) {}
00177     };
00178     
00185     template <class data_t>
00186     class try_read
00187     {
00188       friend class XmlReader;
00189 
00190       data_t & _object;
00191 
00192     public:
00195       try_read(data_t & object) : _object(object){}
00196     };
00197 
00198 
00202   class XmlNoTagException : public Exception
00203     {
00204     public:
00206       XmlNoTagException(std::string msg = std::string("XmlNoTagException!")) : Exception(msg) {}}
00207     ;
00208 
00209   private:
00210     xmlDocPtr _doc;
00211     xmlXPathContextPtr _xpathCtx;
00212 
00213     std::vector<stream_command> _current_path;
00214     std::string _current_attribute;
00215     bool _attribute_active;
00216 
00217     void parse_element(const std::string & path_expression, std::string & result) const
00218       throw (XmlNoTagException);
00219     
00220     void parse_attribute(const std::string & attribute, std::string & result) const
00221       throw (XmlNoTagException);
00222 
00223     size_t evaluate_x_path(const std::string & path_expr, xmlNodeSetPtr & node_set_ptr) const;
00224 
00225     void compute_current_path(std::string & path) const;
00226 
00227     size_t compute_n_elements(const std::string & path_expr) const;
00228 
00229     template<size_t N, class data_t>
00230     void string_2_fixed_vector(const std::string & str, ublas::fixed_vector<data_t, N> & v)
00231     {
00232       std::istringstream in(str);
00233       char buffer[5];
00234 
00235       in.getline(buffer, 5, '(');
00236 
00237       for(std::size_t i = 0; i < N - 1; ++i)
00238       {
00239         v(i) = data_t(float_t(0));
00240         in >> v(i);
00241         in.getline(buffer, 5, ',');
00242       }
00243 
00244       v(N - 1) = data_t(float_t(0));
00245       in >> v(N - 1);
00246     }
00247     
00248     template <class data_t>
00249     XmlReader &  read_integral_type_value(data_t & value)
00250     {
00251       std::string temp;
00252   
00253       *this >> temp;
00254   
00255       try
00256       {
00257         value = boost::lexical_cast<data_t>(temp);
00258       }
00259       catch(boost::bad_lexical_cast & e)
00260       {
00261         throw Exception("Exception: lexical cast of '" + temp + "' failed in XmlReader::read_integral_type_value().");
00262       }
00263   
00264       return *this;
00265     }
00266     
00267     template <class data_t>
00268     XmlReader & read_integral_type_vector(std::vector<data_t> & vector)
00269     {
00270       std::string path;
00271       size_t n_elements;
00272   
00273       compute_current_path(path);
00274       n_elements = compute_n_elements(path);
00275       vector.resize(n_elements);
00276   
00277       for(size_t i = 0; i < n_elements; ++i)
00278       {
00279         *this >> element(i);
00280         *this >> vector[i];
00281         *this >> end_element;
00282       }
00283       
00284       *this >> end_element;
00285   
00286       return *this;
00287     }
00288 
00289   public:
00293     static const stream_command end_element;
00294 
00296     XmlReader(const std::string & xml_file_name, const std::string & root_element);
00297 
00299     ~XmlReader();
00300 
00302     XmlReader & operator>>(const stream_command & command);
00303 
00305     template<size_t N, class data_t>
00306     XmlReader & operator>>(ublas::fixed_vector<data_t, N> & value)
00307     {
00308       std::string temp;
00309 
00310       (*this) >> temp;
00311 
00312       string_2_fixed_vector(temp, value);
00313 
00314       return *this;
00315     }
00316 
00318     template<size_t N, class data_t>
00319     XmlReader & operator>>(std::vector< ublas::fixed_vector<data_t, N> > & vector)
00320     {
00321       std::string path;
00322       size_t n_elements;
00323 
00324       compute_current_path(path);
00325       n_elements = compute_n_elements(path);
00326       vector.resize(n_elements);
00327 
00328       for(size_t i = 0; i < n_elements; ++i)
00329       {
00330         *this >> element(i);
00331         *this >> vector[i];
00332         *this >> end_element;
00333       }
00334       
00335       *this >> end_element;
00336 
00337       return *this;
00338     }
00339     
00341     XmlReader & operator>>(std::vector<float_t> & vector);
00342     
00344     XmlReader & operator>>(float_t & value);
00345     
00347     XmlReader & operator>>(size_t & value);
00348     
00350     XmlReader & operator>>(int & value);
00351     
00353     XmlReader & operator>>(bool & value);
00354     
00356     XmlReader & operator>>(std::string & string);
00357     
00359     XmlReader & operator>>(std::vector<std::string> & vector);
00360 
00362     template<class data_t>
00363     XmlReader & operator>>(const default_value<data_t> & command)
00364     {
00365       try { *this >> command._object; }
00366       catch (XmlNoTagException & exception) { command._object = command._default_object; }
00367 
00368       return *this;
00369     }
00370 
00372     template<class data_t>
00373     XmlReader & operator>>(const try_read<data_t> & command)
00374     {
00375       try { *this >> command._object; }
00376       catch (XmlNoTagException & exception) { }
00377 
00378       return *this;
00379     }
00380     
00382     template<class data_t>
00383     XmlReader & operator>>(std::vector<data_t> & vector)
00384     {
00385       xml_handler<data_t> handler;
00386       
00387       std::string path;
00388       size_t n_elements;
00389       
00390       *this >> element(handler.element_name);
00391 
00392       compute_current_path(path);
00393       n_elements = compute_n_elements(path);
00394       vector.resize(n_elements);
00395 
00396       for(size_t i = 0; i < n_elements; ++i)
00397       {
00398         *this >> element(i);
00399         handler.read_object(*this, vector[i]);
00400         *this >> end_element;
00401       }
00402 
00403       *this >> end_element;
00404 
00405       return *this;
00406     }
00407     
00409     template<class data_t>
00410     XmlReader & operator>>(std::vector< boost::shared_ptr<data_t> > & vector)
00411     {
00412       xml_handler<data_t> handler;
00413       
00414       std::string path;
00415       size_t n_elements;
00416       
00417       *this >> element(handler.element_name);
00418 
00419       compute_current_path(path);
00420       n_elements = compute_n_elements(path);
00421       vector.resize(n_elements);
00422       for(size_t i = 0; i < n_elements; ++i)
00423       {
00424         try
00425         {
00426           vector[i].reset(new data_t);
00427         }
00428         catch(std::bad_alloc & e)
00429         {
00430           n_elements = 0;
00431           vector.resize(n_elements);
00432         }
00433       }
00434 
00435       for(size_t i = 0; i < n_elements; ++i)
00436       {
00437         *this >> element(i);
00438         handler.read_object(*this, *vector[i]);
00439         *this >> end_element;
00440       }
00441 
00442       *this >> end_element;
00443 
00444       return *this;
00445     }
00446     
00448     template<class data_t>
00449     XmlReader & operator>>(data_t & object)
00450     {
00451       xml_handler<data_t> handler;
00452       bool xml_exception_thrown = false;
00453       XmlReader::XmlNoTagException exception;
00454       
00455       *this >> element(handler.element_name);
00456       
00457       try
00458       {
00459         handler.read_object(*this, object);
00460       }
00461       catch(XmlReader::XmlNoTagException & e)
00462       {
00463         xml_exception_thrown = true;
00464         exception = e;
00465       }
00466       
00467       *this >> end_element;
00468       
00469       if(xml_exception_thrown)
00470         throw exception;
00471 
00472       return *this;
00473     }
00474 
00476     size_t n_elements() const;
00477 
00479     size_t n_child_elements() const;
00480 
00482     std::string current_element_name() const;
00483   };
00484 }
00485 
00486 #endif

Generated on Tue Feb 10 10:01:31 2009 for imaging2 by  doxygen 1.5.5