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.dev/sumo
3 // Copyright (C) 2002-2024 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 occurring 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),
44  myExpectedRoot(expectedRoot), myNextSectionStart(-1, nullptr) {
45  int i = 0;
46  while (tags[i].key != terminatorTag) {
47  myTagMap.insert(TagMap::value_type(tags[i].str, tags[i].key));
48  i++;
49  }
50  i = 0;
51  while (attrs[i].key != terminatorAttr) {
52  int key = attrs[i].key;
53  assert(key >= 0);
54  while (key >= (int)myPredefinedTags.size()) {
55  myPredefinedTags.push_back(nullptr);
56  myPredefinedTagsMML.push_back("");
57  }
58  myPredefinedTags[key] = convert(attrs[i].str);
59  myPredefinedTagsMML[key] = attrs[i].str;
60  i++;
61  }
62 }
63 
64 
66  for (AttrMap::iterator i1 = myPredefinedTags.begin(); i1 != myPredefinedTags.end(); i1++) {
67  delete[](*i1);
68  }
69  delete myNextSectionStart.second;
70 }
71 
72 
73 void
74 GenericSAXHandler::setFileName(const std::string& name) {
75  myFileName = name;
76 }
77 
78 
79 const std::string&
81  return myFileName;
82 }
83 
84 
85 XMLCh*
86 GenericSAXHandler::convert(const std::string& name) const {
87  int len = (int)name.length();
88  XMLCh* ret = new XMLCh[len + 1];
89  int i = 0;
90  for (; i < len; i++) {
91  ret[i] = (XMLCh) name[i];
92  }
93  ret[i] = 0;
94  return ret;
95 }
96 
97 
98 void
99 GenericSAXHandler::startElement(const XMLCh* const /*uri*/,
100  const XMLCh* const /*localname*/,
101  const XMLCh* const qname,
102  const XERCES_CPP_NAMESPACE::Attributes& attrs) {
103  std::string name = StringUtils::transcode(qname);
104  if (!myRootSeen && myExpectedRoot != "" && name != myExpectedRoot) {
105  WRITE_WARNINGF(TL("Found root element '%' in file '%' (expected '%')."), name, getFileName(), myExpectedRoot);
106  }
107  myRootSeen = true;
108  myCharactersVector.clear();
109  const int element = convertTag(name);
110  if (mySectionSeen && !mySectionOpen && element != mySection) {
111  mySectionEnded = true;
112  myNextSectionStart.first = element;
114  return;
115  }
116  if (element == mySection) {
117  mySectionSeen = true;
118  mySectionOpen = true;
119  }
121  if (element == SUMO_TAG_INCLUDE) {
122  std::string file = na.getString(SUMO_ATTR_HREF);
123  if (!FileHelpers::isAbsolute(file)) {
125  }
126  XMLSubSys::runParser(*this, file);
127  } else {
128  myStartElement(element, na);
129  }
130 }
131 
132 
133 void
134 GenericSAXHandler::endElement(const XMLCh* const /*uri*/,
135  const XMLCh* const /*localname*/,
136  const XMLCh* const qname) {
137  std::string name = StringUtils::transcode(qname);
138  int element = convertTag(name);
139  // collect characters
140  if (myCharactersVector.size() != 0) {
141  int len = 0;
142  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
143  len += (int)myCharactersVector[i].length();
144  }
145  char* buf = new char[len + 1];
146  int pos = 0;
147  for (int i = 0; i < (int)myCharactersVector.size(); ++i) {
148  memcpy((unsigned char*) buf + pos, (unsigned char*) myCharactersVector[i].c_str(),
149  sizeof(char)*myCharactersVector[i].length());
150  pos += (int)myCharactersVector[i].length();
151  }
152  buf[pos] = 0;
153 
154  // call user handler
155  try {
156  myCharacters(element, buf);
157  } catch (std::runtime_error&) {
158  delete[] buf;
159  throw;
160  }
161  delete[] buf;
162  }
163  if (element == mySection) {
164  mySectionOpen = false;
165  }
166  if (element != SUMO_TAG_INCLUDE) {
167  myEndElement(element);
168  if (myParentHandler && myParentIndicator == element) {
171  myParentHandler = nullptr;
172  }
173  }
174 }
175 
176 
177 void
179  myParentHandler = handler;
180  myParentIndicator = tag;
181  XMLSubSys::setHandler(*this);
182 }
183 
184 
185 void
186 GenericSAXHandler::characters(const XMLCh* const chars,
187  const XERCES3_SIZE_t length) {
189  myCharactersVector.push_back(StringUtils::transcode(chars, (int)length));
190  }
191 }
192 
193 
194 int
195 GenericSAXHandler::convertTag(const std::string& tag) const {
196  TagMap::const_iterator i = myTagMap.find(tag);
197  if (i == myTagMap.end()) {
198  return SUMO_TAG_NOTHING;
199  }
200  return (*i).second;
201 }
202 
203 
204 std::string
205 GenericSAXHandler::buildErrorMessage(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
206  std::ostringstream buf;
207  char* pMsg = XERCES_CPP_NAMESPACE::XMLString::transcode(exception.getMessage());
208  buf << pMsg << std::endl;
209  buf << TL(" In file '") << getFileName() << "'" << std::endl;
210  buf << TL(" At line/column ") << exception.getLineNumber() + 1
211  << '/' << exception.getColumnNumber() << "." << std::endl;
212  XERCES_CPP_NAMESPACE::XMLString::release(&pMsg);
213  return buf.str();
214 }
215 
216 
217 void
218 GenericSAXHandler::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
219  WRITE_WARNING(buildErrorMessage(exception));
220 }
221 
222 
223 void
224 GenericSAXHandler::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
225  throw ProcessError(buildErrorMessage(exception));
226 }
227 
228 
229 void
230 GenericSAXHandler::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
231  throw ProcessError(buildErrorMessage(exception));
232 }
233 
234 
235 void
237 
238 
239 void
240 GenericSAXHandler::myCharacters(int, const std::string&) {}
241 
242 
243 void
245 
246 void
248  if (myParentHandler) {
249  myParentHandler->myEndElement(element);
250  }
251 }
252 
253 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
@ SUMO_TAG_INCLUDE
@ SUMO_TAG_NOTHING
invalid tag
@ SUMO_ATTR_HREF
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 occurring 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.
bool mySectionEnded
whether the reader has already seen the end of the section
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.
bool mySectionOpen
whether an element of the current section is open
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
bool mySectionSeen
whether the reader has already seen the begin of the section
GenericSAXHandler * myParentHandler
The handler to give control back to.
int mySection
The tag indicating the current section to parse.
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.
std::pair< int, SUMOSAXAttributes * > myNextSectionStart
void callParentEnd(int element)
signal endElement to the parent handler (special case for MSCalibrator)
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
bool myCollectCharacterData
whether the reader should collect character data
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, bool *isPresent=nullptr) 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:146
static void setHandler(GenericSAXHandler &handler)
Sets the given handler for the default reader.
Definition: XMLSubSys.cpp:142
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.
Definition: XMLSubSys.cpp:148