YARP
Yet Another Robot Platform
XMLReaderFileV3.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  *
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 
10 
17 
18 #include <yarp/os/LogStream.h>
19 #include <yarp/os/Network.h>
20 #include <yarp/os/Property.h>
21 
22 #include <algorithm>
23 #include <iterator>
24 #include <sstream>
25 #include <string>
26 #include <tinyxml.h>
27 #include <vector>
28 
29 #define SYNTAX_ERROR(line) yError() << "Syntax error while loading" << curr_filename << "at line" << line << "."
30 #define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
31 
32 // BUG in TinyXML, see
33 // https://sourceforge.net/tracker/?func=detail&aid=3567726&group_id=13559&atid=113559
34 // When this bug is fixed upstream we can enable this
35 #define TINYXML_UNSIGNED_INT_BUG 0
36 
38 {
39 public:
40  explicit Private(XMLReaderFileV3* parent);
41  virtual ~Private();
42 
46 
50 
57 
61 
62  bool PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path);
63 
65 
66 #ifdef USE_DTD
68 #endif
69 
71  std::string curr_filename;
72  unsigned int minorVersion;
73  unsigned int majorVersion;
74 };
75 
76 
78  parent(p),
79  minorVersion(0),
80  majorVersion(0)
81 {
82  verbose_output = false;
83 }
84 
86 
88 {
89  yDebug() << "Reading file" << fileName.c_str();
90  auto* doc = new TiXmlDocument(fileName.c_str());
91  if (!doc->LoadFile()) {
92  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
94  }
95 
96  if (!doc->RootElement()) {
97  SYNTAX_ERROR(doc->Row()) << "No root element.";
99  }
100 
101 #ifdef USE_DTD
102  for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
103  if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
104  if (dtd.parse(childNode->ToUnknown(), curr_filename)) {
105  break;
106  }
107  }
108  }
109 
110  if (!dtd.valid()) {
111  SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version yarprobotinterfaceV1.0";
112  dtd.setDefault();
114  }
115 
116  if (dtd.type != RobotInterfaceDTD::DocTypeRobot) {
117  SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot)
118  << ". Found" << DocTypeToString(dtd.type);
119  }
120 
121  if (dtd.majorVersion != 1 || dtd.minorVersion != 0) {
122  SYNTAX_WARNING(doc->Row()) << "Only yarprobotinterface DTD version 1.0 is supported";
123  }
124 #endif
125 
126  std::string current_path;
127  current_path = fileName.substr(0, fileName.find_last_of("\\/"));
128  std::string current_filename;
129  std::string log_filename;
130  current_filename = fileName.substr(fileName.find_last_of("\\/") + 1);
131  log_filename = current_filename.substr(0, current_filename.find(".xml"));
132  log_filename += "_preprocessor_log.xml";
133  double start_time = yarp::os::Time::now();
134  PerformInclusions(doc->RootElement(), current_filename, current_path);
135  double end_time = yarp::os::Time::now();
136  std::string full_log_withpath = current_path + std::string("\\") + log_filename;
137  std::replace(full_log_withpath.begin(), full_log_withpath.end(), '\\', '/');
138  yDebug() << "Preprocessor complete in: " << end_time - start_time << "s";
139  if (verbose_output) {
140  yDebug() << "Preprocessor output stored in: " << full_log_withpath;
141  doc->SaveFile(full_log_withpath);
142  }
143  yarp::robotinterface::experimental::XMLReaderResult result = readRobotTag(doc->RootElement());
144  delete doc;
145 
146  // yDebug() << robot;
147 
148  return result;
149 }
150 
152 {
153  curr_filename = " XML runtime string ";
154  auto* doc = new TiXmlDocument();
155  if (!doc->Parse(xmlString.c_str())) {
156  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
158  }
159 
160  if (!doc->RootElement()) {
161  SYNTAX_ERROR(doc->Row()) << "No root element.";
163  }
164 
165  yarp::robotinterface::experimental::XMLReaderResult result = readRobotTag(doc->RootElement());
166  delete doc;
167 
168  return result;
169 }
170 
171 bool yarp::robotinterface::impl::XMLReaderFileV3::Private::PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path)
172 {
173 loop_start: //goto label
174  for (TiXmlElement* childElem = pParent->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
175 #ifdef DEBUG_PARSER
176  std::string a;
177  if (childElem->FirstAttribute())
178  a = childElem->FirstAttribute()->Value();
179  yDebug() << "Parsing" << childElem->Value() << a;
180 #endif
181  std::string elemString = childElem->ValueStr();
182  if (elemString == "file") {
183  yFatal() << "'file' attribute is forbidden in yarprobotinterface DTD format 3.0. Error found in " << parent_fileName;
184  return false;
185  } else if (elemString == "xi:include") {
186  std::string href_filename;
187  std::string included_filename;
188  std::string included_path;
189  if (childElem->QueryStringAttribute("href", &href_filename) == TIXML_SUCCESS) {
190  included_path = std::string(current_path).append("\\").append(href_filename.substr(0, href_filename.find_last_of("\\/")));
191  included_filename = href_filename.substr(href_filename.find_last_of("\\/") + 1);
192  std::string full_path_file = std::string(included_path).append("\\").append(included_filename);
193  TiXmlDocument included_file;
194 
195  std::replace(full_path_file.begin(), full_path_file.end(), '\\', '/');
196  if (included_file.LoadFile(full_path_file)) {
197  PerformInclusions(included_file.RootElement(), included_filename, included_path);
198  //included_file.RootElement()->SetAttribute("xml:base", href_filename); //not yet implemented
199  included_file.RootElement()->RemoveAttribute("xmlns:xi");
200  if (pParent->ReplaceChild(childElem, *included_file.FirstChildElement())) {
201  //the replace operation invalidates the iterator, hence we need to restart the parsing of this level
202  goto loop_start;
203  } else {
204  //fatal error
205  yFatal() << "Failed to include: " << included_filename << " in: " << parent_fileName;
206  return false;
207  }
208  } else {
209  //fatal error
210  yError() << included_file.ErrorDesc() << " file" << full_path_file << "included by " << parent_fileName << "at line" << childElem->Row();
211  yFatal() << "In file:" << included_filename << " included by: " << parent_fileName << " at line: " << childElem->Row();
212  return false;
213  }
214  } else {
215  //fatal error
216  yFatal() << "Syntax error in: " << parent_fileName << " while searching for href attribute";
217  return false;
218  }
219  }
220  PerformInclusions(childElem, parent_fileName, current_path);
221  }
222  return true;
223 }
224 
226 {
228  result.parsingIsSuccessful = true;
229 
230  if (robotElem->ValueStr() != "robot") {
231  SYNTAX_ERROR(robotElem->Row()) << "Root element should be \"robot\". Found" << robotElem->ValueStr();
233  }
234 
235  if (robotElem->QueryStringAttribute("name", &result.robot.name()) != TIXML_SUCCESS) {
236  SYNTAX_ERROR(robotElem->Row()) << R"("robot" element should contain the "name" attribute)";
238  }
239 
240 #if TINYXML_UNSIGNED_INT_BUG
241  if (robotElem->QueryUnsignedAttribute("build", &result.robot.build()) != TIXML_SUCCESS) {
242  // No build attribute. Assuming build="0"
243  SYNTAX_WARNING(robotElem->Row()) << "\"robot\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
244  }
245 #else
246  int tmp;
247  if (robotElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) {
248  // No build attribute. Assuming build="0"
249  SYNTAX_WARNING(robotElem->Row()) << R"("robot" element should contain the "build" attribute [unsigned int]. Assuming 0)";
250  tmp = 0;
251  }
252  result.robot.build() = (unsigned)tmp;
253 #endif
254 
255  if (robotElem->QueryStringAttribute("portprefix", &result.robot.portprefix()) != TIXML_SUCCESS) {
256  SYNTAX_WARNING(robotElem->Row()) << R"("robot" element should contain the "portprefix" attribute. Using "name" attribute)";
257  result.robot.portprefix() = result.robot.name();
258  }
259 
260  // yDebug() << "Found robot [" << robot.name() << "] build [" << robot.build() << "] portprefix [" << robot.portprefix() << "]";
261 
262  for (TiXmlElement* childElem = robotElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
263  std::string elemString = childElem->ValueStr();
264  if (elemString == "device" || elemString == "devices") {
265  yarp::robotinterface::experimental::DeviceList childDevices = readDevices(childElem, result);
266  for (yarp::robotinterface::experimental::DeviceList::const_iterator it = childDevices.begin(); it != childDevices.end(); ++it) {
267  result.robot.devices().push_back(*it);
268  }
269  } else {
270  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
271  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
272  result.robot.params().push_back(*it);
273  }
274  }
275  }
276 
277  return result;
278 }
279 
280 
283 {
284  const std::string& valueStr = devicesElem->ValueStr();
285 
286  if (valueStr == "device") {
287  // yDebug() << valueStr;
289  deviceList.push_back(readDeviceTag(devicesElem, result));
290  return deviceList;
291  } else if (valueStr == "devices") {
292  // "devices"
293  return readDevicesTag(devicesElem, result);
294  } else {
295  SYNTAX_ERROR(devicesElem->Row()) << R"(Expected "device" or "devices". Found)" << valueStr;
296  result.parsingIsSuccessful = false;
297  }
299 }
300 
303 {
304  const std::string& valueStr = deviceElem->ValueStr();
305 
306  if (valueStr != "device") {
307  SYNTAX_ERROR(deviceElem->Row()) << "Expected \"device\". Found" << valueStr;
308  result.parsingIsSuccessful = false;
310  }
311 
313 
314  if (deviceElem->QueryStringAttribute("name", &device.name()) != TIXML_SUCCESS) {
315  SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "name" attribute)";
316  result.parsingIsSuccessful = false;
317  return device;
318  }
319 
320  // yDebug() << "Found device [" << device.name() << "]";
321 
322  if (deviceElem->QueryStringAttribute("type", &device.type()) != TIXML_SUCCESS) {
323  SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "type" attribute)";
324  result.parsingIsSuccessful = false;
325  return device;
326  }
327 
328  device.params().push_back(yarp::robotinterface::experimental::Param("robotName", result.robot.portprefix()));
329 
330  for (TiXmlElement* childElem = deviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
331  if (childElem->ValueStr() == "action" || childElem->ValueStr() == "actions") {
332  yarp::robotinterface::experimental::ActionList childActions = readActions(childElem, result);
333  for (yarp::robotinterface::experimental::ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) {
334  device.actions().push_back(*it);
335  }
336  } else {
337  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
338  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
339  device.params().push_back(*it);
340  }
341  }
342  }
343 
344  // yDebug() << device;
345  return device;
346 }
347 
350 {
351  //const std::string &valueStr = devicesElem->ValueStr();
352 
354  for (TiXmlElement* childElem = devicesElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
355  yarp::robotinterface::experimental::DeviceList childDevices = readDevices(childElem, result);
356  for (yarp::robotinterface::experimental::DeviceList::const_iterator it = childDevices.begin(); it != childDevices.end(); ++it) {
357  devices.push_back(*it);
358  }
359  }
360 
361  return devices;
362 }
363 
366 {
367  const std::string& valueStr = paramsElem->ValueStr();
368 
369  if (valueStr == "param") {
371  params.push_back(readParamTag(paramsElem, result));
372  return params;
373  } else if (valueStr == "group") {
375  params.push_back(readGroupTag(paramsElem, result));
376  return params;
377  } else if (valueStr == "paramlist") {
378  return readParamListTag(paramsElem, result);
379  } else if (valueStr == "subdevice") {
380  return readSubDeviceTag(paramsElem, result);
381  } else if (valueStr == "params") {
382  return readParamsTag(paramsElem, result);
383  } else {
384  SYNTAX_ERROR(paramsElem->Row()) << R"(Expected "param", "group", "paramlist", "subdevice", or "params". Found)" << valueStr;
385  result.parsingIsSuccessful = false;
386  }
388 }
389 
390 
393 {
394  if (paramElem->ValueStr() != "param") {
395  SYNTAX_ERROR(paramElem->Row()) << "Expected \"param\". Found" << paramElem->ValueStr();
396  result.parsingIsSuccessful = false;
398  }
399 
401 
402  if (paramElem->QueryStringAttribute("name", &param.name()) != TIXML_SUCCESS) {
403  SYNTAX_ERROR(paramElem->Row()) << R"("param" element should contain the "name" attribute)";
404  result.parsingIsSuccessful = false;
406  }
407 
408  // yDebug() << "Found param [" << param.name() << "]";
409 
410  const char* valueText = paramElem->GetText();
411  if (!valueText) {
412  SYNTAX_ERROR(paramElem->Row()) << R"("param" element should have a value [ "name" = )" << param.name() << "]";
413  result.parsingIsSuccessful = false;
415  }
416  param.value() = valueText;
417 
418  // yDebug() << param;
419  return param;
420 }
421 
424 {
425  if (groupElem->ValueStr() != "group") {
426  SYNTAX_ERROR(groupElem->Row()) << "Expected \"group\". Found" << groupElem->ValueStr();
427  result.parsingIsSuccessful = false;
429  }
430 
432 
433  if (groupElem->QueryStringAttribute("name", &group.name()) != TIXML_SUCCESS) {
434  SYNTAX_ERROR(groupElem->Row()) << R"("group" element should contain the "name" attribute)";
435  result.parsingIsSuccessful = false;
437  }
438 
439  // yDebug() << "Found group [" << group.name() << "]";
440 
442  for (TiXmlElement* childElem = groupElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
443  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
444  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
445  params.push_back(*it);
446  }
447  }
448  if (params.empty()) {
449  SYNTAX_ERROR(groupElem->Row()) << "\"group\" cannot be empty";
450  result.parsingIsSuccessful = false;
452  }
453 
454  std::string groupString;
455  for (auto& param : params) {
456  if (!groupString.empty()) {
457  groupString += " ";
458  }
459  groupString += "(" + param.name() + " " + param.value() + ")";
460  }
461 
462  group.value() = groupString;
463 
464  return group;
465 }
466 
469 {
470  if (paramListElem->ValueStr() != "paramlist") {
471  SYNTAX_ERROR(paramListElem->Row()) << "Expected \"paramlist\". Found" << paramListElem->ValueStr();
472  result.parsingIsSuccessful = false;
474  }
475 
478 
479  if (paramListElem->QueryStringAttribute("name", &mainparam.name()) != TIXML_SUCCESS) {
480  SYNTAX_ERROR(paramListElem->Row()) << R"("paramlist" element should contain the "name" attribute)";
481  result.parsingIsSuccessful = false;
483  }
484 
485  params.push_back(mainparam);
486 
487  // yDebug() << "Found paramlist [" << params.at(0).name() << "]";
488 
489  for (TiXmlElement* childElem = paramListElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
490  if (childElem->ValueStr() != "elem") {
491  SYNTAX_ERROR(childElem->Row()) << "Expected \"elem\". Found" << childElem->ValueStr();
492  result.parsingIsSuccessful = false;
494  }
495 
497 
498  if (childElem->QueryStringAttribute("name", &childParam.name()) != TIXML_SUCCESS) {
499  SYNTAX_ERROR(childElem->Row()) << R"("elem" element should contain the "name" attribute)";
500  result.parsingIsSuccessful = false;
502  }
503 
504  const char* valueText = childElem->GetText();
505  if (!valueText) {
506  SYNTAX_ERROR(childElem->Row()) << R"("elem" element should have a value [ "name" = )" << childParam.name() << "]";
507  result.parsingIsSuccessful = false;
509  }
510  childParam.value() = valueText;
511 
512  params.push_back(childParam);
513  }
514 
515  if (params.empty()) {
516  SYNTAX_ERROR(paramListElem->Row()) << "\"paramlist\" cannot be empty";
517  result.parsingIsSuccessful = false;
519  }
520 
521  // +1 skips the first element, that is the main param
522  for (auto it = params.begin() + 1; it != params.end(); ++it) {
524  params.at(0).value() += (params.at(0).value().empty() ? "(" : " ") + param.name();
525  }
526  params.at(0).value() += ")";
527 
528  // yDebug() << params;
529  return params;
530 }
531 
534 {
535  if (subDeviceElem->ValueStr() != "subdevice") {
536  SYNTAX_ERROR(subDeviceElem->Row()) << "Expected \"subdevice\". Found" << subDeviceElem->ValueStr();
537  result.parsingIsSuccessful = false;
539  }
540 
542 
543  //FIXME yarp::robotinterface::experimental::Param featIdParam;
545 
546  //FIXME featIdParam.name() = "FeatId";
547  subDeviceParam.name() = "subdevice";
548 
549  //FIXME if (subDeviceElem->QueryStringAttribute("name", &featIdParam.value()) != TIXML_SUCCESS) {
550  // SYNTAX_ERROR(subDeviceElem->Row()) << "\"subdevice\" element should contain the \"name\" attribute";
551  // }
552 
553  if (subDeviceElem->QueryStringAttribute("type", &subDeviceParam.value()) != TIXML_SUCCESS) {
554  SYNTAX_ERROR(subDeviceElem->Row()) << R"("subdevice" element should contain the "type" attribute)";
555  result.parsingIsSuccessful = false;
557  }
558 
559  //FIXME params.push_back(featIdParam);
560  params.push_back(subDeviceParam);
561 
562  // yDebug() << "Found subdevice [" << params.at(0).value() << "]";
563 
564  for (TiXmlElement* childElem = subDeviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
565  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
566  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
567  params.push_back(yarp::robotinterface::experimental::Param(it->name(), it->value()));
568  }
569  }
570 
571  // yDebug() << params;
572  return params;
573 }
574 
577 {
578  //const std::string &valueStr = paramsElem->ValueStr();
579 
581  for (TiXmlElement* childElem = paramsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
582  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
583  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
584  params.push_back(*it);
585  }
586  }
587 
588  return params;
589 }
590 
593 {
594  const std::string& valueStr = actionsElem->ValueStr();
595 
596  if (valueStr != "action" && valueStr != "actions") {
597  SYNTAX_ERROR(actionsElem->Row()) << R"(Expected "action" or "actions". Found)" << valueStr;
598  }
599 
600  if (valueStr == "action") {
602  actionList.push_back(readActionTag(actionsElem, result));
603  return actionList;
604  }
605  // "actions"
606  return readActionsTag(actionsElem, result);
607 }
608 
611 {
612  if (actionElem->ValueStr() != "action") {
613  SYNTAX_ERROR(actionElem->Row()) << "Expected \"action\". Found" << actionElem->ValueStr();
614  result.parsingIsSuccessful = false;
616  }
617 
619 
620  if (actionElem->QueryValueAttribute<yarp::robotinterface::experimental::ActionPhase>("phase", &action.phase()) != TIXML_SUCCESS || action.phase() == yarp::robotinterface::experimental::ActionPhaseUnknown) {
621  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "phase" attribute [startup|interrupt{1,2,3}|shutdown])";
622  result.parsingIsSuccessful = false;
624  }
625 
626 
627  if (actionElem->QueryValueAttribute<yarp::robotinterface::experimental::ActionType>("type", &action.type()) != TIXML_SUCCESS || action.type() == yarp::robotinterface::experimental::ActionTypeUnknown) {
628  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "type" attribute [configure|calibrate|attach|abort|detach|park|custom])";
629  result.parsingIsSuccessful = false;
631  }
632 
633  // yDebug() << "Found action [ ]";
634 
635 #if TINYXML_UNSIGNED_INT_BUG
636  if (actionElem->QueryUnsignedAttribute("level", &action.level()) != TIXML_SUCCESS) {
637  SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"level\" attribute [unsigned int]";
638  }
639 #else
640  int tmp;
641  if (actionElem->QueryIntAttribute("level", &tmp) != TIXML_SUCCESS || tmp < 0) {
642  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "level" attribute [unsigned int])";
643  result.parsingIsSuccessful = false;
645  }
646  action.level() = (unsigned)tmp;
647 #endif
648 
649  for (TiXmlElement* childElem = actionElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
650  yarp::robotinterface::experimental::ParamList childParams = readParams(childElem, result);
651  for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
652  action.params().push_back(*it);
653  }
654  }
655 
656  // yDebug() << action;
657  return action;
658 }
659 
662 {
663  //const std::string &valueStr = actionsElem->ValueStr();
664 
665  std::string robotName;
666  if (actionsElem->QueryStringAttribute("robot", &robotName) != TIXML_SUCCESS) {
667  SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "robot" attribute)";
668  }
669 
670  if (robotName != result.robot.name()) {
671  SYNTAX_WARNING(actionsElem->Row()) << "Trying to import a file for the wrong robot. Found" << robotName << "instead of" << result.robot.name();
672  }
673 
674  unsigned int build;
675 #if TINYXML_UNSIGNED_INT_BUG
676  if (actionsElem->QueryUnsignedAttribute("build", &build()) != TIXML_SUCCESS) {
677  // No build attribute. Assuming build="0"
678  SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
679  }
680 #else
681  int tmp;
682  if (actionsElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) {
683  // No build attribute. Assuming build="0"
684  SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "build" attribute [unsigned int]. Assuming 0)";
685  tmp = 0;
686  }
687  build = (unsigned)tmp;
688 #endif
689 
690  if (build != result.robot.build()) {
691  SYNTAX_WARNING(actionsElem->Row()) << "Import a file for a different robot build. Found" << build << "instead of" << result.robot.build();
692  }
693 
695  for (TiXmlElement* childElem = actionsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
696  yarp::robotinterface::experimental::ActionList childActions = readActions(childElem, result);
697  for (yarp::robotinterface::experimental::ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) {
698  actions.push_back(*it);
699  }
700  }
701 
702  return actions;
703 }
704 
705 
707 {
708  mPriv->verbose_output = verb;
709  return mPriv->readRobotFromFile(filename);
710 }
711 
713 {
714  mPriv->verbose_output = verb;
715  return mPriv->readRobotFromString(xmlString);
716 }
717 
718 
720  mPriv(new Private(this))
721 {
722 }
723 
725 {
726  if (mPriv) {
727  delete mPriv;
728  }
729 }
#define yError(...)
Definition: Log.h:282
#define yDebug(...)
Definition: Log.h:237
#define yFatal(...)
Definition: Log.h:293
#define SYNTAX_ERROR(line)
#define SYNTAX_WARNING(line)
Result of the parsing of XMLReader.
Definition: XMLReader.h:26
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
Definition: XMLReader.h:43
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
Definition: XMLReader.h:38
yarp::robotinterface::experimental::XMLReaderResult readRobotFromFile(const std::string &fileName)
yarp::robotinterface::experimental::Param readGroupTag(TiXmlElement *groupElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readParamListTag(TiXmlElement *paramListElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ActionList readActions(TiXmlElement *actionsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
bool PerformInclusions(TiXmlNode *pParent, const std::string &parent_fileName, const std::string &current_path)
yarp::robotinterface::experimental::DeviceList readDevicesTag(TiXmlElement *devicesElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readSubDeviceTag(TiXmlElement *subDeviceElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readParamsTag(TiXmlElement *paramsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readParams(TiXmlElement *paramsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::DeviceList readDevices(TiXmlElement *devicesElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::Param readParamTag(TiXmlElement *paramElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::Action readActionTag(TiXmlElement *actionElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::XMLReaderResult readRobotFromString(const std::string &xmlString)
yarp::robotinterface::experimental::ActionList readActionsTag(TiXmlElement *actionsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::Device readDeviceTag(TiXmlElement *deviceElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::XMLReaderResult readRobotTag(TiXmlElement *robotElem)
yarp::robotinterface::experimental::XMLReaderResult getRobotFromFile(const std::string &filename, bool verbose=false) override
yarp::robotinterface::experimental::XMLReaderResult getRobotFromString(const std::string &xmlString, bool verbose=false) override
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
std::vector< robotinterface::experimental::Action > ActionList
Definition: Types.h:35
std::vector< robotinterface::experimental::Device > DeviceList
Definition: Types.h:36
std::vector< robotinterface::experimental::Param > ParamList
Definition: Types.h:32
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)