Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpXmlParser.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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 automatize the creation of xml parser based on the libXML2.
32 */
33
34#include <visp3/core/vpConfig.h>
35
36#ifdef VISP_HAVE_XML2
37
38#include <libxml/parser.h>
39
40#include <visp3/core/vpXmlParser.h>
41#include <visp3/core/vpDebug.h>
42#include <visp3/core/vpException.h>
43
44#include <iomanip>
45#include <sstream>
46#include <string>
47#include <typeinfo>
48
56
73{
74 // xmlCleanupParser();
75}
76
83
84/* utilities functions to read/write data from an xml document */
85
97char *vpXmlParser::xmlReadCharChild(xmlDocPtr doc, xmlNodePtr node)
98{
99 if (node->xmlChildrenNode == nullptr) {
100 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read char*";
101 std::cerr << errorMsg << std::endl;
102 throw vpException(vpException::fatalError, errorMsg);
103 }
104 return (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
105}
106
116
117std::string vpXmlParser::xmlReadStringChild(xmlDocPtr doc, xmlNodePtr node)
118{
119 if (node->xmlChildrenNode == nullptr) {
120 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read std::string";
121 std::cerr << errorMsg << std::endl;
122 throw vpException(vpException::fatalError, errorMsg);
123 }
124 char *dataCh = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
125 std::string dataStr = dataCh;
126 xmlFree(dataCh);
127 return dataStr;
128}
129
141int vpXmlParser::xmlReadIntChild(xmlDocPtr doc, xmlNodePtr node)
142{
143 if (node->xmlChildrenNode == nullptr) {
144 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read int";
145 std::cerr << errorMsg << std::endl;
146 throw vpException(vpException::fatalError, errorMsg);
147 }
148 char *val_char;
149 char *control_convert;
150 int val_int;
151
152 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
153 val_int = static_cast<int>(strtol((char *)val_char, &control_convert, 10));
154
155 if (val_char == control_convert) {
156 xmlFree((xmlChar *)val_char);
157 throw vpException(vpException::ioError, "cannot parse entry to int");
158 }
159 xmlFree((xmlChar *)val_char);
160
161 return val_int;
162}
163
175unsigned int vpXmlParser::xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
176{
177 if (node->xmlChildrenNode == nullptr) {
178 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read unsigned int";
179 std::cerr << errorMsg << std::endl;
180 throw vpException(vpException::fatalError, errorMsg);
181 }
182 char *val_char;
183 char *control_convert;
184 unsigned int val_uint;
185
186 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
187 val_uint = static_cast<unsigned int>(strtoul((char *)val_char, &control_convert, 10));
188
189 if (val_char == control_convert) {
190 xmlFree((xmlChar *)val_char);
191 throw vpException(vpException::ioError, "cannot parse entry to int");
192 }
193 xmlFree((xmlChar *)val_char);
194
195 return val_uint;
196}
197
209double vpXmlParser::xmlReadDoubleChild(xmlDocPtr doc, xmlNodePtr node)
210{
211 if (node->xmlChildrenNode == nullptr) {
212 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read double";
213 std::cerr << errorMsg << std::endl;
214 throw vpException(vpException::fatalError, errorMsg);
215 }
216 char *val_char;
217 char *control_convert;
218 double val_double;
219
220 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
221 val_double = strtod((char *)val_char, &control_convert);
222
223 if (val_char == control_convert) {
224 xmlFree((xmlChar *)val_char);
225 throw vpException(vpException::ioError, "cannot parse entry to double");
226 }
227 xmlFree((xmlChar *)val_char);
228 return val_double;
229}
230
242float vpXmlParser::xmlReadFloatChild(xmlDocPtr doc, xmlNodePtr node)
243{
244 if (node->xmlChildrenNode == nullptr) {
245 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read float";
246 std::cerr << errorMsg << std::endl;
247 throw vpException(vpException::fatalError, errorMsg);
248 }
249 char *val_char;
250 char *control_convert;
251 float val_float;
252
253 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
254#if defined(VISP_HAVE_FUNC_STRTOF)
255 val_float = strtof((char *)val_char, &control_convert);
256#else
257 val_float = static_cast<float>(strtod((char *)val_char, &control_convert));
258#endif
259
260 if (val_char == control_convert) {
261 xmlFree((xmlChar *)val_char);
262 throw vpException(vpException::ioError, "cannot parse entry to float");
263 }
264 xmlFree((xmlChar *)val_char);
265 return val_float;
266}
267
279bool vpXmlParser::xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
280{
281 if (node->xmlChildrenNode == nullptr) {
282 std::string errorMsg = "Empty node " + std::string((char *)node->name) + ", cannot read bool";
283 std::cerr << errorMsg << std::endl;
284 throw vpException(vpException::fatalError, errorMsg);
285 }
286 char *val_char;
287 bool val_bool;
288
289 val_char = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
290 val_bool = val_char[0] != '0'; // reading only 1st character : bool xml storage is '0' or '1'
291
292 xmlFree((xmlChar *)val_char);
293 return val_bool;
294}
295
303void vpXmlParser::xmlWriteCharChild(xmlNodePtr node, const char *label, const char *value)
304{
305 xmlNodePtr tmp;
306 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)value);
307 xmlAddChild(node, tmp);
308}
309
317void vpXmlParser::xmlWriteStringChild(xmlNodePtr node, const char *label, const std::string &value)
318{
319 xmlNodePtr tmp;
320 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)value.c_str());
321 xmlAddChild(node, tmp);
322}
323
331void vpXmlParser::xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
332{
333 char str[100];
334 snprintf(str, 100, "%d", value);
335 xmlNodePtr tmp;
336 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)str);
337 xmlAddChild(node, tmp);
338}
339
347void vpXmlParser::xmlWriteUnsignedIntChild(xmlNodePtr node, const char *label, unsigned int value)
348{
349 char str[100];
350 snprintf(str, 100, "%u", value);
351 xmlNodePtr tmp;
352 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)str);
353 xmlAddChild(node, tmp);
354}
355
363void vpXmlParser::xmlWriteDoubleChild(xmlNodePtr node, const char *label, double value)
364{
365 char str[100];
366 snprintf(str, 100, "%lf", value);
367 xmlNodePtr tmp;
368 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)str);
369 xmlAddChild(node, tmp);
370}
371
379void vpXmlParser::xmlWriteFloatChild(xmlNodePtr node, const char *label, float value)
380{
381 char str[100];
382 snprintf(str, 100, "%f", value);
383 xmlNodePtr tmp;
384 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)str);
385 xmlAddChild(node, tmp);
386}
387
395void vpXmlParser::xmlWriteBoolChild(xmlNodePtr node, const char *label, bool value)
396{
397 char str[2];
398 snprintf(str, 2, "%d", static_cast<int>(value));
399 xmlNodePtr tmp;
400 tmp = xmlNewChild(node, nullptr, (xmlChar *)label, (xmlChar *)str);
401 xmlAddChild(node, tmp);
402}
403
404/* --------------------------------------------------------------------------
405 */
406/* MAIN METHODS */
407/* --------------------------------------------------------------------------
408 */
409
418void vpXmlParser::parse(const std::string &filename)
419{
420 xmlDocPtr doc;
421 xmlNodePtr root_node;
422
423 doc = xmlParseFile(filename.c_str());
424 if (doc == nullptr) {
425 vpERROR_TRACE("cannot open file");
426 throw vpException(vpException::ioError, "cannot open file");
427 }
428
429 root_node = xmlDocGetRootElement(doc);
430 if (root_node == nullptr) {
431 vpERROR_TRACE("cannot get root element");
432 throw vpException(vpException::ioError, "cannot get root element");
433 }
434
435 readMainClass(doc, root_node);
436
437 xmlFreeDoc(doc);
438}
439
450void vpXmlParser::save(const std::string &filename, bool append)
451{
452 xmlDocPtr doc;
453 xmlNodePtr root_node;
454
455 doc = xmlReadFile(filename.c_str(), nullptr, XML_PARSE_NOWARNING + XML_PARSE_NOERROR + XML_PARSE_NOBLANKS);
456 if (doc == nullptr) {
457 doc = xmlNewDoc((xmlChar *)"1.0");
458 root_node = xmlNewNode(nullptr, (xmlChar *)main_tag.c_str());
459 xmlDocSetRootElement(doc, root_node);
460 }
461 else {
462 if (!append) {
463 xmlFreeDoc(doc);
464 if (remove(filename.c_str()) != 0)
465 throw vpException(vpException::ioError, "Cannot remove existing xml file");
466
467 doc = xmlNewDoc((xmlChar *)"1.0");
468 root_node = xmlNewNode(nullptr, (xmlChar *)main_tag.c_str());
469 xmlDocSetRootElement(doc, root_node);
470 }
471 }
472
473 root_node = xmlDocGetRootElement(doc);
474 if (root_node == nullptr) {
475 vpERROR_TRACE("problem to get the root node");
476 throw vpException(vpException::ioError, "problem to get the root node");
477 }
478
479 writeMainClass(root_node);
480
481 xmlSaveFormatFile(filename.c_str(), doc, 1);
482 xmlFreeDoc(doc);
483}
484
486{
487 xmlCleanupParser();
488}
489
490END_VISP_NAMESPACE
491#elif !defined(VISP_BUILD_SHARED_LIBS)
492// Work around to avoid warning: libvisp_core.a(vpXmlParser.cpp.o) has no symbols
493void dummy_vpXmlParser() { }
494#endif
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ ioError
I/O error.
Definition vpException.h:67
@ fatalError
Fatal error.
Definition vpException.h:72
void xmlWriteIntChild(xmlNodePtr node, const char *label, int value)
static void cleanup()
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)
std::map< std::string, int > nodeMap
void save(const std::string &filename, bool append=false)
bool xmlReadBoolChild(xmlDocPtr doc, xmlNodePtr node)
unsigned int xmlReadUnsignedIntChild(xmlDocPtr doc, xmlNodePtr node)
virtual ~vpXmlParser()
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
#define vpERROR_TRACE
Definition vpDebug.h:423