SUMO - Simulation of Urban MObility
SUMOSAXReader.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2012-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // SAX-reader encapsulation containing binary reader
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <string>
27 #include <iostream>
28 #include <xercesc/sax2/XMLReaderFactory.hpp>
29 #include <xercesc/framework/LocalFileInputSource.hpp>
30 #include <xercesc/framework/MemBufInputSource.hpp>
31 
33 #include <utils/common/ToString.h>
38 #include "GenericSAXHandler.h"
39 #include "SUMOSAXReader.h"
40 
41 
42 // ===========================================================================
43 // method definitions
44 // ===========================================================================
45 SUMOSAXReader::SUMOSAXReader(GenericSAXHandler& handler, const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
46  : myHandler(nullptr), myValidationScheme(validationScheme), myXMLReader(nullptr), myBinaryInput(nullptr) {
47  setHandler(handler);
48 }
49 
50 
52  delete myXMLReader;
53  delete myBinaryInput;
54 }
55 
56 
57 void
59  myHandler = &handler;
61  if (myXMLReader != nullptr) {
62  myXMLReader->setContentHandler(&handler);
63  myXMLReader->setErrorHandler(&handler);
64  }
65 }
66 
67 
68 void
69 SUMOSAXReader::setValidation(const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme) {
70  if (myXMLReader != nullptr && validationScheme != myValidationScheme) {
71  if (validationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Never) {
72  myXMLReader->setEntityResolver(nullptr);
73  myXMLReader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgWFXMLScanner);
74  } else {
75  myXMLReader->setEntityResolver(&mySchemaResolver);
76  myXMLReader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgIGXMLScanner);
77  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchema, true);
78  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgSAX2CoreValidation, true);
79  myXMLReader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesDynamic, validationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Auto);
80  }
81  }
82  myValidationScheme = validationScheme;
83 }
84 
85 
86 void
87 SUMOSAXReader::parse(std::string systemID) {
88  if (systemID.length() >= 4 && systemID.substr(systemID.length() - 4) == ".sbx") {
89  if (parseFirst(systemID)) {
90  while (parseNext());
91  }
92  } else {
93  if (myXMLReader == nullptr) {
95  }
96  myXMLReader->parse(systemID.c_str());
97  }
98 }
99 
100 
101 void
102 SUMOSAXReader::parseString(std::string content) {
103  if (myXMLReader == nullptr) {
105  }
106  XERCES_CPP_NAMESPACE::MemBufInputSource memBufIS((const XMLByte*)content.c_str(), content.size(), "registrySettings");
107  myXMLReader->parse(memBufIS);
108 }
109 
110 
111 bool
112 SUMOSAXReader::parseFirst(std::string systemID) {
113  if (systemID.substr(systemID.length() - 4) == ".sbx") {
114  myBinaryInput = new BinaryInputDevice(systemID, true, myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Always);
116  if (mySbxVersion < 1 || mySbxVersion > 2) {
117  throw ProcessError("Unknown sbx version");
118  }
119  std::string sumoVer;
120  *myBinaryInput >> sumoVer;
121  std::vector<std::string> elems;
122  *myBinaryInput >> elems;
123  // !!! check elems here
124  elems.clear();
125  *myBinaryInput >> elems;
126  // !!! check attrs here
127  elems.clear();
128  *myBinaryInput >> elems;
129  // !!! check node types here
130  elems.clear();
131  *myBinaryInput >> elems;
132  // !!! check edge types here
133  elems.clear();
134  *myBinaryInput >> elems;
135  // !!! check edges here
136  std::vector< std::vector<int> > followers;
137  *myBinaryInput >> followers;
138  // !!! check followers here
139  return parseNext();
140  } else {
141  if (myXMLReader == nullptr) {
143  }
144  myToken = XERCES_CPP_NAMESPACE::XMLPScanToken();
145  return myXMLReader->parseFirst(systemID.c_str(), myToken);
146  }
147 }
148 
149 
150 bool
152  if (myBinaryInput != nullptr) {
153  int next = myBinaryInput->peek();
154  switch (next) {
155  case EOF:
156  delete myBinaryInput;
157  myBinaryInput = nullptr;
158  return false;
160  int tag;
161  unsigned char tagByte;
162  *myBinaryInput >> tagByte;
163  tag = tagByte;
164  if (mySbxVersion > 1) {
166  *myBinaryInput >> tagByte;
167  tag += 256 * tagByte;
168  }
169  myXMLStack.push_back((SumoXMLTag)tag);
171  myHandler->myStartElement(tag, attrs);
172  break;
173  }
175  if (myXMLStack.empty()) {
176  throw ProcessError("Binary file is invalid, unexpected tag end.");
177  }
179  myXMLStack.pop_back();
180  myBinaryInput->read(mySbxVersion > 1 ? 1 : 2);
181  break;
182  }
183  default:
184  throw ProcessError("Binary file is invalid, expected tag start or tag end.");
185  }
186  return true;
187  } else {
188  if (myXMLReader == nullptr) {
189  throw ProcessError("The XML-parser was not initialized.");
190  }
191  return myXMLReader->parseNext(myToken);
192  }
193 }
194 
195 
196 XERCES_CPP_NAMESPACE::SAX2XMLReader*
198  XERCES_CPP_NAMESPACE::SAX2XMLReader* reader = XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader();
199  if (reader == nullptr) {
200  throw ProcessError("The XML-parser could not be build.");
201  }
202  // see here https://svn.apache.org/repos/asf/xerces/c/trunk/samples/src/SAX2Count/SAX2Count.cpp for the way to set features
203  if (myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Never) {
204  reader->setProperty(XERCES_CPP_NAMESPACE::XMLUni::fgXercesScannerName, (void*)XERCES_CPP_NAMESPACE::XMLUni::fgWFXMLScanner);
205  } else {
206  reader->setEntityResolver(&mySchemaResolver);
207  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchema, true);
208  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgSAX2CoreValidation, true);
209  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesDynamic, myValidationScheme == XERCES_CPP_NAMESPACE::SAX2XMLReader::Val_Auto);
210  }
211  reader->setContentHandler(myHandler);
212  reader->setErrorHandler(myHandler);
213  return reader;
214 }
215 
216 
217 XERCES_CPP_NAMESPACE::InputSource*
218 SUMOSAXReader::LocalSchemaResolver::resolveEntity(const XMLCh* const /* publicId */, const XMLCh* const systemId) {
219  const std::string url = StringUtils::transcode(systemId);
220  const std::string::size_type pos = url.rfind("/");
221  if (pos != std::string::npos) {
222  const std::string dir = url.substr(0, pos);
223  if (dir == "http://sumo.sf.net/xsd" || dir == "http://sumo-sim.org/xsd" || dir == "http://sumo-sim.org/xsd/amitran" ||
224  dir == "http://sumo.dlr.de/xsd" || dir == "http://sumo.dlr.de/xsd/amitran") {
226  const char* sumoPath = std::getenv("SUMO_HOME");
227  if (sumoPath == nullptr) {
228  WRITE_WARNING("Environment variable SUMO_HOME is not set, schema resolution will use slow website lookups.");
229  return nullptr;
230  }
231  const std::string file = sumoPath + std::string("/data/xsd") + url.substr(url.find("/xsd/") + 4);
232  if (FileHelpers::isReadable(file)) {
233  XMLCh* t = XERCES_CPP_NAMESPACE::XMLString::transcode(file.c_str());
234  XERCES_CPP_NAMESPACE::InputSource* const result = new XERCES_CPP_NAMESPACE::LocalFileInputSource(t);
235  XERCES_CPP_NAMESPACE::XMLString::release(&t);
236  return result;
237  } else {
238  WRITE_WARNING("Cannot find local schema '" + file + "', will try website lookup.");
239  }
240  }
241  }
242  return nullptr;
243 }
244 
245 
246 void
248  myHandler = &handler;
249 }
250 
251 
252 /****************************************************************************/
std::vector< SumoXMLTag > myXMLStack
The stack of begun xml elements.
int peek()
Returns the next character to be read by an actual parse.
SumoXMLTag
Numbers representing SUMO-XML - element names.
SUMOSAXReader(GenericSAXHandler &handler, const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
Constructor.
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:47
void putback(char c)
Pushes a character back into the stream to be read by the next actual parse.
XERCES_CPP_NAMESPACE::SAX2XMLReader * getSAXReader()
Builds a reader.
void setValidation(const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
XERCES_CPP_NAMESPACE::XMLPScanToken myToken
void parseString(std::string content)
BinaryInputDevice * myBinaryInput
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
void setSchemaSeen(const bool schemaSeen=true)
static std::string transcode(const XMLCh *const data)
converts a 0-terminated XMLCh* array (usually UTF-16, stemming from Xerces) into std::string in UTF-8...
Definition: StringUtils.h:133
A handler which converts occuring elements and attributes into enums.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
void parse(std::string systemID)
void setHandler(GenericSAXHandler &handler)
XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes myValidationScheme
Information whether built reader/parser shall validate XML-documents against schemata.
bool parseFirst(std::string systemID)
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Callback method for an opening tag to implement by derived classes.
Encapsulated Xerces-SAX-attributes.
XERCES_CPP_NAMESPACE::SAX2XMLReader * myXMLReader
void setHandler(GenericSAXHandler &handler)
Sets the given handler as content and error handler for the reader.
LocalSchemaResolver mySchemaResolver
std::map< int, std::string > myPredefinedTagsMML
the map from ids to their string representation
XERCES_CPP_NAMESPACE::InputSource * resolveEntity(const XMLCh *const publicId, const XMLCh *const systemId)
~SUMOSAXReader()
Destructor.
Encapsulates binary reading operations on a file.
GenericSAXHandler * myHandler
std::string read(int numBytes)
Reads the defined number of bytes and returns them as a string.
virtual void myEndElement(int element)
Callback method for a closing tag to implement by derived classes.