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