Visual Servoing Platform  version 3.0.0
vpXmlParser.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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 = 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 = 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 
208 
219 double
220 vpXmlParser::xmlReadDoubleChild (xmlDocPtr doc, xmlNodePtr node)
221 {
222  if(node ->xmlChildrenNode == NULL){
223  std::string errorMsg = "Empty node " + std::string((char*)node->name) + ", cannot read double";
224  std::cerr << errorMsg << std::endl;
225  throw vpException(vpException::fatalError, errorMsg);
226  }
227  char * val_char;
228  char * control_convert;
229  double val_double;
230 
231  val_char = (char *) xmlNodeListGetString(doc, node ->xmlChildrenNode, 1);
232  val_double = strtod ((char *)val_char, &control_convert);
233 
234  if (val_char == control_convert){
235  xmlFree((xmlChar*) val_char);
236  throw vpException(vpException::ioError, "cannot parse entry to double");
237  }
238  xmlFree((xmlChar*) val_char);
239  return val_double;
240 }
241 
249 void
250 vpXmlParser::xmlWriteCharChild(xmlNodePtr node, const char* label, const char* value)
251 {
252  xmlNodePtr tmp;
253  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)value);
254  xmlAddChild(node, tmp);
255 }
256 
264 void
265 vpXmlParser::xmlWriteStringChild(xmlNodePtr node, const char* label, const std::string& value)
266 {
267  xmlNodePtr tmp;
268  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)value.c_str());
269  xmlAddChild(node, tmp);
270 }
271 
272 
280 void
281 vpXmlParser::xmlWriteIntChild(xmlNodePtr node, const char* label, const int value)
282 {
283  char str[100];
284  sprintf(str, "%d", value);
285  xmlNodePtr tmp;
286  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
287  xmlAddChild(node, tmp);
288 }
289 
297 void
298 vpXmlParser::xmlWriteUnsignedIntChild(xmlNodePtr node, const char* label, const unsigned int value)
299 {
300  char str[100];
301  sprintf(str, "%u", value);
302  xmlNodePtr tmp;
303  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
304  xmlAddChild(node, tmp);
305 }
306 
307 
315 void
316 vpXmlParser::xmlWriteDoubleChild(xmlNodePtr node, const char* label, const double value)
317 {
318  char str[100];
319  sprintf(str, "%lf", value);
320  xmlNodePtr tmp;
321  tmp = xmlNewChild(node, NULL, (xmlChar*)label, (xmlChar*)str);
322  xmlAddChild(node, tmp);
323 }
324 
325 
326 /* -------------------------------------------------------------------------- */
327 /* MAIN METHODS */
328 /* -------------------------------------------------------------------------- */
329 
338 void
339 vpXmlParser::parse(const std::string& filename)
340 {
341  xmlDocPtr doc;
342  xmlNodePtr root_node;
343 
344  doc = xmlParseFile(filename.c_str());
345  if(doc == NULL){
346  vpERROR_TRACE("cannot open file");
347  throw vpException(vpException::ioError, "cannot open file");
348  }
349 
350  root_node = xmlDocGetRootElement(doc);
351  if(root_node == NULL){
352  vpERROR_TRACE("cannot get root element");
353  throw vpException(vpException::ioError, "cannot get root element");
354  }
355 
356  readMainClass(doc, root_node);
357 
358  xmlFreeDoc(doc);
359 }
360 
371 void
372 vpXmlParser::save(const std::string& filename, const bool append)
373 {
374  xmlDocPtr doc;
375  xmlNodePtr root_node;
376 
377  doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
378  if (doc == NULL){
379  doc = xmlNewDoc ((xmlChar*)"1.0");
380  root_node = xmlNewNode(NULL, (xmlChar*)main_tag.c_str());
381  xmlDocSetRootElement(doc, root_node);
382  }
383  else{
384  if(!append){
385  xmlFreeDoc(doc);
386  if (remove(filename.c_str()) != 0)
387  throw vpException(vpException::ioError, "Cannot remove existing xml file");
388 
389  doc = xmlNewDoc ((xmlChar*)"1.0");
390  root_node = xmlNewNode(NULL, (xmlChar*)main_tag.c_str());
391  xmlDocSetRootElement(doc, root_node);
392  }
393  }
394 
395  root_node = xmlDocGetRootElement(doc);
396  if (root_node == NULL)
397  {
398  vpERROR_TRACE("problem to get the root node");
399  throw vpException(vpException::ioError, "problem to get the root node");
400  }
401 
402  writeMainClass(root_node);
403 
404  xmlSaveFormatFile(filename.c_str(), doc, 1);
405  xmlFreeDoc(doc);
406 }
407 
408 #elif !defined(VISP_BUILD_SHARED_LIBS)
409 // Work arround to avoid warning: libvisp_core.a(vpXmlParser.cpp.o) has no symbols
410 void dummy_vpXmlParser() {};
411 #endif
std::string main_tag
Definition: vpXmlParser.h:198
void xmlWriteIntChild(xmlNodePtr node, const char *label, const int value)
virtual ~vpXmlParser()
Definition: vpXmlParser.cpp:75
#define vpERROR_TRACE
Definition: vpDebug.h:391
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:174
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)
void xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
std::map< std::string, int > nodeMap
Definition: vpXmlParser.h:193
void parse(const std::string &filename)