Visual Servoing Platform version 3.5.0
vpXmlParser.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Tool to automatise the creation of xml parser based on the libXML2
33 *
34 * Authors:
35 * Romain Tallonneau
36 *
37 *****************************************************************************/
38
39#include <visp3/core/vpConfig.h>
40#include <visp3/core/vpXmlParser.h>
41
42#ifdef VISP_HAVE_XML2
43
44#include <libxml/parser.h>
45#include <visp3/core/vpDebug.h>
46#include <visp3/core/vpException.h>
47
48#include <iomanip>
49#include <sstream>
50#include <string>
51#include <typeinfo>
52
58vpXmlParser::vpXmlParser() : nodeMap(), main_tag("config") {}
59
76{
77 // xmlCleanupParser();
78}
79
85vpXmlParser::vpXmlParser(const vpXmlParser &_twin) : nodeMap(_twin.nodeMap), main_tag(_twin.main_tag) {}
86
87/* utilities functions to read/write data from an xml document */
88
100char *vpXmlParser::xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
101{
102 if (node->xmlChildrenNode == NULL) {
103 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read char*";
104 std::cerr << errorMsg << std::endl;
105 throw vpException(vpException::fatalError, errorMsg);
106 }
107 return (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
108}
109
120std::string vpXmlParser::xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
121{
122 if (node->xmlChildrenNode == NULL) {
123 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read std::string";
124 std::cerr << errorMsg << std::endl;
125 throw vpException(vpException::fatalError, errorMsg);
126 }
127 char *dataCh = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
128 std::string dataStr = dataCh;
129 xmlFree(dataCh);
130 return dataStr;
131}
132
144int vpXmlParser::xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
145{
146 if (node->xmlChildrenNode == NULL) {
147 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read int";
148 std::cerr << errorMsg << std::endl;
149 throw vpException(vpException::fatalError, errorMsg);
150 }
151 char *val_char;
152 char *control_convert;
153 int val_int;
154
155 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
156 val_int = (int)strtol((char *)val_char, &control_convert, 10);
157
158 if (val_char == control_convert) {
159 xmlFree((xmlChar *)val_char);
160 throw vpException(vpException::ioError, "cannot parse entry to int");
161 }
162 xmlFree((xmlChar *)val_char);
163
164 return val_int;
165}
166
178unsigned int vpXmlParser::xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
179{
180 if (node->xmlChildrenNode == NULL) {
181 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read unsigned int";
182 std::cerr << errorMsg << std::endl;
183 throw vpException(vpException::fatalError, errorMsg);
184 }
185 char *val_char;
186 char *control_convert;
187 unsigned int val_uint;
188
189 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
190 val_uint = (unsigned int)strtoul((char *)val_char, &control_convert, 10);
191
192 if (val_char == control_convert) {
193 xmlFree((xmlChar *)val_char);
194 throw vpException(vpException::ioError, "cannot parse entry to int");
195 }
196 xmlFree((xmlChar *)val_char);
197
198 return val_uint;
199}
200
212double vpXmlParser::xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
213{
214 if (node->xmlChildrenNode == NULL) {
215 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read double";
216 std::cerr << errorMsg << std::endl;
217 throw vpException(vpException::fatalError, errorMsg);
218 }
219 char *val_char;
220 char *control_convert;
221 double val_double;
222
223 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
224 val_double = strtod((char *)val_char, &control_convert);
225
226 if (val_char == control_convert) {
227 xmlFree((xmlChar *)val_char);
228 throw vpException(vpException::ioError, "cannot parse entry to double");
229 }
230 xmlFree((xmlChar *)val_char);
231 return val_double;
232}
233
245float vpXmlParser::xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
246{
247 if (node->xmlChildrenNode == NULL) {
248 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read float";
249 std::cerr << errorMsg << std::endl;
250 throw vpException(vpException::fatalError, errorMsg);
251 }
252 char *val_char;
253 char *control_convert;
254 float val_float;
255
256 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
257#if defined(VISP_HAVE_FUNC_STRTOF)
258 val_float = strtof((char *)val_char, &control_convert);
259#else
260 val_float = (float)strtod((char *)val_char, &control_convert);
261#endif
262
263 if (val_char == control_convert) {
264 xmlFree((xmlChar *)val_char);
265 throw vpException(vpException::ioError, "cannot parse entry to float");
266 }
267 xmlFree((xmlChar *)val_char);
268 return val_float;
269}
270
282bool vpXmlParser::xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
283{
284 if (node->xmlChildrenNode == NULL) {
285 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read bool";
286 std::cerr << errorMsg << std::endl;
287 throw vpException(vpException::fatalError, errorMsg);
288 }
289 char *val_char;
290 bool val_bool;
291
292 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
293 val_bool = val_char[0] != '0'; // reading only 1st character : bool xml storage is '0' or '1'
294
295 xmlFree((xmlChar *)val_char);
296 return val_bool;
297}
298
306void vpXmlParser::xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
307{
308 xmlNodePtr tmp;
309 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)value);
310 xmlAddChild(node, tmp);
311}
312
320void vpXmlParser::xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
321{
322 xmlNodePtr tmp;
323 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)value.c_str());
324 xmlAddChild(node, tmp);
325}
326
334void vpXmlParser::xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
335{
336 char str[100];
337 sprintf(str, "%d", value);
338 xmlNodePtr tmp;
339 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
340 xmlAddChild(node, tmp);
341}
342
350void vpXmlParser::xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, unsigned int value)
351{
352 char str[100];
353 sprintf(str, "%u", value);
354 xmlNodePtr tmp;
355 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
356 xmlAddChild(node, tmp);
357}
358
366void vpXmlParser::xmlWriteDoubleChild(xmlNodePtr node, const char *label, double value)
367{
368 char str[100];
369 sprintf(str, "%lf", value);
370 xmlNodePtr tmp;
371 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
372 xmlAddChild(node, tmp);
373}
374
382void vpXmlParser::xmlWriteFloatChild(xmlNodePtr node, const char *label, float value)
383{
384 char str[100];
385 sprintf(str, "%f", value);
386 xmlNodePtr tmp;
387 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
388 xmlAddChild(node, tmp);
389}
390
398void vpXmlParser::xmlWriteBoolChild(xmlNodePtr node, const char *label, bool value)
399{
400 char str[2];
401 sprintf(str, "%d", (int)value);
402 xmlNodePtr tmp;
403 tmp = xmlNewChild(node, NULL, (xmlChar *)label, (xmlChar *)str);
404 xmlAddChild(node, tmp);
405}
406
407/* --------------------------------------------------------------------------
408 */
409/* MAIN METHODS */
410/* --------------------------------------------------------------------------
411 */
412
421void vpXmlParser::parse(const std::string &filename)
422{
423 xmlDocPtr doc;
424 xmlNodePtr root_node;
425
426 doc = xmlParseFile(filename.c_str());
427 if (doc == NULL) {
428 vpERROR_TRACE("cannot open file");
429 throw vpException(vpException::ioError, "cannot open file");
430 }
431
432 root_node = xmlDocGetRootElement(doc);
433 if (root_node == NULL) {
434 vpERROR_TRACE("cannot get root element");
435 throw vpException(vpException::ioError, "cannot get root element");
436 }
437
438 readMainClass(doc, root_node);
439
440 xmlFreeDoc(doc);
441}
442
453void vpXmlParser::save(const std::string &filename, bool append)
454{
455 xmlDocPtr doc;
456 xmlNodePtr root_node;
457
458 doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
459 if (doc == NULL) {
460 doc = xmlNewDoc((xmlChar *)"1.0");
461 root_node = xmlNewNode(NULL, (xmlChar *)main_tag.c_str());
462 xmlDocSetRootElement(doc, root_node);
463 } else {
464 if (!append) {
465 xmlFreeDoc(doc);
466 if (remove(filename.c_str()) != 0)
467 throw vpException(vpException::ioError, "Cannot remove existing xml file");
468
469 doc = xmlNewDoc((xmlChar *)"1.0");
470 root_node = xmlNewNode(NULL, (xmlChar *)main_tag.c_str());
471 xmlDocSetRootElement(doc, root_node);
472 }
473 }
474
475 root_node = xmlDocGetRootElement(doc);
476 if (root_node == NULL) {
477 vpERROR_TRACE("problem to get the root node");
478 throw vpException(vpException::ioError, "problem to get the root node");
479 }
480
481 writeMainClass(root_node);
482
483 xmlSaveFormatFile(filename.c_str(), doc, 1);
484 xmlFreeDoc(doc);
485}
486
487#elif !defined(VISP_BUILD_SHARED_LIBS)
488// Work arround to avoid warning: libvisp_core.a(vpXmlParser.cpp.o) has no
489// symbols
490void dummy_vpXmlParser(){};
491#endif
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ ioError
I/O error.
Definition: vpException.h:91
@ fatalError
Fatal error.
Definition: vpException.h:96
void xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
void xmlWriteBoolChild(xmlNodePtr node, const char *label, bool value)
void xmlWriteFloatChild(xmlNodePtr node, const char *label, float value)
double xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
void xmlWriteDoubleChild(xmlNodePtr node, const char *label, double value)
float xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
void xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, unsigned int value)
void xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
void xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
int xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
void save(const std::string &filename, bool append=false)
bool xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
unsigned int xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
virtual ~vpXmlParser()
Definition: vpXmlParser.cpp:75
void parse(const std::string &filename)
char * xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
virtual void readMainClass(xmlDocPtr doc, xmlNodePtr node)=0
std::string xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
virtual void writeMainClass(xmlNodePtr node)=0
std::string main_tag
Definition: vpXmlParser.h:235
#define vpERROR_TRACE
Definition: vpDebug.h:393