Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpXmlParser.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Tool to automatise the creation of xml parser based on the libXML2
32  *
33  * Authors:
34  * Romain Tallonneau
35  *
36  *****************************************************************************/
37 
38 #include <visp3/core/vpXmlParser.h>
39 #include <visp3/core/vpConfig.h>
40 
41 #ifdef VISP_HAVE_XML2
42 
43 #include <visp3/core/vpException.h>
44 #include <visp3/core/vpDebug.h>
45 #include <libxml/parser.h>
46 
47 #include <string>
48 #include <sstream>
49 #include <iomanip>
50 #include <typeinfo>
51 
57 vpXmlParser::vpXmlParser() : nodeMap(), main_tag("config")
58 {
59 }
60 
76 {
77  //xmlCleanupParser();
78 }
79 
86  : nodeMap(), main_tag("config")
87 {
88  main_tag = _twin.main_tag;
89  nodeMap = _twin.nodeMap;
90 }
91 
92 /* utilities functions to read/write data from an xml document */
93 
105 char*
106 vpXmlParser::xmlReadCharChild (xmlDocPtr doc, xmlNodePtr node)
107 {
108  if(node ->xmlChildrenNode == NULL){
109  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read char*";
110  std::cerr << errorMsg << std::endl;
111  throw vpException(vpException::fatalError, errorMsg);
112  }
113  return (char *) xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
114 }
115 
126 std::string
127 vpXmlParser::xmlReadStringChild (xmlDocPtr doc, xmlNodePtr node)
128 {
129  if(node ->xmlChildrenNode == NULL){
130  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read std::string";
131  std::cerr << errorMsg << std::endl;
132  throw vpException(vpException::fatalError, errorMsg);
133  }
134  char* dataCh = (char*)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
135  std::string dataStr = dataCh;
136  xmlFree(dataCh);
137  return dataStr;
138 }
139 
150 int
151 vpXmlParser::xmlReadIntChild (xmlDocPtr doc, xmlNodePtr node)
152 {
153  if(node ->xmlChildrenNode == NULL){
154  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read int";
155  std::cerr << errorMsg << std::endl;
156  throw vpException(vpException::fatalError, errorMsg);
157  }
158  char * val_char;
159  char * control_convert;
160  int val_int;
161 
162  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
163  val_int = (int)strtol ((char *)val_char, &control_convert, 10);
164 
165  if (val_char == control_convert){
166  xmlFree((xmlChar*) val_char);
167  throw vpException(vpException::ioError, "cannot parse entry to int");
168  }
169  xmlFree((xmlChar*) val_char);
170 
171  return val_int;
172 }
173 
184 unsigned int
185 vpXmlParser::xmlReadUnsignedIntChild (xmlDocPtr doc, xmlNodePtr node)
186 {
187  if(node ->xmlChildrenNode == NULL){
188  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read unsigned int";
189  std::cerr << errorMsg << std::endl;
190  throw vpException(vpException::fatalError, errorMsg);
191  }
192  char * val_char;
193  char * control_convert;
194  unsigned int val_uint;
195 
196  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
197  val_uint = (unsigned int)strtoul ((char *)val_char, &control_convert, 10);
198 
199  if (val_char == control_convert){
200  xmlFree((xmlChar*) val_char);
201  throw vpException(vpException::ioError, "cannot parse entry to int");
202  }
203  xmlFree((xmlChar*) val_char);
204 
205  return val_uint;
206 }
207 
218 double
219 vpXmlParser::xmlReadDoubleChild (xmlDocPtr doc, xmlNodePtr node)
220 {
221  if(node ->xmlChildrenNode == NULL){
222  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read double";
223  std::cerr << errorMsg << std::endl;
224  throw vpException(vpException::fatalError, errorMsg);
225  }
226  char * val_char;
227  char * control_convert;
228  double val_double;
229 
230  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
231  val_double = strtod ((char *)val_char, &control_convert);
232 
233  if (val_char == control_convert){
234  xmlFree((xmlChar*) val_char);
235  throw vpException(vpException::ioError, "cannot parse entry to double");
236  }
237  xmlFree((xmlChar*) val_char);
238  return val_double;
239 }
240 
251 float
252 vpXmlParser::xmlReadFloatChild (xmlDocPtr doc, xmlNodePtr node)
253 {
254  if(node ->xmlChildrenNode == NULL){
255  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read float";
256  std::cerr << errorMsg << std::endl;
257  throw vpException(vpException::fatalError, errorMsg);
258  }
259  char * val_char;
260  char * control_convert;
261  float val_float;
262 
263  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
264 #if defined(VISP_HAVE_FUNC_STRTOF)
265  val_float = strtof ((char *)val_char, &control_convert);
266 #else
267  val_float = (float) strtod ((char *)val_char, &control_convert);
268 #endif
269 
270  if (val_char == control_convert){
271  xmlFree((xmlChar*) val_char);
272  throw vpException(vpException::ioError, "cannot parse entry to float");
273  }
274  xmlFree((xmlChar*) val_char);
275  return val_float;
276 }
277 
288 bool
289 vpXmlParser::xmlReadBoolChild (xmlDocPtr doc, xmlNodePtr node)
290 {
291  if(node ->xmlChildrenNode == NULL){
292  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read bool";
293  std::cerr << errorMsg << std::endl;
294  throw vpException(vpException::fatalError, errorMsg);
295  }
296  char * val_char;
297  bool val_bool;
298 
299  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
300  val_bool = val_char[0] != '0'; //reading only 1st character : bool xml storage is '0' or '1'
301 
302  xmlFree((xmlChar*) val_char);
303  return val_bool;
304 }
305 
313 void
314 vpXmlParser::xmlWriteCharChild(xmlNodePtr node, const char* label, const char* value)
315 {
316  xmlNodePtr tmp;
317  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)value);
318  xmlAddChild(node, tmp);
319 }
320 
328 void
329 vpXmlParser::xmlWriteStringChild(xmlNodePtr node, const char* label, const std::string& value)
330 {
331  xmlNodePtr tmp;
332  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)value.c_str());
333  xmlAddChild(node, tmp);
334 }
335 
336 
344 void
345 vpXmlParser::xmlWriteIntChild(xmlNodePtr node, const char* label, const int value)
346 {
347  char str[100];
348  sprintf(str, "%d", value);
349  xmlNodePtr tmp;
350  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
351  xmlAddChild(node, tmp);
352 }
353 
361 void
362 vpXmlParser::xmlWriteUnsignedIntChild(xmlNodePtr node, const char* label, const unsigned int value)
363 {
364  char str[100];
365  sprintf(str, "%u", value);
366  xmlNodePtr tmp;
367  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
368  xmlAddChild(node, tmp);
369 }
370 
371 
379 void
380 vpXmlParser::xmlWriteDoubleChild(xmlNodePtr node, const char* label, const double value)
381 {
382  char str[100];
383  sprintf(str, "%lf", value);
384  xmlNodePtr tmp;
385  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
386  xmlAddChild(node, tmp);
387 }
388 
396 void
397 vpXmlParser::xmlWriteFloatChild(xmlNodePtr node, const char* label, const float value)
398 {
399  char str[100];
400  sprintf(str, "%f", value);
401  xmlNodePtr tmp;
402  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
403  xmlAddChild(node, tmp);
404 }
405 
413 void
414 vpXmlParser::xmlWriteBoolChild(xmlNodePtr node, const char* label, const bool value)
415 {
416  char str[2];
417  sprintf(str, "%d", (int)value);
418  xmlNodePtr tmp;
419  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
420  xmlAddChild(node, tmp);
421 }
422 
423 /* -------------------------------------------------------------------------- */
424 /* MAIN METHODS */
425 /* -------------------------------------------------------------------------- */
426 
435 void
436 vpXmlParser::parse(const std::string& filename)
437 {
438  xmlDocPtr doc;
439  xmlNodePtr root_node;
440 
441  doc = xmlParseFile(filename.c_str());
442  if(doc == NULL){
443  vpERROR_TRACE("cannot open file");
444  throw vpException(vpException::ioError, "cannot open file");
445  }
446 
447  root_node = xmlDocGetRootElement(doc);
448  if(root_node == NULL){
449  vpERROR_TRACE("cannot get root element");
450  throw vpException(vpException::ioError, "cannot get root element");
451  }
452 
453  readMainClass(doc, root_node);
454 
455  xmlFreeDoc(doc);
456 }
457 
468 void
469 vpXmlParser::save(const std::string& filename, const bool append)
470 {
471  xmlDocPtr doc;
472  xmlNodePtr root_node;
473 
474  doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
475  if (doc == NULL){
476  doc = xmlNewDoc ((xmlChar*)"1.0");
477  root_node = xmlNewNode(NULL, (xmlChar*)main_tag.c_str());
478  xmlDocSetRootElement(doc, root_node);
479  }
480  else{
481  if(!append){
482  xmlFreeDoc(doc);
483  if (remove(filename.c_str()) != 0)
484  throw vpException(vpException::ioError, "Cannot remove existing xml file");
485 
486  doc = xmlNewDoc ((xmlChar*)"1.0");
487  root_node = xmlNewNode(NULL, (xmlChar*)main_tag.c_str());
488  xmlDocSetRootElement(doc, root_node);
489  }
490  }
491 
492  root_node = xmlDocGetRootElement(doc);
493  if (root_node == NULL)
494  {
495  vpERROR_TRACE("problem to get the root node");
496  throw vpException(vpException::ioError, "problem to get the root node");
497  }
498 
499  writeMainClass(root_node);
500 
501  xmlSaveFormatFile(filename.c_str(), doc, 1);
502  xmlFreeDoc(doc);
503 }
504 
505 #elif !defined(VISP_BUILD_SHARED_LIBS)
506 // Work arround to avoid warning: libvisp_core.a(vpXmlParser.cpp.o) has no symbols
507 void dummy_vpXmlParser() {};
508 #endif
std::string main_tag
Definition: vpXmlParser.h:229
void xmlWriteIntChild(xmlNodePtr node, const char *label, const int value)
virtual ~vpXmlParser()
Definition: vpXmlParser.cpp:75
void xmlWriteFloatChild(xmlNodePtr node, const char *label, const float value)
#define vpERROR_TRACE
Definition: vpDebug.h:391
void xmlWriteBoolChild(xmlNodePtr node, const char *label, const bool value)
error that can be emited by ViSP classes.
Definition: vpException.h:73
virtual void writeMainClass(xmlNodePtr node)=0
double xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
char * xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
void save(const std::string &filename, const bool append=false)
This class intends to simplify the creation of xml parser based on the libxml2 third party library...
Definition: vpXmlParser.h:175
void xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, const unsigned int value)
void xmlWriteDoubleChild(xmlNodePtr node, const char *label, const double value)
void xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
int xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
virtual void readMainClass(xmlDocPtr doc, xmlNodePtr node)=0
unsigned int xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
std::string xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
float xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
void xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
bool xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
std::map< std::string, int > nodeMap
Definition: vpXmlParser.h:224
void parse(const std::string &filename)