Eclipse SUMO - Simulation of Urban MObility
GenericSAXHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2019 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 /****************************************************************************/
18 // A handler which converts occuring elements and attributes into enums
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <cassert>
28 #include "GenericSAXHandler.h"
33 #include <utils/common/ToString.h>
35 #include "XMLSubSys.h"
36 
37 
38 // ===========================================================================
39 // class definitions
40 // ===========================================================================
42  StringBijection<int>::Entry* tags, int terminatorTag,
43  StringBijection<int>::Entry* attrs, int terminatorAttr,
44  const std::string& file, const std::string& expectedRoot)
45  : myParentHandler(nullptr), myParentIndicator(SUMO_TAG_NOTHING), myFileName(file), myExpectedRoot(expectedRoot), mySchemaSeen(false) {
46  int i = 0;
47  while (tags[i].key != terminatorTag) {
48  myTagMap.insert(TagMap::value_type(tags[i].str, tags[i].key));
49  i++;
50  }
51  i = 0;
52  while (attrs[i].key != terminatorAttr) {
53  assert(myPredefinedTags.find(attrs[i].key) == myPredefinedTags.end());
54  myPredefinedTags[attrs[i].key] = convert(attrs[i].str);
55  myPredefinedTagsMML[attrs[i].key] = attrs[i].str;
56  i++;
57  }
58 }
59 
60 
62  for (AttrMap::iterator i1 = myPredefinedTags.begin(); i1 != myPredefinedTags.end(); i1++) {
63  delete[](*i1).second;
64  }
65 }
66 
67 
68 void
69 GenericSAXHandler::setFileName(const std::string& name) {
70  myFileName = name;
71 }
72 
73 
74 const std::string&
76  return myFileName;
77 }
78 
79 
80 XMLCh*
81 GenericSAXHandler::convert(const std::string& name) const {
82  int len = (int)name.length();
83  XMLCh* ret = new XMLCh[len + 1];
84  int i = 0;
85  for (; i < len; i++) {
86  ret[i] = (XMLCh) name[i];
87  }
88  ret[i] = 0;
89  return ret;
90 }
91 
92 
93 void
94 GenericSAXHandler::startElement(const XMLCh* const /*uri*/,
95  const XMLCh* const /*localname*/,
96  const XMLCh* const qname,
97  const XERCES_CPP_NAMESPACE::Attributes& attrs) {
98  std::string name = StringUtils::transcode(qname);
99  if (mySchemaSeen && myExpectedRoot != "") {
100  if (name != myExpectedRoot) {
101  throw ProcessError("Found root element '" + name + "' in file '" + getFileName() + "' (expected '" + myExpectedRoot + "').");
102  }
103  mySchemaSeen = false;
104  }
105  int element = convertTag(name);
106  myCharactersVector.clear();
108  if (element == SUMO_TAG_INCLUDE) {
109  std::string file = na.getString(SUMO_ATTR_HREF);
110  if (!FileHelpers::isAbsolute(file)) {
112  }
113  XMLSubSys::runParser(*this, file);
114  } else {
115  myStartElement(element, na);
116  }
117 }
118 
119 
120 void
121 GenericSAXHandler::endElement(const XMLCh* const /*uri*/,
122  const XMLCh* const /*localname*/,
123  const XMLCh* const qname) {
124  std::string name = StringUtils::transcode(qname);
125  int element = convertTag(name);
126  // collect characters
127  if (myCharactersVector.size() != 0) {
128  int len = 0;
129  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
130  len += (int)myCharactersVector[i].length();
131  }
132  char* buf = new char[len + 1];
133  int pos = 0;
134  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
135  memcpy((unsigned char*) buf + pos, (unsigned char*) myCharactersVector[i].c_str(),
136  sizeof(char)*myCharactersVector[i].length());
137  pos += (int)myCharactersVector[i].length();
138  }
139  buf[pos] = 0;
140 
141  // call user handler
142  try {
143  myCharacters(element, buf);
144  } catch (std::runtime_error&) {
145  delete[] buf;
146  throw;
147  }
148  delete[] buf;
149  }
150  if (element != SUMO_TAG_INCLUDE) {
151  myEndElement(element);
152  if (myParentHandler && myParentIndicator == element) {
155  myParentHandler = nullptr;
156  }
157  }
158 }
159 
160 
161 void
163  myParentHandler = handler;
164  myParentIndicator = tag;
165  XMLSubSys::setHandler(*this);
166 }
167 
168 
169 void
170 GenericSAXHandler::characters(const XMLCh* const chars,
171  const XERCES3_SIZE_t length) {
172  myCharactersVector.push_back(StringUtils::transcode(chars, (int)length));
173 }
174 
175 
176 int
177 GenericSAXHandler::convertTag(const std::string& tag) const {
178  TagMap::const_iterator i = myTagMap.find(tag);
179  if (i == myTagMap.end()) {
180  return SUMO_TAG_NOTHING;
181  }
182  return (*i).second;
183 }
184 
185 
186 std::string
187 GenericSAXHandler::buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
188  std::ostringstream buf;
189  char* pMsg = XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage());
190  buf << pMsg << std::endl;
191  buf << " In file '" << getFileName() << "'" << std::endl;
192  buf << " At line/column " << exception.getLineNumber() + 1
193  << '/' << exception.getColumnNumber() << "." << std::endl;
194  XERCES_CPP_NAMESPACE::XMLString::release(&pMsg);
195  return buf.str();
196 }
197 
198 
199 void
200 GenericSAXHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
201  WRITE_WARNING(buildErrorMessage(exception));
202 }
203 
204 
205 void
206 GenericSAXHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
207  throw ProcessError(buildErrorMessage(exception));
208 }
209 
210 
211 void
212 GenericSAXHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
213  throw ProcessError(buildErrorMessage(exception));
214 }
215 
216 
217 void
219 
220 
221 void
222 GenericSAXHandler::myCharacters(int, const std::string&) {}
223 
224 
225 void
227 
228 
229 /****************************************************************************/
230 
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
int convertTag(const std::string &tag) const
Converts a tag from its string into its numerical representation.
const std::string & getFileName() const
returns the current file name
std::string myFileName
The name of the currently parsed file.
std::string buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Builds an error message.
std::vector< std::string > myCharactersVector
A list of character strings obtained so far to build the complete characters string at the end...
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:113
std::string transcode(const XMLCh *const qname)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
std::string myExpectedRoot
The root element to expect, empty string disables the check.
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:132
void characters(const XMLCh *const chars, const XERCES3_SIZE_t length)
The inherited method called when characters occurred.
virtual ~GenericSAXHandler()
Destructor.
A handler which converts occuring elements and attributes into enums.
void setFileName(const std::string &name)
Sets the current file name.
Encapsulated SAX-Attributes.
static bool isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
XMLCh * convert(const std::string &name) const
converts from c++-string into unicode
void warning(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-warnings.
virtual void myCharacters(int element, const std::string &chars)
Callback method for characters to implement by derived classes.
GenericSAXHandler * myParentHandler
The handler to give control back to.
void registerParent(const int tag, GenericSAXHandler *handler)
Assigning a parent handler which is enabled when the specified tag is closed.
static void setHandler(GenericSAXHandler &handler)
Sets the given handler for the default reader.
Definition: XMLSubSys.cpp:107
Encapsulated Xerces-SAX-attributes.
#define XERCES3_SIZE_t
Definition: config.h:213
std::string getString(int id) const
Returns the string-value of the named (by its enum-value) attribute.
void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Callback method for an opening tag to implement by derived classes.
bool mySchemaSeen
whether the reader has already seen a schema
std::map< int, std::string > myPredefinedTagsMML
the map from ids to their string representation
int myParentIndicator
The tag indicating that control should be given back.
void startElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname, const XERCES_CPP_NAMESPACE::Attributes &attrs)
The inherited method called when a new tag opens.
GenericSAXHandler(StringBijection< int >::Entry *tags, int terminatorTag, StringBijection< int >::Entry *attrs, int terminatorAttr, const std::string &file, const std::string &expectedRoot="")
Constructor.
void endElement(const XMLCh *const uri, const XMLCh *const localname, const XMLCh *const qname)
The inherited method called when a tag is being closed.
virtual void myEndElement(int element)
Callback method for a closing tag to implement by derived classes.