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
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{
42public:
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";
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";
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
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";
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";
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:356
#define yDebug(...)
Definition: Log.h:270
#define yWarning(...)
Definition: Log.h:335
#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:56
bool parse(TiXmlUnknown *unknownNode, const std::string &curr_filename)
Result of the parsing of yarp::robotinterface::XMLReader.
Definition: XMLReader.h:26
static XMLReaderResult ParsingFailed()
Definition: XMLReader.h:28
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:21
std::string DocTypeToString(RobotInterfaceDTD::DocType doctype)