Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
XMLSubSys.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2002-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
20// Utility methods for initialising, closing and using the XML-subsystem
21/****************************************************************************/
22#include <config.h>
23
24#include <cstdint>
25#include <xercesc/util/PlatformUtils.hpp>
26#include <xercesc/util/TransService.hpp>
27#include <xercesc/util/TranscodingException.hpp>
28#include <xercesc/util/XMLString.hpp>
29#include <xercesc/sax2/XMLReaderFactory.hpp>
30#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
35#include "SUMOSAXHandler.h"
36#include "SUMOSAXReader.h"
37#include "XMLSubSys.h"
38
39using XERCES_CPP_NAMESPACE::SAX2XMLReader;
40using XERCES_CPP_NAMESPACE::XMLPlatformUtils;
41using XERCES_CPP_NAMESPACE::XMLReaderFactory;
42
43
44// ===========================================================================
45// static member variables
46// ===========================================================================
47std::vector<SUMOSAXReader*> XMLSubSys::myReaders;
49std::string XMLSubSys::myValidationScheme = "local";
50std::string XMLSubSys::myNetValidationScheme = "local";
51std::string XMLSubSys::myRouteValidationScheme = "local";
52XERCES_CPP_NAMESPACE::XMLGrammarPool* XMLSubSys::myGrammarPool = nullptr;
54XERCES_CPP_NAMESPACE::XMLLCPTranscoder* XMLSubSys::myLCPTranscoder = nullptr;
55
56
57// ===========================================================================
58// method definitions
59// ===========================================================================
60void
62 try {
63 XMLPlatformUtils::Initialize();
65 } catch (const XERCES_CPP_NAMESPACE::XMLException& e) {
66 throw ProcessError("Error during XML-initialization:\n " + XMLSubSys::transcode(e.getMessage()));
67 }
68}
69
70
71std::string
72XMLSubSys::warnLocalScheme(const std::string& newScheme, const bool haveSUMO_HOME) {
73 if (newScheme != "never" && newScheme != "auto" && newScheme != "always" && newScheme != "local") {
74 throw ProcessError("Unknown xml validation scheme + '" + newScheme + "'.");
75 }
76 if (!haveSUMO_HOME && newScheme == "local") {
78 WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, disabling XML validation. Set 'auto' or 'always' for web lookups."));
80 }
81 return "never";
82 }
83 return newScheme;
84}
85
86
87void
88XMLSubSys::setValidation(const std::string& validationScheme, const std::string& netValidationScheme, const std::string& routeValidationScheme) {
89 const char* sumoPath = std::getenv("SUMO_HOME");
90 const bool haveSUMO_HOME = sumoPath != nullptr && FileHelpers::isReadable(sumoPath + std::string("/data/xsd/net_file.xsd"));
91 myValidationScheme = warnLocalScheme(validationScheme, haveSUMO_HOME);
92 myNetValidationScheme = warnLocalScheme(netValidationScheme, haveSUMO_HOME);
93 myRouteValidationScheme = warnLocalScheme(routeValidationScheme, haveSUMO_HOME);
94 if (myGrammarPool == nullptr &&
95 (myValidationScheme != "never" ||
96 myNetValidationScheme != "never" ||
97 myRouteValidationScheme != "never")) {
98 if (!haveSUMO_HOME) {
100 WRITE_WARNING(TL("Environment variable SUMO_HOME is not set properly, XML validation will fail or use slow website lookups."));
102 }
103 return;
104 }
105 myGrammarPool = new XERCES_CPP_NAMESPACE::XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager);
106 SAX2XMLReader* parser(XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, myGrammarPool));
107#if _XERCES_VERSION >= 30100
108 parser->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesHandleMultipleImports, true);
109#endif
110 for (const char* const& filetype : {
111 "additional", "routes", "net"
112 }) {
113 const std::string file = sumoPath + std::string("/data/xsd/") + filetype + "_file.xsd";
114 if (!parser->loadGrammar(file.c_str(), XERCES_CPP_NAMESPACE::Grammar::SchemaGrammarType, true)) {
115 WRITE_WARNINGF(TL("Cannot read local schema '%'."), file);
116 }
117 }
118 delete parser;
119 }
120}
121
122
123void
125 for (std::vector<SUMOSAXReader*>::iterator i = myReaders.begin(); i != myReaders.end(); ++i) {
126 delete *i;
127 }
128 myReaders.clear();
129 delete myGrammarPool;
130 myGrammarPool = nullptr;
131 XMLPlatformUtils::Terminate();
132 myLCPTranscoder = nullptr;
133}
134
135
137XMLSubSys::getSAXReader(SUMOSAXHandler& handler, const bool isNet, const bool isRoute) {
138 std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme;
139 if (isRoute) {
140 validationScheme = myRouteValidationScheme;
141 }
142 return new SUMOSAXReader(handler, validationScheme, myGrammarPool);
143}
144
145
146void
148 myReaders[myNextFreeReader - 1]->setHandler(handler);
149}
150
151
152bool
153XMLSubSys::runParser(GenericSAXHandler& handler, const std::string& file,
154 const bool isNet, const bool isRoute, const bool isExternal, const bool catchExceptions) {
156 std::string errorMsg = "";
157 try {
158 std::string validationScheme = isNet ? myNetValidationScheme : myValidationScheme;
159 if (isRoute) {
160 validationScheme = myRouteValidationScheme;
161 }
162 if (isExternal && validationScheme == "local") {
163 WRITE_MESSAGEF(TL("Disabling XML validation for external file '%'. Use 'auto' or 'always' to enable."), file);
164 validationScheme = "never";
165 }
166 if (myNextFreeReader == (int)myReaders.size()) {
167 myReaders.push_back(new SUMOSAXReader(handler, validationScheme, myGrammarPool));
168 } else {
169 myReaders[myNextFreeReader]->setValidation(validationScheme);
170 myReaders[myNextFreeReader]->setHandler(handler);
171 }
173 std::string prevFile = handler.getFileName();
174 handler.setFileName(file);
175 myReaders[myNextFreeReader - 1]->parse(file);
176 handler.setFileName(prevFile);
178 } catch (const ProcessError& e) {
179 if (catchExceptions) {
180 errorMsg = std::string(e.what()) != std::string("") ? e.what() : TL("Process Error");
181 } else {
182 throw;
183 }
184 } catch (const std::runtime_error& re) {
185 errorMsg = TLF("Runtime error: % while parsing '%'", re.what(), file);
186 } catch (const std::exception& ex) {
187 errorMsg = TLF("Error occurred: % while parsing '%'", ex.what(), file);
188 } catch (const XERCES_CPP_NAMESPACE::SAXException& e) {
189 errorMsg = TLF("SAX error occurred while parsing '%':\n %", file, XMLSubSys::transcode(e.getMessage()));
190 } catch (...) {
191 errorMsg = TLF("Unspecified error occurred while parsing '%'", file);
192 }
193 if (errorMsg != "") {
194 if (catchExceptions) {
195 WRITE_ERROR(errorMsg);
196 } else {
197 throw ProcessError(errorMsg);
198 }
199 }
201}
202
203
204std::string
205XMLSubSys::transcode(const XMLCh* const data, int length) {
206 if (data == 0) {
207 throw EmptyData();
208 }
209 if (length < 0) {
210 length = (int)XERCES_CPP_NAMESPACE::XMLString::stringLen(data);
211 }
212 if (length == 0) {
213 return "";
214 }
215#if _XERCES_VERSION < 30100
216 char* t = XERCES_CPP_NAMESPACE::XMLString::transcode(data);
217 std::string result(t);
218 XERCES_CPP_NAMESPACE::XMLString::release(&t);
219 return result;
220#else
221 try {
222 XERCES_CPP_NAMESPACE::TranscodeToStr utf8(data, "UTF-8");
223 return reinterpret_cast<const char*>(utf8.str());
224 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {
225 return "?";
226 }
227#endif
228}
229
230
231std::string
232XMLSubSys::transcodeFromLocal(const std::string& localString) {
233#if _XERCES_VERSION > 30100
234 try {
235 if (myLCPTranscoder == nullptr) {
236 myLCPTranscoder = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgMemoryManager);
237 }
238 if (myLCPTranscoder != nullptr) {
239 return transcode(myLCPTranscoder->transcode(localString.c_str()));
240 }
241 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {}
242#endif
243 return localString;
244}
245
246
247std::string
248XMLSubSys::transcodeToLocal(const std::string& utf8String) {
249#if _XERCES_VERSION > 30100
250 try {
251 if (myLCPTranscoder == nullptr) {
252 myLCPTranscoder = XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgMemoryManager);
253 }
254 if (myLCPTranscoder != nullptr) {
255 XERCES_CPP_NAMESPACE::TranscodeFromStr utf8(reinterpret_cast<const XMLByte*>(utf8String.c_str()), utf8String.size(), "UTF-8");
256 return myLCPTranscoder->transcode(utf8.str());
257 }
258 } catch (XERCES_CPP_NAMESPACE::TranscodingException&) {}
259#endif
260 return utf8String;
261}
262
263
264/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
static bool isReadable(std::string path)
Checks whether the given file is readable.
A handler which converts occurring elements and attributes into enums.
void setFileName(const std::string &name)
Sets the current file name.
const std::string & getFileName() const
returns the current file name
bool wasInformed() const
Returns the information whether any messages were added.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
virtual void clear(bool resetInformed=true)
Clears information whether an error occurred previously and print aggregated message summary.
SAX-handler base for SUMO-files.
SAX-reader encapsulation containing binary reader.
static int myNextFreeReader
Information whether the reader is parsing.
Definition XMLSubSys.h:168
static std::vector< SUMOSAXReader * > myReaders
The XML Readers used for repeated parsing.
Definition XMLSubSys.h:165
static void setHandler(GenericSAXHandler &handler)
Sets the given handler for the default reader.
static std::string myValidationScheme
Information whether built reader/parser shall validate XML-documents against schemata.
Definition XMLSubSys.h:171
static void setValidation(const std::string &validationScheme, const std::string &netValidationScheme, const std::string &routeValidationScheme)
Enables or disables validation.
Definition XMLSubSys.cpp:88
static XERCES_CPP_NAMESPACE::XMLGrammarPool * myGrammarPool
Schema cache to be used for grammars which are not declared.
Definition XMLSubSys.h:180
static SUMOSAXReader * getSAXReader(SUMOSAXHandler &handler, const bool isNet=false, const bool isRoute=false)
Builds a reader and assigns the handler to it.
static void close()
Closes the xml-subsystem.
static std::string transcode(const XMLCh *const data, int length=-1)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8
static void init()
Initialises the xml-subsystem.
Definition XMLSubSys.cpp:61
static std::string warnLocalScheme(const std::string &newScheme, const bool haveSUMO_HOME)
Definition XMLSubSys.cpp:72
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
static std::string transcodeToLocal(const std::string &utf8String)
convert a string from UTF-8 to the local codepage
static std::string myRouteValidationScheme
Information whether built reader/parser shall validate SUMO routes against schemata.
Definition XMLSubSys.h:177
static bool myNeedsValidationWarning
Whether a warning about missing SUMO_HOME should be emitted.
Definition XMLSubSys.h:183
static std::string myNetValidationScheme
Information whether built reader/parser shall validate SUMO networks against schemata.
Definition XMLSubSys.h:174
static std::string transcodeFromLocal(const std::string &localString)
convert a string from the local codepage to UTF-8
static XERCES_CPP_NAMESPACE::XMLLCPTranscoder * myLCPTranscoder
reusable transcoder for local <-> UTF-8 conversions
Definition XMLSubSys.h:186