Eclipse 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-2020 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 // SAX-reader encapsulation containing binary reader
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
25 #include <memory>
26 #include <iostream>
27 #include <xercesc/sax2/XMLReaderFactory.hpp>
28 #include <xercesc/framework/LocalFileInputSource.hpp>
29 #include <xercesc/framework/MemBufInputSource.hpp>
30 
33 #include <utils/common/ToString.h>
35 #include "GenericSAXHandler.h"
36 #ifdef HAVE_ZLIB
37 #include <foreign/zstr/zstr.hpp>
38 #endif
39 #include "IStreamInputSource.h"
40 #include "SUMOSAXReader.h"
41 
42 using XERCES_CPP_NAMESPACE::SAX2XMLReader;
43 using XERCES_CPP_NAMESPACE::XMLUni;
44 
45 
46 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 SUMOSAXReader::SUMOSAXReader(GenericSAXHandler& handler, const SAX2XMLReader::ValSchemes validationScheme, XERCES_CPP_NAMESPACE::XMLGrammarPool* grammarPool)
50  : myHandler(nullptr), myValidationScheme(validationScheme), myGrammarPool(grammarPool), myXMLReader(nullptr), myIStream(nullptr), myInputStream(nullptr) {
51  setHandler(handler);
52 }
53 
54 
56  delete myXMLReader;
57 }
58 
59 
60 void
62  myHandler = &handler;
64  if (myXMLReader != nullptr) {
65  myXMLReader->setContentHandler(&handler);
66  myXMLReader->setErrorHandler(&handler);
67  }
68 }
69 
70 
71 void
72 SUMOSAXReader::setValidation(const SAX2XMLReader::ValSchemes validationScheme) {
73  if (myXMLReader != nullptr && validationScheme != myValidationScheme) {
74  if (validationScheme == SAX2XMLReader::Val_Never) {
75  myXMLReader->setEntityResolver(nullptr);
76  myXMLReader->setProperty(XMLUni::fgXercesScannerName, (void*)XMLUni::fgWFXMLScanner);
77  } else {
78  myXMLReader->setEntityResolver(&mySchemaResolver);
79  myXMLReader->setProperty(XMLUni::fgXercesScannerName, (void*)XMLUni::fgIGXMLScanner);
80  myXMLReader->setFeature(XMLUni::fgXercesSchema, true);
81  myXMLReader->setFeature(XMLUni::fgSAX2CoreValidation, true);
82  myXMLReader->setFeature(XMLUni::fgXercesDynamic, validationScheme == SAX2XMLReader::Val_Auto);
83  myXMLReader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, myValidationScheme == SAX2XMLReader::Val_Always);
84  }
85  }
86  myValidationScheme = validationScheme;
87 }
88 
89 
90 void
91 SUMOSAXReader::parse(std::string systemID) {
92  if (myXMLReader == nullptr) {
94  }
95  if (!FileHelpers::isReadable(systemID)) {
96  throw ProcessError("Cannot read file '" + systemID + "'!");
97  }
98  if (FileHelpers::isDirectory(systemID)) {
99  throw ProcessError("File '" + systemID + "' is a directory!");
100  }
101 #ifdef HAVE_ZLIB
102  zstr::ifstream istream(systemID.c_str(), std::fstream::in | std::fstream::binary);
103  myXMLReader->parse(IStreamInputSource(istream));
104 #else
105  myXMLReader->parse(systemID.c_str());
106 #endif
107 }
108 
109 
110 void
111 SUMOSAXReader::parseString(std::string content) {
112  if (myXMLReader == nullptr) {
114  }
115  XERCES_CPP_NAMESPACE::MemBufInputSource memBufIS((const XMLByte*)content.c_str(), content.size(), "registrySettings");
116  myXMLReader->parse(memBufIS);
117 }
118 
119 
120 bool
121 SUMOSAXReader::parseFirst(std::string systemID) {
122  if (!FileHelpers::isReadable(systemID)) {
123  throw ProcessError("Cannot read file '" + systemID + "'!");
124  }
125  if (myXMLReader == nullptr) {
127  }
128  myToken = XERCES_CPP_NAMESPACE::XMLPScanToken();
129 #ifdef HAVE_ZLIB
130  myIStream = std::unique_ptr<zstr::ifstream>(new zstr::ifstream(systemID.c_str(), std::fstream::in | std::fstream::binary));
131  myInputStream = std::unique_ptr<IStreamInputSource>(new IStreamInputSource(*myIStream));
132  return myXMLReader->parseFirst(*myInputStream, myToken);
133 #else
134  return myXMLReader->parseFirst(systemID.c_str(), myToken);
135 #endif
136 }
137 
138 
139 bool
141  if (myXMLReader == nullptr) {
142  throw ProcessError("The XML-parser was not initialized.");
143  }
144  return myXMLReader->parseNext(myToken);
145 }
146 
147 
148 SAX2XMLReader*
150  SAX2XMLReader* reader = XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader(XERCES_CPP_NAMESPACE::XMLPlatformUtils::fgMemoryManager, myGrammarPool);
151  if (reader == nullptr) {
152  throw ProcessError("The XML-parser could not be build.");
153  }
154  // see here https://svn.apache.org/repos/asf/xerces/c/trunk/samples/src/SAX2Count/SAX2Count.cpp for the way to set features
155  if (myValidationScheme == SAX2XMLReader::Val_Never) {
156  reader->setProperty(XMLUni::fgXercesScannerName, (void*)XMLUni::fgWFXMLScanner);
157  } else {
158  reader->setEntityResolver(&mySchemaResolver);
159  reader->setFeature(XMLUni::fgXercesSchema, true);
160  reader->setFeature(XMLUni::fgSAX2CoreValidation, true);
161  reader->setFeature(XMLUni::fgXercesDynamic, myValidationScheme == SAX2XMLReader::Val_Auto);
162  reader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, myValidationScheme == SAX2XMLReader::Val_Always);
163  }
164  reader->setContentHandler(myHandler);
165  reader->setErrorHandler(myHandler);
166  return reader;
167 }
168 
169 
170 XERCES_CPP_NAMESPACE::InputSource*
171 SUMOSAXReader::LocalSchemaResolver::resolveEntity(const XMLCh* const /* publicId */, const XMLCh* const systemId) {
172  const std::string url = StringUtils::transcode(systemId);
173  const std::string::size_type pos = url.find("/xsd/");
174  if (pos != std::string::npos) {
175  const char* sumoPath = std::getenv("SUMO_HOME");
176  if (sumoPath == nullptr) {
177  // no need for a warning here, global preparsing should have done it.
178  return nullptr;
179  }
180  const std::string file = sumoPath + std::string("/data") + url.substr(pos);
181  if (FileHelpers::isReadable(file)) {
182  XMLCh* t = XERCES_CPP_NAMESPACE::XMLString::transcode(file.c_str());
183  XERCES_CPP_NAMESPACE::InputSource* const result = new XERCES_CPP_NAMESPACE::LocalFileInputSource(t);
184  XERCES_CPP_NAMESPACE::XMLString::release(&t);
185  return result;
186  } else {
187  WRITE_WARNING("Cannot read local schema '" + file + "', will try website lookup.");
188  }
189  }
190  return nullptr;
191 }
192 
193 
194 void
196  myHandler = &handler;
197 }
198 
199 
200 /****************************************************************************/
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
std::string transcode(const XMLCh *const qname)
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:48
static bool isDirectory(std::string path)
Checks whether the given file is a directory.
Definition: FileHelpers.cpp:62
A handler which converts occuring elements and attributes into enums.
Xerces InputSource reading from arbitrary std::istream.
void setHandler(GenericSAXHandler &handler)
XERCES_CPP_NAMESPACE::InputSource * resolveEntity(const XMLCh *const publicId, const XMLCh *const systemId)
XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes myValidationScheme
Information whether built reader/parser shall validate XML-documents against schemata.
std::unique_ptr< IStreamInputSource > myInputStream
SUMOSAXReader(GenericSAXHandler &handler, const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme, XERCES_CPP_NAMESPACE::XMLGrammarPool *grammarPool)
Constructor.
void setHandler(GenericSAXHandler &handler)
Sets the given handler as content and error handler for the reader.
void parseString(std::string content)
bool parseFirst(std::string systemID)
std::unique_ptr< std::istream > myIStream
LocalSchemaResolver mySchemaResolver
void setValidation(const XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme)
~SUMOSAXReader()
Destructor.
XERCES_CPP_NAMESPACE::SAX2XMLReader * getSAXReader()
Builds a reader.
GenericSAXHandler * myHandler
void parse(std::string systemID)
XERCES_CPP_NAMESPACE::SAX2XMLReader * myXMLReader
XERCES_CPP_NAMESPACE::XMLGrammarPool * myGrammarPool
Schema cache to be used for grammars which are not declared.
XERCES_CPP_NAMESPACE::XMLPScanToken myToken
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