30 #define SYNTAX_ERROR(line) yFatal() << "Syntax error while loading" << curr_filename << "at line" << line << "."
31 #define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
36 #define TINYXML_UNSIGNED_INT_BUG 0
94 std::replace(filename.begin(), filename.end(),
'/',
'\\');
97 curr_filename = fileName;
99 path = filename.substr(0, filename.rfind(
"\\"));
101 path = filename.substr(0, filename.rfind(
'/'));
104 yDebug() <<
"Reading file" << filename.c_str();
105 auto* doc =
new TiXmlDocument(filename.c_str());
106 if (!doc->LoadFile()) {
111 if (!doc->RootElement()) {
117 for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
118 if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
119 if (dtd.parse(childNode->ToUnknown(), curr_filename)) {
126 SYNTAX_WARNING(doc->Row()) <<
"No DTD found. Assuming version yarprobotinterfaceV1.0";
136 if (dtd.majorVersion != 1 || dtd.minorVersion != 0) {
137 SYNTAX_WARNING(doc->Row()) <<
"Only yarprobotinterface DTD version 1.0 is supported";
151 curr_filename =
" XML runtime string ";
152 auto* doc =
new TiXmlDocument();
153 if (!doc->Parse(xmlString.c_str())) {
158 if (!doc->RootElement()) {
175 if (robotElem->ValueStr() !=
"robot") {
176 SYNTAX_ERROR(robotElem->Row()) <<
"Root element should be \"robot\". Found" << robotElem->ValueStr();
180 if (robotElem->QueryStringAttribute(
"name", &result.
robot.
name()) != TIXML_SUCCESS) {
181 SYNTAX_ERROR(robotElem->Row()) << R
"("robot" element should contain the "name" attribute)";
185 #if TINYXML_UNSIGNED_INT_BUG
186 if (robotElem->QueryUnsignedAttribute(
"build", &robot.build()) != TIXML_SUCCESS) {
188 SYNTAX_WARNING(robotElem->Row()) <<
"\"robot\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
192 if (robotElem->QueryIntAttribute(
"build", &tmp) != TIXML_SUCCESS || tmp < 0) {
194 SYNTAX_WARNING(robotElem->Row()) << R
"("robot" element should contain the "build" attribute [unsigned int]. Assuming 0)";
200 if (robotElem->QueryStringAttribute(
"portprefix", &result.
robot.
portprefix()) != TIXML_SUCCESS) {
201 SYNTAX_WARNING(robotElem->Row()) << R
"("robot" element should contain the "portprefix" attribute. Using "name" attribute)";
207 for (TiXmlElement* childElem = robotElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
208 if (childElem->ValueStr() ==
"device" || childElem->ValueStr() ==
"devices") {
210 for (yarp::robotinterface::experimental::DeviceList::const_iterator it = childDevices.begin(); it != childDevices.end(); ++it) {
215 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
228 const std::string& valueStr = devicesElem->ValueStr();
230 if (valueStr ==
"device") {
233 deviceList.push_back(readDeviceTag(devicesElem, result));
235 }
else if (valueStr ==
"devices") {
237 return readDevicesTag(devicesElem, result);
239 SYNTAX_ERROR(devicesElem->Row()) << R
"(Expected "device" or "devices". Found)" << valueStr;
248 const std::string& valueStr = deviceElem->ValueStr();
250 if (valueStr !=
"device") {
251 SYNTAX_ERROR(deviceElem->Row()) <<
"Expected \"device\". Found" << valueStr;
257 if (deviceElem->QueryStringAttribute(
"name", &device.
name()) != TIXML_SUCCESS) {
258 SYNTAX_ERROR(deviceElem->Row()) << R
"("device" element should contain the "name" attribute)";
264 if (deviceElem->QueryStringAttribute(
"type", &device.
type()) != TIXML_SUCCESS) {
265 SYNTAX_ERROR(deviceElem->Row()) << R
"("device" element should contain the "type" attribute)";
271 for (TiXmlElement* childElem = deviceElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
272 if (childElem->ValueStr() ==
"action" || childElem->ValueStr() ==
"actions") {
274 for (yarp::robotinterface::experimental::ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) {
275 device.
actions().push_back(*it);
279 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
280 device.
params().push_back(*it);
294 std::string filename;
295 if (devicesElem->QueryStringAttribute(
"file", &filename) == TIXML_SUCCESS) {
298 std::replace(filename.begin(), filename.end(),
'/',
'\\');
299 filename = path +
"\\" + filename;
301 filename = path +
"/" + filename;
303 return readDevicesFile(filename, result);
343 for (TiXmlElement* childElem = devicesElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
345 for (yarp::robotinterface::experimental::DeviceList::const_iterator it = childDevices.begin(); it != childDevices.end(); ++it) {
346 devices.push_back(*it);
356 std::string old_filename = curr_filename;
357 curr_filename = fileName;
359 yDebug() <<
"Reading file" << fileName.c_str();
360 auto* doc =
new TiXmlDocument(fileName.c_str());
361 if (!doc->LoadFile()) {
365 if (!doc->RootElement()) {
371 for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
372 if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
373 if (devicesFileDTD.
parse(childNode->ToUnknown(), curr_filename)) {
379 if (!devicesFileDTD.
valid()) {
380 SYNTAX_WARNING(doc->Row()) <<
"No DTD found. Assuming version yarprobotinterfaceV1.0";
391 SYNTAX_ERROR(doc->Row()) <<
"Trying to import a file with a different yarprobotinterface DTD version";
397 curr_filename = old_filename;
405 const std::string& valueStr = paramsElem->ValueStr();
407 if (valueStr ==
"param") {
409 params.push_back(readParamTag(paramsElem, result));
411 }
else if (valueStr ==
"group") {
413 params.push_back(readGroupTag(paramsElem, result));
415 }
else if (valueStr ==
"paramlist") {
416 return readParamListTag(paramsElem, result);
417 }
else if (valueStr ==
"subdevice") {
418 return readSubDeviceTag(paramsElem, result);
419 }
else if (valueStr ==
"params") {
420 return readParamsTag(paramsElem, result);
422 SYNTAX_ERROR(paramsElem->Row()) << R
"(Expected "param", "group", "paramlist", "subdevice", or "params". Found)" << valueStr;
431 if (paramElem->ValueStr() !=
"param") {
432 SYNTAX_ERROR(paramElem->Row()) <<
"Expected \"param\". Found" << paramElem->ValueStr();
438 if (paramElem->QueryStringAttribute(
"name", ¶m.
name()) != TIXML_SUCCESS) {
439 SYNTAX_ERROR(paramElem->Row()) << R
"("param" element should contain the "name" attribute)";
445 const char* valueText = paramElem->GetText();
447 SYNTAX_ERROR(paramElem->Row()) << R
"("param" element should have a value [ "name" = )" << param.name() << "]";
449 param.
value() = valueText;
459 if (groupElem->ValueStr() !=
"group") {
460 SYNTAX_ERROR(groupElem->Row()) <<
"Expected \"group\". Found" << groupElem->ValueStr();
466 if (groupElem->QueryStringAttribute(
"name", &group.
name()) != TIXML_SUCCESS) {
467 SYNTAX_ERROR(groupElem->Row()) << R
"("group" element should contain the "name" attribute)";
474 for (TiXmlElement* childElem = groupElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
476 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
477 params.push_back(*it);
480 if (params.empty()) {
481 SYNTAX_ERROR(groupElem->Row()) <<
"\"group\" cannot be empty";
484 std::string groupString;
485 for (
auto& param : params) {
486 if (!groupString.empty()) {
489 groupString +=
"(" + param.name() +
" " + param.value() +
")";
492 group.
value() = groupString;
500 if (paramListElem->ValueStr() !=
"paramlist") {
501 SYNTAX_ERROR(paramListElem->Row()) <<
"Expected \"paramlist\". Found" << paramListElem->ValueStr();
508 if (paramListElem->QueryStringAttribute(
"name", &mainparam.
name()) != TIXML_SUCCESS) {
509 SYNTAX_ERROR(paramListElem->Row()) << R
"("paramlist" element should contain the "name" attribute)";
513 params.push_back(mainparam);
517 for (TiXmlElement* childElem = paramListElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
518 if (childElem->ValueStr() !=
"elem") {
519 SYNTAX_ERROR(childElem->Row()) <<
"Expected \"elem\". Found" << childElem->ValueStr();
524 if (childElem->QueryStringAttribute(
"name", &childParam.
name()) != TIXML_SUCCESS) {
525 SYNTAX_ERROR(childElem->Row()) << R
"("elem" element should contain the "name" attribute)";
529 const char* valueText = childElem->GetText();
531 SYNTAX_ERROR(childElem->Row()) << R
"("elem" element should have a value [ "name" = )" << childParam.name() << "]";
534 childParam.
value() = valueText;
537 params.push_back(childParam);
540 if (params.empty()) {
541 SYNTAX_ERROR(paramListElem->Row()) <<
"\"paramlist\" cannot be empty";
546 for (
auto it = params.begin() + 1; it != params.end(); ++it) {
548 params.at(0).
value() += (params.at(0).value().empty() ?
"(" :
" ") + param.
name();
550 params.at(0).value() +=
")";
559 if (subDeviceElem->ValueStr() !=
"subdevice") {
560 SYNTAX_ERROR(subDeviceElem->Row()) <<
"Expected \"subdevice\". Found" << subDeviceElem->ValueStr();
570 subDeviceParam.
name() =
"subdevice";
576 if (subDeviceElem->QueryStringAttribute(
"type", &subDeviceParam.
value()) != TIXML_SUCCESS) {
577 SYNTAX_ERROR(subDeviceElem->Row()) << R
"("subdevice" element should contain the "type" attribute)";
581 params.push_back(subDeviceParam);
585 for (TiXmlElement* childElem = subDeviceElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
587 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
601 std::string filename;
602 if (paramsElem->QueryStringAttribute(
"file", &filename) == TIXML_SUCCESS) {
605 std::replace(filename.begin(), filename.end(),
'/',
'\\');
606 filename = path +
"\\" + filename;
608 filename = path +
"/" + filename;
610 return readParamsFile(filename, result);
644 for (TiXmlElement* childElem = paramsElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
646 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
647 params.push_back(*it);
657 std::string old_filename = curr_filename;
658 curr_filename = fileName;
660 yDebug() <<
"Reading file" << fileName.c_str();
661 auto* doc =
new TiXmlDocument(fileName.c_str());
662 if (!doc->LoadFile()) {
668 if (!doc->RootElement()) {
676 for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
677 if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
678 if (paramsFileDTD.
parse(childNode->ToUnknown(), curr_filename)) {
684 if (!paramsFileDTD.
valid()) {
685 SYNTAX_WARNING(doc->Row()) <<
"No DTD found. Assuming version yarprobotinterfaceV1.0";
696 SYNTAX_ERROR(doc->Row()) <<
"Trying to import a file with a different yarprobotinterface DTD version";
702 curr_filename = old_filename;
709 const std::string& valueStr = actionsElem->ValueStr();
711 if (valueStr !=
"action" && valueStr !=
"actions") {
712 SYNTAX_ERROR(actionsElem->Row()) << R
"(Expected "action" or "actions". Found)" << valueStr;
715 if (valueStr ==
"action") {
717 actionList.push_back(readActionTag(actionsElem, result));
721 return readActionsTag(actionsElem, result);
727 if (actionElem->ValueStr() !=
"action") {
728 SYNTAX_ERROR(actionElem->Row()) <<
"Expected \"action\". Found" << actionElem->ValueStr();
734 SYNTAX_ERROR(actionElem->Row()) << R
"("action" element should contain the "phase" attribute [startup|interrupt{1,2,3}|shutdown])";
739 SYNTAX_ERROR(actionElem->Row()) << R
"("action" element should contain the "type" attribute [configure|calibrate|attach|abort|detach|park|custom])";
744 #if TINYXML_UNSIGNED_INT_BUG
745 if (actionElem->QueryUnsignedAttribute(
"level", &action.
level()) != TIXML_SUCCESS) {
746 SYNTAX_ERROR(actionElem->Row()) <<
"\"action\" element should contain the \"level\" attribute [unsigned int]";
750 if (actionElem->QueryIntAttribute(
"level", &tmp) != TIXML_SUCCESS || tmp < 0) {
751 SYNTAX_ERROR(actionElem->Row()) << R
"("action" element should contain the "level" attribute [unsigned int])";
753 action.level() = (unsigned)tmp;
756 for (TiXmlElement* childElem = actionElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
758 for (yarp::robotinterface::experimental::ParamList::const_iterator it = childParams.begin(); it != childParams.end(); ++it) {
759 action.
params().push_back(*it);
772 std::string filename;
773 if (actionsElem->QueryStringAttribute(
"file", &filename) == TIXML_SUCCESS) {
776 std::replace(filename.begin(), filename.end(),
'/',
'\\');
777 filename = path +
"\\" + filename;
779 filename = path +
"/" + filename;
781 return readActionsFile(filename, result);
784 std::string robotName;
785 if (actionsElem->QueryStringAttribute(
"robot", &robotName) != TIXML_SUCCESS) {
786 SYNTAX_WARNING(actionsElem->Row()) << R
"("actions" element should contain the "robot" attribute)";
790 SYNTAX_WARNING(actionsElem->Row()) <<
"Trying to import a file for the wrong robot. Found" << robotName <<
"instead of" << result.
robot.
name();
794 #if TINYXML_UNSIGNED_INT_BUG
795 if (actionsElem->QueryUnsignedAttribute(
"build", &build()) != TIXML_SUCCESS) {
797 SYNTAX_WARNING(actionsElem->Row()) <<
"\"actions\" element should contain the \"build\" attribute [unsigned int]. Assuming 0";
801 if (actionsElem->QueryIntAttribute(
"build", &tmp) != TIXML_SUCCESS || tmp < 0) {
803 SYNTAX_WARNING(actionsElem->Row()) << R
"("actions" element should contain the "build" attribute [unsigned int]. Assuming 0)";
806 build = (unsigned)tmp;
810 SYNTAX_WARNING(actionsElem->Row()) <<
"Import a file for a different robot build. Found" << build <<
"instead of" << result.
robot.
build();
814 for (TiXmlElement* childElem = actionsElem->FirstChildElement(); childElem !=
nullptr; childElem = childElem->NextSiblingElement()) {
816 for (yarp::robotinterface::experimental::ActionList::const_iterator it = childActions.begin(); it != childActions.end(); ++it) {
817 actions.push_back(*it);
827 std::string old_filename = curr_filename;
828 curr_filename = fileName;
830 yDebug() <<
"Reading file" << fileName.c_str();
831 auto* doc =
new TiXmlDocument(fileName.c_str());
832 if (!doc->LoadFile()) {
836 if (!doc->RootElement()) {
842 for (TiXmlNode* childNode = doc->FirstChild(); childNode != 0; childNode = childNode->NextSibling()) {
843 if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
844 if (actionsFileDTD.
parse(childNode->ToUnknown(), curr_filename)) {
850 if (!actionsFileDTD.
valid()) {
851 SYNTAX_WARNING(doc->Row()) <<
"No DTD found. Assuming version yarprobotinterfaceV1.0";
862 SYNTAX_ERROR(doc->Row()) <<
"Trying to import a file with a different yarprobotinterface DTD version";
868 curr_filename = old_filename;
#define SYNTAX_ERROR(line)
#define SYNTAX_WARNING(line)
unsigned int majorVersion
bool parse(TiXmlUnknown *unknownNode, const std::string &curr_filename)
std::string & portprefix()
Result of the parsing of XMLReader.
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
static XMLReaderResult ParsingFailed()
yarp::robotinterface::experimental::DeviceList readDevicesFile(const std::string &fileName, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readParamListTag(TiXmlElement *paramListElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::DeviceList readDevices(TiXmlElement *devicesElem, 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::ActionList readActions(TiXmlElement *actionsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::Param readParamTag(TiXmlElement *paramElem, yarp::robotinterface::experimental::XMLReaderResult &result)
std::string curr_filename
yarp::robotinterface::experimental::ActionList readActionsFile(const std::string &fileName, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ParamList readParamsTag(TiXmlElement *paramsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
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::XMLReaderResult readRobotFromString(const std::string &xmlString)
XMLReaderFileV1 *const parent
yarp::robotinterface::experimental::XMLReaderResult readRobotFromFile(const std::string &fileName)
yarp::robotinterface::experimental::ParamList readParams(TiXmlElement *paramsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::ActionList readActionsTag(TiXmlElement *actionsElem, yarp::robotinterface::experimental::XMLReaderResult &result)
yarp::robotinterface::experimental::Action readActionTag(TiXmlElement *actionElem, yarp::robotinterface::experimental::XMLReaderResult &result)
unsigned int majorVersion
Private(XMLReaderFileV1 *parent)
yarp::robotinterface::experimental::Param readGroupTag(TiXmlElement *groupElem, yarp::robotinterface::experimental::XMLReaderResult &result)
unsigned int minorVersion
yarp::robotinterface::experimental::ParamList readParamsFile(const std::string &fileName, yarp::robotinterface::experimental::XMLReaderResult &result)
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
~XMLReaderFileV1() override
std::vector< robotinterface::experimental::Action > ActionList
std::vector< robotinterface::experimental::Device > DeviceList
std::vector< robotinterface::experimental::Param > ParamList
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)