YARP
Yet Another Robot Platform
XMLReaderFileV3.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
7 
14 
15 #include <yarp/os/LogStream.h>
16 #include <yarp/os/Network.h>
17 #include <yarp/os/Property.h>
18 
19 #include <algorithm>
20 #include <iterator>
21 #include <sstream>
22 #include <string>
23 #include <tinyxml.h>
24 #include <vector>
25 
26 #define SYNTAX_ERROR(line) yError() << "Syntax error while loading" << curr_filename << "at line" << line << "."
27 #define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
28 
29 // BUG in TinyXML, see
30 // https://sourceforge.net/tracker/?func=detail&aid=3567726&group_id=13559&atid=113559
31 // When this bug is fixed upstream we can enable this
32 #define TINYXML_UNSIGNED_INT_BUG 0
33 
35 {
36 public:
37  explicit Private(XMLReaderFileV3* parent);
38  virtual ~Private();
39 
40  yarp::robotinterface::XMLReaderResult readRobotFromFile(const std::string& fileName);
41  yarp::robotinterface::XMLReaderResult readRobotFromString(const std::string& xmlString);
42  yarp::robotinterface::XMLReaderResult readRobotTag(TiXmlElement* robotElem);
43 
47 
54 
58 
59  bool PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path);
60 
62 
63 #ifdef USE_DTD
65 #endif
66 
69  std::string curr_filename;
70  unsigned int minorVersion;
71  unsigned int majorVersion;
72 };
73 
74 
76  parent(p),
77  minorVersion(0),
78  majorVersion(0)
79 {
80  verbose_output = false;
81 }
82 
84 
86 {
87  yDebug() << "Reading file" << fileName.c_str();
88  auto* doc = new TiXmlDocument(fileName.c_str());
89  if (!doc->LoadFile()) {
90  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
92  }
93 
94  if (!doc->RootElement()) {
95  SYNTAX_ERROR(doc->Row()) << "No root element.";
97  }
98 
99 #ifdef USE_DTD
100  for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
101  if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
102  if (dtd.parse(childNode->ToUnknown(), curr_filename)) {
103  break;
104  }
105  }
106  }
107 
108  if (!dtd.valid()) {
109  SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version yarprobotinterfaceV1.0";
110  dtd.setDefault();
112  }
113 
114  if (dtd.type != RobotInterfaceDTD::DocTypeRobot) {
115  SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot)
116  << ". Found" << DocTypeToString(dtd.type);
117  }
118 
119  if (dtd.majorVersion != 1 || dtd.minorVersion != 0) {
120  SYNTAX_WARNING(doc->Row()) << "Only yarprobotinterface DTD version 1.0 is supported";
121  }
122 #endif
123 
124  std::string current_path;
125  current_path = fileName.substr(0, fileName.find_last_of("\\/"));
126  std::string current_filename;
127  std::string log_filename;
128  current_filename = fileName.substr(fileName.find_last_of("\\/") + 1);
129  log_filename = current_filename.substr(0, current_filename.find(".xml"));
130  log_filename += "_preprocessor_log.xml";
131  double start_time = yarp::os::Time::now();
132  PerformInclusions(doc->RootElement(), current_filename, current_path);
133  double end_time = yarp::os::Time::now();
134  std::string full_log_withpath = current_path + std::string("\\") + log_filename;
135  std::replace(full_log_withpath.begin(), full_log_withpath.end(), '\\', '/');
136  yDebug() << "Preprocessor complete in: " << end_time - start_time << "s";
137  if (verbose_output) {
138  yDebug() << "Preprocessor output stored in: " << full_log_withpath;
139  doc->SaveFile(full_log_withpath);
140  }
141  yarp::robotinterface::XMLReaderResult result = readRobotTag(doc->RootElement());
142  delete doc;
143 
144  // yDebug() << robot;
145 
146  return result;
147 }
148 
150 {
151  curr_filename = " XML runtime string ";
152  auto* doc = new TiXmlDocument();
153  if (!doc->Parse(xmlString.c_str())) {
154  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
156  }
157 
158  if (!doc->RootElement()) {
159  SYNTAX_ERROR(doc->Row()) << "No root element.";
161  }
162 
163  yarp::robotinterface::XMLReaderResult result = readRobotTag(doc->RootElement());
164  delete doc;
165 
166  return result;
167 }
168 
169 bool yarp::robotinterface::impl::XMLReaderFileV3::Private::PerformInclusions(TiXmlNode* pParent, const std::string& parent_fileName, const std::string& current_path)
170 {
171 loop_start: //goto label
172  for (TiXmlElement* childElem = pParent->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
173 #ifdef DEBUG_PARSER
174  std::string a;
175  if (childElem->FirstAttribute())
176  a = childElem->FirstAttribute()->Value();
177  yDebug() << "Parsing" << childElem->Value() << a;
178 #endif
179  std::string elemString = childElem->ValueStr();
180  if (elemString == "file") {
181  yFatal() << "'file' attribute is forbidden in yarprobotinterface DTD format 3.0. Error found in " << parent_fileName;
182  return false;
183  }
184 
185  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() = static_cast<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  for (const auto& childDevice : readDevices(childElem, result)) {
266  result.robot.devices().push_back(childDevice);
267  }
268  } else {
269  for (const auto& childParam : readParams(childElem, result)) {
270  result.robot.params().push_back(childParam);
271  }
272  }
273  }
274 
275  return result;
276 }
277 
278 
281 {
282  const std::string& valueStr = devicesElem->ValueStr();
283 
284  if (valueStr == "device") {
285  // yDebug() << valueStr;
287  deviceList.push_back(readDeviceTag(devicesElem, result));
288  return deviceList;
289  }
290  if (valueStr == "devices") {
291  // "devices"
292  return readDevicesTag(devicesElem, result);
293  }
294 
295  SYNTAX_ERROR(devicesElem->Row()) << R"(Expected "device" or "devices". Found)" << valueStr;
296  result.parsingIsSuccessful = false;
298 }
299 
302 {
303  const std::string& valueStr = deviceElem->ValueStr();
304 
305  if (valueStr != "device") {
306  SYNTAX_ERROR(deviceElem->Row()) << "Expected \"device\". Found" << valueStr;
307  result.parsingIsSuccessful = false;
309  }
310 
312 
313  if (deviceElem->QueryStringAttribute("name", &device.name()) != TIXML_SUCCESS) {
314  SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "name" attribute)";
315  result.parsingIsSuccessful = false;
316  return device;
317  }
318 
319  // yDebug() << "Found device [" << device.name() << "]";
320 
321  if (deviceElem->QueryStringAttribute("type", &device.type()) != TIXML_SUCCESS) {
322  SYNTAX_ERROR(deviceElem->Row()) << R"("device" element should contain the "type" attribute)";
323  result.parsingIsSuccessful = false;
324  return device;
325  }
326 
327  device.params().push_back(yarp::robotinterface::Param("robotName", result.robot.portprefix()));
328 
329  for (TiXmlElement* childElem = deviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
330  if (childElem->ValueStr() == "action" || childElem->ValueStr() == "actions") {
331  for (const auto& childAction : readActions(childElem, result)) {
332  device.actions().push_back(childAction);
333  }
334  } else {
335  for (const auto& childParam : readParams(childElem, result)) {
336  device.params().push_back(childParam);
337  }
338  }
339  }
340 
341  // yDebug() << device;
342  return device;
343 }
344 
347 {
348  //const std::string &valueStr = devicesElem->ValueStr();
349 
351  for (TiXmlElement* childElem = devicesElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
352  for (const auto& childDevice : readDevices(childElem, result)) {
353  devices.push_back(childDevice);
354  }
355  }
356 
357  return devices;
358 }
359 
362 {
363  const std::string& valueStr = paramsElem->ValueStr();
364 
365  if (valueStr == "param") {
367  params.push_back(readParamTag(paramsElem, result));
368  return params;
369  }
370  if (valueStr == "group") {
372  params.push_back(readGroupTag(paramsElem, result));
373  return params;
374  }
375  if (valueStr == "paramlist") {
376  return readParamListTag(paramsElem, result);
377  }
378  if (valueStr == "subdevice") {
379  return readSubDeviceTag(paramsElem, result);
380  }
381  if (valueStr == "params") {
382  return readParamsTag(paramsElem, result);
383  }
384 
385  SYNTAX_ERROR(paramsElem->Row()) << R"(Expected "param", "group", "paramlist", "subdevice", or "params". Found)" << valueStr;
386  result.parsingIsSuccessful = false;
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 
417  std::string extern_name;
418  if (paramElem->QueryStringAttribute("extern-name", &extern_name) == TIXML_SUCCESS && config && config->check(extern_name)) {
419  // FIXME Check DTD >= 3.1
420  param.value() = config->find(extern_name).toString();
421  } else {
422  param.value() = valueText;
423  }
424 
425  // yDebug() << param;
426  return param;
427 }
428 
431 {
432  if (groupElem->ValueStr() != "group") {
433  SYNTAX_ERROR(groupElem->Row()) << "Expected \"group\". Found" << groupElem->ValueStr();
434  result.parsingIsSuccessful = false;
436  }
437 
438  yarp::robotinterface::Param group(true);
439 
440  if (groupElem->QueryStringAttribute("name", &group.name()) != TIXML_SUCCESS) {
441  SYNTAX_ERROR(groupElem->Row()) << R"("group" element should contain the "name" attribute)";
442  result.parsingIsSuccessful = false;
444  }
445 
446  // yDebug() << "Found group [" << group.name() << "]";
447 
449  for (TiXmlElement* childElem = groupElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
450  for (const auto& childParam : readParams(childElem, result)) {
451  params.push_back(childParam);
452  }
453  }
454  if (params.empty()) {
455  SYNTAX_ERROR(groupElem->Row()) << "\"group\" cannot be empty";
456  result.parsingIsSuccessful = false;
458  }
459 
460  std::string groupString;
461  for (auto& param : params) {
462  if (!groupString.empty()) {
463  groupString += " ";
464  }
465  groupString += "(" + param.name() + " " + param.value() + ")";
466  }
467 
468  group.value() = groupString;
469 
470  return group;
471 }
472 
475 {
476  if (paramListElem->ValueStr() != "paramlist") {
477  SYNTAX_ERROR(paramListElem->Row()) << "Expected \"paramlist\". Found" << paramListElem->ValueStr();
478  result.parsingIsSuccessful = false;
480  }
481 
483  yarp::robotinterface::Param mainparam;
484 
485  if (paramListElem->QueryStringAttribute("name", &mainparam.name()) != TIXML_SUCCESS) {
486  SYNTAX_ERROR(paramListElem->Row()) << R"("paramlist" element should contain the "name" attribute)";
487  result.parsingIsSuccessful = false;
489  }
490 
491  params.push_back(mainparam);
492 
493  // yDebug() << "Found paramlist [" << params.at(0).name() << "]";
494 
495  for (TiXmlElement* childElem = paramListElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
496  if (childElem->ValueStr() != "elem") {
497  SYNTAX_ERROR(childElem->Row()) << "Expected \"elem\". Found" << childElem->ValueStr();
498  result.parsingIsSuccessful = false;
500  }
501 
502  yarp::robotinterface::Param childParam;
503 
504  if (childElem->QueryStringAttribute("name", &childParam.name()) != TIXML_SUCCESS) {
505  SYNTAX_ERROR(childElem->Row()) << R"("elem" element should contain the "name" attribute)";
506  result.parsingIsSuccessful = false;
508  }
509 
510  const char* valueText = childElem->GetText();
511  if (!valueText) {
512  SYNTAX_ERROR(childElem->Row()) << R"("elem" element should have a value [ "name" = )" << childParam.name() << "]";
513  result.parsingIsSuccessful = false;
515  }
516  childParam.value() = valueText;
517 
518  params.push_back(childParam);
519  }
520 
521  if (params.empty()) {
522  SYNTAX_ERROR(paramListElem->Row()) << "\"paramlist\" cannot be empty";
523  result.parsingIsSuccessful = false;
525  }
526 
527  // +1 skips the first element, that is the main param
528  for (auto it = params.begin() + 1; it != params.end(); ++it) {
529  yarp::robotinterface::Param& param = *it;
530  params.at(0).value() += (params.at(0).value().empty() ? "(" : " ") + param.name();
531  }
532  params.at(0).value() += ")";
533 
534  // yDebug() << params;
535  return params;
536 }
537 
540 {
541  if (subDeviceElem->ValueStr() != "subdevice") {
542  SYNTAX_ERROR(subDeviceElem->Row()) << "Expected \"subdevice\". Found" << subDeviceElem->ValueStr();
543  result.parsingIsSuccessful = false;
545  }
546 
548 
549  //FIXME yarp::robotinterface::Param featIdParam;
550  yarp::robotinterface::Param subDeviceParam;
551 
552  //FIXME featIdParam.name() = "FeatId";
553  subDeviceParam.name() = "subdevice";
554 
555  //FIXME if (subDeviceElem->QueryStringAttribute("name", &featIdParam.value()) != TIXML_SUCCESS) {
556  // SYNTAX_ERROR(subDeviceElem->Row()) << "\"subdevice\" element should contain the \"name\" attribute";
557  // }
558 
559  if (subDeviceElem->QueryStringAttribute("type", &subDeviceParam.value()) != TIXML_SUCCESS) {
560  SYNTAX_ERROR(subDeviceElem->Row()) << R"("subdevice" element should contain the "type" attribute)";
561  result.parsingIsSuccessful = false;
563  }
564 
565  //FIXME params.push_back(featIdParam);
566  params.push_back(subDeviceParam);
567 
568  // yDebug() << "Found subdevice [" << params.at(0).value() << "]";
569 
570  for (TiXmlElement* childElem = subDeviceElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
571  for (const auto& childParam : readParams(childElem, result)) {
572  params.push_back(yarp::robotinterface::Param(childParam.name(), childParam.value()));
573  }
574  }
575 
576  // yDebug() << params;
577  return params;
578 }
579 
582 {
583  //const std::string &valueStr = paramsElem->ValueStr();
584 
586  for (TiXmlElement* childElem = paramsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
587  for (const auto & childParam : readParams(childElem, result)) {
588  params.push_back(childParam);
589  }
590  }
591 
592  return params;
593 }
594 
597 {
598  const std::string& valueStr = actionsElem->ValueStr();
599 
600  if (valueStr != "action" && valueStr != "actions") {
601  SYNTAX_ERROR(actionsElem->Row()) << R"(Expected "action" or "actions". Found)" << valueStr;
602  }
603 
604  if (valueStr == "action") {
606  actionList.push_back(readActionTag(actionsElem, result));
607  return actionList;
608  }
609  // "actions"
610  return readActionsTag(actionsElem, result);
611 }
612 
615 {
616  if (actionElem->ValueStr() != "action") {
617  SYNTAX_ERROR(actionElem->Row()) << "Expected \"action\". Found" << actionElem->ValueStr();
618  result.parsingIsSuccessful = false;
620  }
621 
623 
624  if (actionElem->QueryValueAttribute<yarp::robotinterface::ActionPhase>("phase", &action.phase()) != TIXML_SUCCESS || action.phase() == yarp::robotinterface::ActionPhaseUnknown) {
625  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "phase" attribute [startup|interrupt{1,2,3}|shutdown])";
626  result.parsingIsSuccessful = false;
628  }
629 
630 
631  if (actionElem->QueryValueAttribute<yarp::robotinterface::ActionType>("type", &action.type()) != TIXML_SUCCESS || action.type() == yarp::robotinterface::ActionTypeUnknown) {
632  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "type" attribute [configure|calibrate|attach|abort|detach|park|custom])";
633  result.parsingIsSuccessful = false;
635  }
636 
637  // yDebug() << "Found action [ ]";
638 
639 #if TINYXML_UNSIGNED_INT_BUG
640  if (actionElem->QueryUnsignedAttribute("level", &action.level()) != TIXML_SUCCESS) {
641  SYNTAX_ERROR(actionElem->Row()) << "\"action\" element should contain the \"level\" attribute [unsigned int]";
642  }
643 #else
644  int tmp;
645  if (actionElem->QueryIntAttribute("level", &tmp) != TIXML_SUCCESS || tmp < 0) {
646  SYNTAX_ERROR(actionElem->Row()) << R"("action" element should contain the "level" attribute [unsigned int])";
647  result.parsingIsSuccessful = false;
649  }
650  action.level() = static_cast<unsigned>(tmp);
651 #endif
652 
653  for (TiXmlElement* childElem = actionElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
654  for (const auto& childParam : readParams(childElem, result)) {
655  action.params().push_back(childParam);
656  }
657  }
658 
659  // yDebug() << action;
660  return action;
661 }
662 
665 {
666  //const std::string &valueStr = actionsElem->ValueStr();
667 
668  std::string robotName;
669  if (actionsElem->QueryStringAttribute("robot", &robotName) != TIXML_SUCCESS) {
670  SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "robot" attribute)";
671  }
672 
673  if (robotName != result.robot.name()) {
674  SYNTAX_WARNING(actionsElem->Row()) << "Trying to import a file for the wrong robot. Found" << robotName << "instead of" << result.robot.name();
675  }
676 
677  unsigned int build;
678 #if TINYXML_UNSIGNED_INT_BUG
679  if (actionsElem->QueryUnsignedAttribute("build", &build()) != TIXML_SUCCESS) {
680  // No build attribute. Assuming build="0"
681  SYNTAX_WARNING(actionsElem->Row()) << "\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
682  }
683 #else
684  int tmp;
685  if (actionsElem->QueryIntAttribute("build", &tmp) != TIXML_SUCCESS || tmp < 0) {
686  // No build attribute. Assuming build="0"
687  SYNTAX_WARNING(actionsElem->Row()) << R"("actions" element should contain the "build" attribute [unsigned int]. Assuming 0)";
688  tmp = 0;
689  }
690  build = static_cast<unsigned>(tmp);
691 #endif
692 
693  if (build != result.robot.build()) {
694  SYNTAX_WARNING(actionsElem->Row()) << "Import a file for a different robot build. Found" << build << "instead of" << result.robot.build();
695  }
696 
698  for (TiXmlElement* childElem = actionsElem->FirstChildElement(); childElem != nullptr; childElem = childElem->NextSiblingElement()) {
699  for (const auto & childAction : readActions(childElem, result)) {
700  actions.push_back(childAction);
701  }
702  }
703 
704  return actions;
705 }
706 
707 
709  const yarp::os::Searchable& config,
710  bool verb)
711 {
712  mPriv->config = &config;
713  mPriv->verbose_output = verb;
714  auto ret = mPriv->readRobotFromFile(filename);
715  mPriv->config = nullptr;
716  return ret;
717 }
718 
720  const yarp::os::Searchable& config,
721  bool verb)
722 {
723  mPriv->config = &config;
724  mPriv->verbose_output = verb;
725  auto ret = mPriv->readRobotFromString(xmlString);
726  mPriv->config = nullptr;
727  return ret;
728 }
729 
730 
732  mPriv(new Private(this))
733 {
734 }
735 
737 {
738  delete mPriv;
739 }
bool ret
#define yError(...)
Definition: Log.h:279
#define yDebug(...)
Definition: Log.h:234
#define yFatal(...)
Definition: Log.h:290
#define SYNTAX_ERROR(line)
#define SYNTAX_WARNING(line)
A base class for nested structures that can be searched.
Definition: Searchable.h:66
unsigned int & level()
Definition: Action.cpp:102
ActionPhase & phase()
Definition: Action.cpp:92
ActionList & actions()
Definition: Device.cpp:269
std::string & type()
Definition: Device.cpp:259
std::string & name()
Definition: Device.cpp:254
std::string & name()
Definition: Param.cpp:80
std::string & value()
Definition: Param.cpp:85
std::string & portprefix()
Definition: Robot.cpp:481
DeviceList & devices()
Definition: Robot.cpp:513
ParamList & params()
Definition: Robot.cpp:508
std::string & name()
Definition: Robot.cpp:471
unsigned int & build()
Definition: Robot.cpp:476
Result of the parsing of XMLReader.
Definition: XMLReader.h:25
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
Definition: XMLReader.h:37
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
Definition: XMLReader.h:42
static XMLReaderResult ParsingFailed()
Definition: XMLReader.h:27
yarp::robotinterface::Device readDeviceTag(TiXmlElement *deviceElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::Param readParamTag(TiXmlElement *paramElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::XMLReaderResult readRobotFromString(const std::string &xmlString)
yarp::robotinterface::ActionList readActionsTag(TiXmlElement *actionsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readSubDeviceTag(TiXmlElement *subDeviceElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::DeviceList readDevices(TiXmlElement *devicesElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParamListTag(TiXmlElement *paramListElem, yarp::robotinterface::XMLReaderResult &result)
bool PerformInclusions(TiXmlNode *pParent, const std::string &parent_fileName, const std::string &current_path)
yarp::robotinterface::XMLReaderResult readRobotTag(TiXmlElement *robotElem)
yarp::robotinterface::Param readGroupTag(TiXmlElement *groupElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParams(TiXmlElement *paramsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::DeviceList readDevicesTag(TiXmlElement *devicesElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ActionList readActions(TiXmlElement *actionsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::Action readActionTag(TiXmlElement *actionElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::ParamList readParamsTag(TiXmlElement *paramsElem, yarp::robotinterface::XMLReaderResult &result)
yarp::robotinterface::XMLReaderResult readRobotFromFile(const std::string &fileName)
yarp::robotinterface::XMLReaderResult getRobotFromString(const std::string &xmlString, const yarp::os::Searchable &config, bool verbose=false) override
yarp::robotinterface::XMLReaderResult getRobotFromFile(const std::string &filename, const yarp::os::Searchable &config, bool verbose=false) override
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
yarp::robotinterface::Param Param
Definition: Param.h:26
yarp::robotinterface::Device Device
Definition: Device.h:31
yarp::robotinterface::Action Action
Definition: Action.h:26
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)
std::vector< robotinterface::Action > ActionList
Definition: Types.h:31
std::vector< robotinterface::Param > ParamList
Definition: Types.h:28
std::vector< robotinterface::Device > DeviceList
Definition: Types.h:32