YARP
Yet Another Robot Platform
XMLReader.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 
21 
22 #include <yarp/conf/filesystem.h>
23 
24 #include <yarp/os/LogStream.h>
25 #include <yarp/os/Property.h>
26 
27 #include <algorithm>
28 #include <iterator>
29 #include <memory>
30 #include <sstream>
31 #include <string>
32 #include <tinyxml.h>
33 #include <vector>
34 
35 #define SYNTAX_ERROR(line) yError() << "Syntax error while loading" << curr_filename << "at line" << line << "."
36 #define SYNTAX_WARNING(line) yWarning() << "Invalid syntax while loading" << curr_filename << "at line" << line << "."
37 
38 // BUG in TinyXML, see
39 // https://sourceforge.net/tracker/?func=detail&aid=3567726&group_id=13559&atid=113559
40 // When this bug is fixed upstream we can enable this
41 #define TINYXML_UNSIGNED_INT_BUG 0
42 
44 {
45 public:
47  {
48  delete mReader;
49  }
50 
51  bool verbose{false};
52  bool enable_deprecated{false};
54 };
55 
56 
58  mPriv(new Private)
59 {
60 }
61 
63 {
64  delete mPriv;
65 }
66 
68 {
69  mPriv->verbose = verb;
70 }
71 
73 {
74  mPriv->enable_deprecated = enab;
75 }
76 
78 {
79  std::string filename = fileName;
80 #if defined(_WIN32)
81  std::replace(filename.begin(), filename.end(), '/', '\\');
82 #endif
83  std::string curr_filename = fileName;
84  std::string path = filename.substr(0, filename.rfind(yarp::conf::filesystem::preferred_separator));
85 
86  yDebug() << "Reading file" << filename.c_str();
87  auto* doc = new TiXmlDocument(filename.c_str());
88  if (!doc->LoadFile()) {
89  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
91  }
92 
93  if (!doc->RootElement()) {
94  SYNTAX_ERROR(doc->Row()) << "No root element.";
96  }
97 
99 
100  for (TiXmlNode* childNode = doc->FirstChild(); childNode != nullptr; 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 yarprobotinterfaceV3.0";
110  dtd.setDefault();
112  }
113 
115  SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot)
116  << ". Found" << DocTypeToString(dtd.type);
117  }
118 
119  if (dtd.majorVersion == 1) {
120  yError() << "DTD V1.x has been deprecated. Please update your configuration files to DTD v3.x";
121  if (mPriv->enable_deprecated) {
122  yWarning() << "yarprobotinterface: using DEPRECATED xml parser for DTD v1.x";
123  mPriv->mReader = new yarp::robotinterface::impl::XMLReaderFileV1;
124  return mPriv->mReader->getRobotFromFile(filename, mPriv->verbose);
125  } else {
126  yError("Invalid DTD version, execution stopped.");
128  }
129  } else if (dtd.majorVersion == 3) {
130  yDebug() << "yarprobotinterface: using xml parser for DTD v3.x";
131  mPriv->mReader = new yarp::robotinterface::impl::XMLReaderFileV3;
132  return mPriv->mReader->getRobotFromFile(filename, mPriv->verbose);
133  }
134 
135  //ERROR HERE
136  yError("Invalid DTD version. Unable to choose parser for DTD.major: %d", dtd.majorVersion);
138 }
139 
141 {
142  std::string curr_filename = " XML runtime string ";
143  std::unique_ptr<TiXmlDocument> doc = std::make_unique<TiXmlDocument>();
144  if (!doc->Parse(xmlString.data())) {
145  SYNTAX_ERROR(doc->ErrorRow()) << doc->ErrorDesc();
147  }
148  if (!doc->RootElement()) {
149  SYNTAX_ERROR(doc->Row()) << "No root element.";
151  }
152 
153  RobotInterfaceDTD dtd;
154 
155  for (TiXmlNode* childNode = doc->FirstChild(); childNode != nullptr; childNode = childNode->NextSibling()) {
156  if (childNode->Type() == TiXmlNode::TINYXML_UNKNOWN) {
157  std::string curr_filename = " XML runtime string ";
158  if (dtd.parse(childNode->ToUnknown(), curr_filename)) {
159  break;
160  }
161  }
162  }
163 
164  if (!dtd.valid()) {
165  SYNTAX_WARNING(doc->Row()) << "No DTD found. Assuming version yarprobotinterfaceV3.0";
166  dtd.setDefault();
168  }
169 
171  SYNTAX_WARNING(doc->Row()) << "Expected document of type" << DocTypeToString(RobotInterfaceDTD::DocTypeRobot)
172  << ". Found" << DocTypeToString(dtd.type);
173  }
174 
175  if (dtd.majorVersion == 1) {
176  yError() << "DTD V1.x has been deprecated. Please update your configuration files to DTD v3.x";
177  if (mPriv->enable_deprecated) {
178  yWarning() << "yarprobotinterface: using DEPRECATED xml parser for DTD v1.x";
179  mPriv->mReader = new yarp::robotinterface::impl::XMLReaderFileV1;
180  return mPriv->mReader->getRobotFromString(xmlString, mPriv->verbose);
181  } else {
182  yError("Invalid DTD version, execution stopped.");
184  }
185  } else if (dtd.majorVersion == 3) {
186  yDebug() << "yarprobotinterface: using xml parser for DTD v3.x";
187  mPriv->mReader = new yarp::robotinterface::impl::XMLReaderFileV3;
188  return mPriv->mReader->getRobotFromString(xmlString, mPriv->verbose);
189  }
190 
191  //ERROR HERE
192  yError("Invalid DTD version. Unable to choose parser for DTD.major: %d", dtd.majorVersion);
194 }
#define yError(...)
Definition: Log.h:282
#define yDebug(...)
Definition: Log.h:237
#define yWarning(...)
Definition: Log.h:271
#define SYNTAX_ERROR(line)
Definition: XMLReader.cpp:35
#define SYNTAX_WARNING(line)
Definition: XMLReader.cpp:36
bool parse(TiXmlUnknown *unknownNode, const std::string &curr_filename)
Result of the parsing of XMLReader.
Definition: XMLReader.h:26
yarp::robotinterface::impl::XMLReaderFileVx * mReader
Definition: XMLReader.cpp:53
XMLReaderResult getRobotFromString(const std::string &xmlString)
Parse the XML description of a robotinterface from a string.
Definition: XMLReader.cpp:140
XMLReaderResult getRobotFromFile(const std::string &filename)
Parse the XML description of a robotinterface from a file.
Definition: XMLReader.cpp:77
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
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
static constexpr value_type preferred_separator
Definition: filesystem.h:28
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)