BPMN-OS
BPMN for optimization and simulation
Loading...
Searching...
No Matches
XMLObject.h
Go to the documentation of this file.
1// schematic++ v0.4.0
2#ifndef XMLObject_H
3#define XMLObject_H
4#include <memory>
5#include <sstream>
6#include <string>
7#include <string_view>
8#include <unordered_map>
9#include <vector>
10#include <optional>
11
12#include <xercesc/dom/DOM.hpp>
13
14/**
15 * @brief The `XML` namespace contains classes representing XML-nodes defined in given XML-schema(s).
16 */
17namespace XML {
18
19class XMLObject;
20
21typedef std::string ClassName;
22typedef std::string ElementName;
23typedef std::string TextContent;
24typedef std::string Namespace;
25typedef std::string AttributeName;
26
27/**
28 * @brief A struct representing the value of an XML-node attribute.
29 *
30 * The Value struct stores a value and provides implicit conversion and assignment operators
31 * to facilitate easy conversion between different types and convenient assignment
32 * of values.
33 *
34 * Example usage:
35 * ```
36 * Value value;
37 * value = std::to_string("a_string"); // Assignment using a std::string.
38 * value = true; // Assignment using a bool.
39 * value = 42; // Assignment using an int.
40 * value = 3.14; // Assignment using a double.
41 *
42 * std::string stringValue = value; // Implicit conversion to std::string.
43 * bool booleanValue = value; // Implicit conversion to bool.
44 * int integerValue = value; // Implicit conversion to int.
45 * double realValue = value; // Implicit conversion to double.
46 * ```
47 */
48struct Value {
49 std::string value;
50 operator std::string_view() const { return value; };
51 operator std::string() const { return value; };
52 operator bool() const { return (value == True); };
53 operator int() const { try { return std::stoi(value); } catch(...) { throw std::runtime_error("Cannot convert '" + value + "' to int"); } };
54 operator double() const { try { return std::stod(value); } catch(...) { throw std::runtime_error("Cannot convert '" + value + "' to double"); } };
55 Value& operator=(const std::string& s) { value = s; return *this; };
56 Value& operator=(bool b) { value = (b ? True : False); return *this; };
57 Value& operator=(int i) { value = std::to_string(i); return *this; };
58 Value& operator=(double d) { value = std::to_string(d); return *this; };
59 Value(const std::string& s) : value(s) {};
60 Value(bool b) : value(b ? True : False) {};
61 Value(int i) : value(std::to_string(i)) {};
62 Value(double d) : value(std::to_string(d)) {};
63 inline static std::string True = "true";
64 inline static std::string False = "false";
65};
66
67/**
68 * @brief A struct representing an attribute of an XML-node.
69 *
70 * The `Attribute` struct stores information about the namespace, prefix, name, and
71 * value of the attribute.
72 */
79
80typedef std::vector<Attribute> Attributes;
81typedef std::vector<std::unique_ptr<XMLObject>> Children;
82
83/// @brief Template function used to store in factory
84template<typename T> XMLObject* createInstance(const Namespace& xmlns, const ClassName& className, const xercesc::DOMElement* element) { return new T(xmlns, className, element, T::defaults); }
85
86/// @brief Factory used to create instance depending on element name
87typedef std::unordered_map<ElementName, XMLObject* (*)(const Namespace& xmlns, const ClassName& className, const xercesc::DOMElement* element)> Factory;
88
89
90/**
91 * @brief A class representing a node in an XML-tree.
92 *
93 * The XMLObject class allows to read and store an XML-tree. The root element can be created using
94 * - @ref XMLObject::createFromStream(std::istream& xmlStream)
95 * - @ref XMLObject::createFromString(const std::string& xmlString)
96 * - @ref XMLObject::createFromFile(const std::string& filename)
97 *
98 * Each object has the following members:
99 * - @ref xmlns : refers to the XML namespace
100 * - @ref className : refers to the class it belong to
101 * - @ref elementName : refers to the name used in the XML
102 * - @ref prefix : refers to the namespace prefix in the XML
103 * - @ref textContent : textual content of XML element without children
104 * - @ref attributes : a list of attributes containing the namespace, prefix, attribute name,
105 * and attribute value
106 * - @ref children : a list of child elements
107 *
108 * Derived classes with dedicated members for attributes and children are automatically generated by
109 * schematic++ according to respective XML schema definition(s).
110 *
111 * Each XMLObject can be converted to a string using @ref stringify() and printed to an output stream
112 * using @ref operator<<(std::ostream& os, const XMLObject* obj) and
113 * @ref operator<<(std::ostream& os, const XMLObject& obj) .
114 */
116
117public:
118 /**
119 * @brief Create an XMLObject from the input stream.
120 *
121 * @param xmlStream The input stream containing the XML data.
122 * @return A pointer to the created XMLObject.
123 * @throws std::runtime_error if parsing the XML fails.
124 */
125 static XMLObject* createFromStream(std::istream& xmlStream);
126
127 /**
128 * @brief Create an XMLObject from a string representation of XML.
129 *
130 * @param xmlString The string containing the XML data.
131 * @return A pointer to the created XMLObject.
132 * @throws std::runtime_error if parsing the XML fails.
133 */
134 static XMLObject* createFromString(const std::string& xmlString);
135
136 /**
137 * @brief Create an XMLObject from an XML file.
138 *
139 * @param filename The path to the XML file.
140 * @return A pointer to the created XMLObject.
141 * @throws std::runtime_error if loading the file or parsing the XML fails.
142 */
143 static XMLObject* createFromFile(const std::string& filename);
144
145 virtual ~XMLObject() {};
146
147protected:
148 static XMLObject* createObject(const xercesc::DOMElement* element);
149
150template<typename T> friend XMLObject* createInstance(const Namespace& xmlns, const ClassName& className, const xercesc::DOMElement* element);
151
152protected:
153 XMLObject(const Namespace& xmlns, const ClassName& className, const xercesc::DOMElement* element, const Attributes& defaultAttributes);
154
155 inline static Factory factory;
156public:
157 /// @brief Returns a pointer of type T of the object.
158 template<typename T> inline T* is() {
159 return dynamic_cast<T*>(this);
160 }
161
162 template<typename T> inline const T* is() const {
163 return dynamic_cast<const T*>(this);
164 }
165
166 /**
167 * @brief Attempt to cast the current instance to the specified type T.
168 * @return A pointer to the casted object.
169 * @throws std::runtime_error if the cast fails.
170 */
171 template<typename T> inline T* get() {
172 T* ptr = dynamic_cast<T*>(this);
173 if ( ptr == nullptr ) {
174 throw std::runtime_error("XMLObject: Illegal cast");
175 }
176 return ptr;
177 }
178
179 /**
180 * @brief Attempt to cast the current instance to the specified type T.
181 * @return A pointer to the casted object.
182 * @throws std::runtime_error if the cast fails.
183 */
184 template<typename T> inline const T* get() const {
185 const T* ptr = dynamic_cast<const T*>(this);
186 if ( ptr == nullptr ) {
187 throw std::runtime_error("XMLObject: Illegal cast");
188 }
189 return ptr;
190 }
191
192private:
193 template<typename T>
194 void findRecursive(std::vector<std::reference_wrapper<T> >& result, const Children& descendants)
195 {
196 for (auto& descendant : descendants) {
197 if (descendant->is<T>()) {
198 result.push_back(*descendant->get<T>());
199 }
200 findRecursive(result, descendant->children );
201 }
202 }
203
204 template<typename T>
205 void findRecursive(std::vector<std::reference_wrapper<const T> >& result, const Children& descendants) const
206 {
207 for (auto& descendant : descendants) {
208 if (descendant->is<const T>()) {
209 result.push_back(*descendant->get<const T>());
210 }
211 findRecursive(result, descendant->children );
212 }
213 }
214
215public:
216 /**
217 * @brief Find all descendants of type T.
218 *
219 * @return A vector of references to descendants of type T.
220 */
221 template<typename T>
222 std::vector<std::reference_wrapper<T> > find()
223 {
224 std::vector<std::reference_wrapper<T> > result;
225 findRecursive(result, children);
226 return result;
227 }
228
229 /**
230 * @brief Find all descendants of type T.
231 *
232 * @return A vector of const references to descendants of type T.
233 */
234 template<typename T>
235 std::vector<std::reference_wrapper<const T> > find() const
236 {
237 std::vector<std::reference_wrapper<const T> > result;
238 findRecursive(result, children);
239 return result;
240 }
241
243 const ClassName className;
246
247 TextContent textContent; ///< Textual content of XML element without children
248 Children children; ///< Child nodes of the XML element
249 Attributes attributes; /// Attributes of the XML element
250 inline static const Attributes defaults = {};
251
252 /**
253 * @brief Convert the XMLObject and its children to a string representation.
254 *
255 * @return The string representation of the XMLObject.
256 */
257 std::string stringify() const;
258
259 /**
260 * @brief Creates formated string representing the XMLObject including its children.
261 *
262 * @return A formated string representing the XMLObject.
263 */
264 std::string format(std::string indentation = "\t", unsigned int depth = 0) const;
265
266 /**
267 * @brief Get a required child of type T.
268 *
269 * @return A reference to the required child.
270 * @throws std::runtime_error if the required child is not found.
271 */
272 template<typename T> T& getRequiredChild() {
273 for ( auto& child : children ) {
274 if ( child->is<T>() ) {
275 return *child->get<T>();
276 }
277 }
278 throw std::runtime_error("Failed to get required child of element '" + elementName + "'");
279 }
280
281 /**
282 * @brief Get an optional child of type T.
283 *
284 * @return An optional containing a reference to the optional child if found,
285 * or `std::nullopt` if the optional child is not found.
286 */
287 template<typename T> std::optional< std::reference_wrapper<T> > getOptionalChild() {
288 for ( auto& child : children ) {
289 if ( child->is<T>() ) {
290 return *child->get<T>();
291 }
292 }
293 return std::nullopt;
294 }
295
296 /**
297 * @brief Get all children of type T.
298 *
299 * @return A vector of references to the children of type T.
300 */
301 template<typename T> std::vector< std::reference_wrapper<T> > getChildren() {
302 std::vector< std::reference_wrapper<T> > result;
303 for ( auto& child : children ) {
304 if ( child->is<T>() ) {
305 result.push_back(*child->get<T>());
306 }
307 }
308 return result;
309 }
310
311 /**
312 * @brief Get a required child with the specified element name.
313 *
314 * @param elementName The name of the child element without namespace prefix.
315 * @return A reference to the required child.
316 * @throws std::runtime_error if the required child is not found.
317 */
319
320 /**
321 * @brief Get the optional child with the specified element name.
322 *
323 * @param elementName The name of the child element without namespace prefix.
324 * @return An optional containing a reference to the optional child if found,
325 * or `std::nullopt` if the optional child is not found.
326 */
327 std::optional< std::reference_wrapper<XMLObject> > getOptionalChildByName(const ElementName& elementName);
328
329 /**
330 * @brief Get all children with the specified element name.
331 *
332 * @param elementName The name of the child elements without namespace prefix.
333 * @return A vector of references to the children with the specified element name.
334 */
335 std::vector< std::reference_wrapper<XMLObject> > getChildrenByName(const ElementName& elementName);
336
337 /**
338 * @brief Get a required attribute with the specified attribute name.
339 *
340 * @param attributeName The name of the attribute without namespace prefix.
341 * @return A reference to the required attribute.
342 * @throws std::runtime_error if the required attribute is not found.
343 */
345
346 /**
347 * @brief Get an optional attribute with the specified attribute name.
348 *
349 * @param attributeName The name of the attribute without namespace prefix.
350 * @return An optional containing a reference to the optional attribute if found,
351 * or `std::nullopt` if the optional attribute is not found.
352 */
353 std::optional< std::reference_wrapper<Attribute> > getOptionalAttributeByName(const AttributeName& attributeName);
354
355
356};
357
358/// @brief Allows printing of stringified XML object
359std::ostream& operator<<(std::ostream& os, const XMLObject* obj);
360/// @brief Allows printing of stringified XML object
361std::ostream& operator<<(std::ostream& os, const XMLObject& obj);
362
363} // end namespace XML
364
365#endif // XML_H
A class representing a node in an XML-tree.
Definition XMLObject.h:115
const T * get() const
Attempt to cast the current instance to the specified type T.
Definition XMLObject.h:184
Attributes attributes
Definition bpmn++.h:250
const T * is() const
Definition XMLObject.h:162
std::vector< std::reference_wrapper< T > > find()
Find all descendants of type T.
Definition XMLObject.h:222
std::optional< std::reference_wrapper< T > > getOptionalChild()
Get an optional child of type T.
Definition XMLObject.h:287
std::optional< std::reference_wrapper< Attribute > > getOptionalAttributeByName(const AttributeName &attributeName)
Get an optional attribute with the specified attribute name.
ElementName elementName
Definition bpmn++.h:246
const ClassName className
Definition bpmn++.h:244
static XMLObject * createObject(const xercesc::DOMElement *element)
std::string format(std::string indentation="\t", unsigned int depth=0) const
Creates formated string representing the XMLObject including its children.
static XMLObject * createFromFile(const std::string &filename)
Create an XMLObject from an XML file.
Children children
Child nodes of the XML element.
Definition bpmn++.h:249
Namespace prefix
Definition bpmn++.h:245
T * is()
Returns a pointer of type T of the object.
Definition XMLObject.h:158
static Factory factory
Definition bpmn++.h:156
XMLObject & getRequiredChildByName(const ElementName &elementName)
Get a required child with the specified element name.
TextContent textContent
Textual content of XML element without children.
Definition bpmn++.h:248
std::string stringify() const
Convert the XMLObject and its children to a string representation.
std::vector< std::reference_wrapper< XMLObject > > getChildrenByName(const ElementName &elementName)
Get all children with the specified element name.
XMLObject(const Namespace &xmlns, const ClassName &className, const xercesc::DOMElement *element, const Attributes &defaultAttributes)
static XMLObject * createFromStream(std::istream &xmlStream)
Create an XMLObject from the input stream.
friend XMLObject * createInstance(const Namespace &xmlns, const ClassName &className, const xercesc::DOMElement *element)
Template function used to store in factory.
Definition bpmn++.h:85
static XMLObject * createFromString(const std::string &xmlString)
Create an XMLObject from a string representation of XML.
std::vector< std::reference_wrapper< const T > > find() const
Find all descendants of type T.
Definition XMLObject.h:235
std::optional< std::reference_wrapper< XMLObject > > getOptionalChildByName(const ElementName &elementName)
Get the optional child with the specified element name.
virtual ~XMLObject()
Definition XMLObject.h:145
std::vector< std::reference_wrapper< T > > getChildren()
Get all children of type T.
Definition XMLObject.h:301
T * get()
Attempt to cast the current instance to the specified type T.
Definition XMLObject.h:171
Attribute & getRequiredAttributeByName(const AttributeName &attributeName)
Get a required attribute with the specified attribute name.
static const Attributes defaults
Attributes of the XML element.
Definition bpmn++.h:251
Namespace xmlns
Definition bpmn++.h:243
T & getRequiredChild()
Get a required child of type T.
Definition XMLObject.h:272
The XML namespace contains classes representing XML-nodes defined in given XML-schema(s).
Definition bpmn++.h:18
std::string ElementName
Definition bpmn++.h:23
std::string Namespace
Definition bpmn++.h:25
std::ostream & operator<<(std::ostream &os, const XMLObject *obj)
Allows printing of stringified XML object.
std::string ClassName
Definition bpmn++.h:22
std::vector< std::unique_ptr< XMLObject > > Children
Definition bpmn++.h:82
XMLObject * createInstance(const Namespace &xmlns, const ClassName &className, const xercesc::DOMElement *element)
Template function used to store in factory.
Definition bpmn++.h:85
std::vector< Attribute > Attributes
Definition bpmn++.h:81
std::string AttributeName
Definition bpmn++.h:26
std::unordered_map< ElementName, XMLObject *(*)(const Namespace &xmlns, const ClassName &className, const xercesc::DOMElement *element)> Factory
Factory used to create instance depending on element name.
Definition bpmn++.h:88
std::string TextContent
Definition bpmn++.h:24
STL namespace.
A struct representing an attribute of an XML-node.
Definition XMLObject.h:73
Value value
Definition bpmn++.h:78
Namespace prefix
Definition bpmn++.h:76
AttributeName name
Definition bpmn++.h:77
Namespace xmlns
Definition bpmn++.h:75
A struct representing the value of an XML-node attribute.
Definition XMLObject.h:48
Value(const std::string &s)
Definition XMLObject.h:59
Value & operator=(bool b)
Definition XMLObject.h:56
Value(bool b)
Definition XMLObject.h:60
Value & operator=(double d)
Definition XMLObject.h:58
static std::string True
Definition bpmn++.h:64
Value(int i)
Definition XMLObject.h:61
Value & operator=(const std::string &s)
Definition XMLObject.h:55
Value & operator=(int i)
Definition XMLObject.h:57
static std::string False
Definition bpmn++.h:65
std::string value
Definition bpmn++.h:50
Value(double d)
Definition XMLObject.h:62