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