00001
00002
00003
00004
00005
00006
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