PLCnext API Documentation 26.0.1.58
XmlReader.hpp
1
2//
3// Copyright Phoenix Contact GmbH & Co. KG
4//
6#pragma once
8#include "Arp/System/Core/Enum.hxx"
9#include "Arp/System/Core/TypeName.hxx"
10#include "Arp/System/Commons/Chrono/Duration.hpp"
11#include "Arp/System/Commons/Exceptions/Exceptions.h"
12#include "Arp/System/Commons/Xml/XmlErrorHandler.hpp"
13#include "Arp/System/Commons/Xml/XmlNodeType.hpp"
14#include "Arp/Base/Core/Convert.hpp"
15
16#include <sstream>
17#include "boost/lexical_cast.hpp"
18
19namespace Arp { namespace System { namespace Commons { namespace Xml
20{
21
22class LibXmlErrorHandler;
23
26{
27public: // typedefs
28public: // construction/destruction
29 XmlReader(void);
30 XmlReader(XmlReader&& arg);
31 ~XmlReader(void);
32
33private: // construction/destruction
34 XmlReader(void* pReader);
35 XmlReader(const XmlReader& arg) = delete;
36 XmlReader& operator=(const XmlReader& arg) = delete;
37
38public: // static factory operations
39 static XmlReader Create(const String& filename);
40 static bool TryCreate(const String& filename, XmlReader& reader);
41
42 static XmlReader Create(const String& filename, const String& xsdFile);
43 static XmlReader CreateForString(const String& buffer);
44
45public: // setter/getter operations
47 long GetLineNumber();
49
50public: // operations
51 bool Read();
52 XmlNodeType GetCurrentNodeType();
53 bool IsEmptyElement();
54 int GetCurrentDepth();
55
56 ARP_DEPRECATED("Use SkipElement() instead.")
57 bool Skip();
58 bool SkipElement();
59 bool SkipElementContent();
60
61 bool MoveToElement();
62
63 bool ReadToFollowing(const String& name);
64 bool ReadToDescendant(const String& name);
65 bool ReadToNextSibling(const String& name);
66
67 void ReadStartElement(const char* elementName = nullptr);
68 bool TryReadStartElement(const char* elementName = nullptr);
69 bool TryReadStartElement(String& elementName, bool conditioned = true);
70
71 void ReadEndElement(void);
72 bool TryReadEndElement(void);
74
75 template<class T>
76 T GetAndResolveAttributeValue(const char* attributeName);
77
78 template<class T>
79 bool TryGetAndResolveAttributeValue(const char* attributeName, T& value);
80
81 template<class T>
82 bool TryGetAndResolveAttributeValue(const char* attributeName, T defaultValue, T& value);
83
91 template<class T>
93 {
94 String elementString = this->ReadElementContent();
95 try
96 {
97 return boost::lexical_cast<T>(elementString);
98 }
99 catch (std::exception& e)
100 {
102 this->GetDocumentFileName(),
103 this->GetLineNumber(),
104 "Cannot convert '{}' to {}: {}", elementString, TypeName<T>().GetFullName(), e.what());
105 }
106 }
107
119 template<class T>
120 T GetAttributeValue(const char* attributeName)
121 {
122 T returnValue;
123 if (TryGetAttributeValue<T>(attributeName, returnValue))
124 {
125 return returnValue;
126 }
127 else
128 {
129 throw XmlException(
130 "GetAttributeValue failed for mandatory attribute: {0} elementName: {1}",
131 attributeName, GetElementLocalName());
132 }
133 }
134
146 template<class T>
147 Enum<T> GetAttributeValueEnum(const char* attributeName)
148 {
149 Enum<T> returnValue;
150
151 if (TryGetAttributeValueEnum<T>(attributeName, returnValue))
152 {
153 return returnValue;
154 }
155 else
156 {
157 throw XmlException(
158 "GetAttributeValueEnum failed for mandatory attribute: {0} elementName: {1}",
159 attributeName, GetElementLocalName());
160 }
161 }
162
174 template<class T>
175 T GetAttributeValueOfEnum(const char* attributeName)
176 {
177 T result;
178 if (!TryGetAttributeValueEnum<T>(attributeName, result))
179 {
180 throw XmlException(
181 "GetAttributeValueOfEnum failed for mandatory attribute: {0} elementName: {1}", attributeName, GetElementLocalName());
182 }
183 return result;
184 }
185
200 template<class T>
201 bool TryGetAttributeValueEnum(const char* attributeName, T& value)
202 {
203 char* charValue = GetAttributeValueInternal(attributeName);
204 if (charValue == nullptr)
205 {
206 return false;
207 }
208 std::istringstream iss(charValue);
209 iss >> value;
210 FreeInternalAttributeValue(charValue);
211 return true;
212 }
213
228 template<class T>
229 bool TryGetAttributeValueEnum(const char* attributeName, Enum<T>& value)
230 {
231 char* charValue = GetAttributeValueInternal(attributeName);
232 if (charValue == nullptr)
233 {
234 return false;
235 }
236
237 value = Enum<T>::Parse(charValue);
238 FreeInternalAttributeValue(charValue);
239 return true;
240 }
241
259 template<class T>
260 bool TryGetAttributeValueEnum(const char* attributeName, T defaultValue, Enum<T>& value)
261 {
262 value = defaultValue;
263 return TryGetAttributeValueEnum<T>(attributeName, value);
264 }
265
266
279 template<class T>
280 T GetAttributeValueDuration(const char* attributeName)
281 {
282 T returnValue;
283
284 if (TryGetAttributeValueDuration<T>(attributeName, returnValue))
285 {
286 return returnValue;
287 }
288 else
289 {
290 throw XmlException(
291 "GetAttributeValueDuration failed for mandatory attribute: {0} elementName: {1}",
292 attributeName, GetElementLocalName());
293 }
294 }
308 template<class T>
309 bool TryGetAttributeValueDuration(const char* attributeName, T& value)
310 {
311 return this->TryGetAttributeValue(attributeName, value);
312 }
313
331 template<class T>
332 bool TryGetAttributeValueDuration(const char* attributeName, T defaultValue, T& value)
333 {
334 value = defaultValue;
335 return TryGetAttributeValueDuration<T>(attributeName, value);
336 }
337
338
352 template<class T>
353 bool TryGetAttributeValue(const char* attributeName, T& value)
354 {
355 char* charValue = nullptr;
356 try
357 {
358 charValue = GetAttributeValueInternal(attributeName);
359 if (charValue == nullptr)
360 {
361 return false;
362 }
363
364 value = boost::lexical_cast<T>(charValue);
365 FreeInternalAttributeValue(charValue);
366 return true;
367 }
368 catch (boost::bad_lexical_cast&)
369 {
370
371 String strValue(charValue);
372 FreeInternalAttributeValue(charValue);
373 throw XmlException("Cast of attribute {0} to {1} failed value: {2}", attributeName,
374 TypeName<T>(), strValue);
375 }
376 }
377
378
396 template<class T>
397 bool TryGetAttributeValue(const char* attributeName, T defaultValue, T& value)
398 {
399 value = defaultValue;
400 return TryGetAttributeValue<T>(attributeName, value);
401 }
402
403 void EnableValidationException();
404 void DisableValidationException();
405
415 template<typename... Args>
416 XmlException CreateException(const char* message, const Args& ... args);
417
418protected: // operations
419private: // static methods
420private: // methods
421 int ReaderState();
422 char* GetAttributeValueInternal(const char* attributeName);
423 void FreeInternalAttributeValue(char* attributeValue);
424 XmlNodeType MoveToContent();
425 void EnableValidation(const String& xsdFile);
426 void CheckForValidationException();
427 bool MoveToNextElement(void);
428 String GetAndResolveAttributeValueInternal(const char* attributeName);
429
430private: // fields
431 String filename;
432 // internal reader ptr
433 void* reader;
434 bool validationEnabled;
435 LibXmlErrorHandler* errorHandler;
436 bool exceptionOnValidationError; // defines whether to throw an exception when a validation
437 // error occurs while parsing
438 String lastError;
439 bool startElementRead;
440
441private: // static fields
442};
443
444// gcc does not allow full template specialization in class definition
445// boost::lexical_cast does not understand true and false so implement special version
446template<>
447bool XmlReader::TryGetAttributeValue(const char*, bool& value);
448
449template<>
450bool XmlReader::TryGetAttributeValue(const char* attributeName, String& value);
451
452template<>
453bool XmlReader::TryGetAttributeValue(const char* attributeName, Chrono::Duration& value);
454
455template<>
456bool XmlReader::TryGetAttributeValue(const char* attributeName, uint8& value);
457
458template<>
459bool XmlReader::TryGetAttributeValue(const char* attributeName, int8& value);
460
462// inline methods of class XmlReader
463template<typename... Args>
464inline XmlException XmlReader::CreateException(const char* message, const Args& ... args)
465{
466 return XmlException::Create(this->filename, this->GetLineNumber(), message, args...);
467}
468
480template<class T>
481inline T XmlReader::GetAndResolveAttributeValue(const char* attributeName)
482{
483 T returnValue{};
484 if (TryGetAndResolveAttributeValue(attributeName, returnValue))
485 {
486 return returnValue;
487 }
488 else
489 {
490 throw XmlException(
491 "GetAndResolveAttributeValue failed for mandatory attribute: {0} elementName: {1}",
492 attributeName, GetElementLocalName());
493 }
494}
495
512template<class T>
513inline bool XmlReader::TryGetAndResolveAttributeValue(const char* attributeName, T& value)
514{
515 String strValue{};
516 try
517 {
518 strValue = this->GetAndResolveAttributeValueInternal(attributeName);
519
520 if (strValue.IsEmpty())
521 {
522 return false;
523 }
524
525 value = Convert::ToValue<T>(strValue);
526
527 return true;
528 }
529 catch (Exception&)
530 {
531 throw XmlException("Could not convert attribute {0} to {1} failed value: {2}", attributeName,
532 TypeName<T>(), strValue);
533 }
534}
535
556template<class T>
557inline bool XmlReader::TryGetAndResolveAttributeValue(const char* attributeName, T defaultValue, T& value)
558{
559 value = defaultValue;
560 return this->TryGetAndResolveAttributeValue(attributeName, value);
561}
562
564// inline methods
565
566}}}} // namespace Arp::System::Commons::Xml
Adapter class for enums to make them loggable and parsable from e.g. XML files.
Definition: Enum.hxx:21
This is the base class of all Arp exception classes.
Definition: Exception.hpp:21
This class represents the Arp String. The implementation is based on std::string.
Definition: String.hpp:39
This (meta programming) class provides the C++ type-name of the as template argument passed type.
Definition: TypeName.hxx:20
Definition: Duration.hpp:16
This exception is used for xml parsing errors.
Definition: XmlException.hpp:15
static XmlException Create(void)
Creates an XmlException instance using a default message text.
Definition: XmlException.cpp:47
Class to read an XML File. Non buffered reader, can only read forward
Definition: XmlReader.hpp:26
bool TryGetAttributeValueEnum(const char *attributeName, T &value)
trys reads an attribute value from the current element and converts the String to Enum<T>
Definition: XmlReader.hpp:201
XmlException CreateException(const char *message, const Args &... args)
Creates an exception by prefixing the given message with current doc name and line number
Definition: XmlReader.hpp:464
T ReadElementContent()
reads the content of the current element if a CDATA section is found, the CDATA enclosure is removed
Definition: XmlReader.hpp:92
T GetAttributeValue(const char *attributeName)
reads an attribute value from the current element
Definition: XmlReader.hpp:120
int GetCurrentDepth()
gets the current depth of the current element inside the xml document
Definition: XmlReader.cpp:357
bool Read()
Reads to the next element inside the xml file
Definition: XmlReader.cpp:215
Enum< T > GetAttributeValueEnum(const char *attributeName)
reads an attribute value from the current element and converts the String to Enum<T>
Definition: XmlReader.hpp:147
XmlNodeType GetCurrentNodeType()
gets the type of the current xml element
Definition: XmlReader.cpp:245
bool ReadToNextSibling(const String &name)
reads to the next element with name which is a sibling of the current element
Definition: XmlReader.cpp:551
bool IsEmptyElement()
test if the current element is an empty element
Definition: XmlReader.cpp:334
bool TryGetAttributeValue(const char *attributeName, T defaultValue, T &value)
tries to read an attribute value from the current element if the attribute was not found or the conve...
Definition: XmlReader.hpp:397
bool SkipElement()
skips the current element with its whole subtree
Definition: XmlReader.cpp:388
bool TryGetAttributeValueDuration(const char *attributeName, T defaultValue, T &value)
tries to read an attribute value from the current element as std::crono::duration if the attribute wa...
Definition: XmlReader.hpp:332
XmlReader(void)
Default contructor.
Definition: XmlReader.cpp:23
bool TryGetAndResolveAttributeValue(const char *attributeName, T &value)
tries to read and resolve an attribute placeholder from the current element
Definition: XmlReader.hpp:513
bool TryGetAttributeValueEnum(const char *attributeName, Enum< T > &value)
trys reads an attribute value from the current element and converts the String to Enum<T>
Definition: XmlReader.hpp:229
void ReadStartElement(const char *elementName=nullptr)
reads to the next element and test if this is a start element with the given name
Definition: XmlReader.cpp:593
T GetAndResolveAttributeValue(const char *attributeName)
reads and resolve an attribute value from the current element
Definition: XmlReader.hpp:481
static XmlReader CreateForString(const String &buffer)
Creates a new Instance of the XmlReader reading from an in memory buffer
Definition: XmlReader.cpp:149
bool TryReadStartElement(const char *elementName=nullptr)
trys to read the next element and test if this is a start element with the given name
Definition: XmlReader.cpp:614
bool MoveToElement()
Moves the position of the current instance to the node that contains the current Attribute node.
Definition: XmlReader.cpp:268
T GetAttributeValueOfEnum(const char *attributeName)
reads an attribute value from the current element and converts the String to Enum<T>
Definition: XmlReader.hpp:175
const String & GetDocumentFileName()
Gets the current document filename of this XML reader
Definition: XmlReader.cpp:204
void ReadEndElement(void)
reads until the next end element is reached skips over an empty element
Definition: XmlReader.cpp:714
T GetAttributeValueDuration(const char *attributeName)
reads an attribute value from the current element and converts the String to std::chrono::duration i....
Definition: XmlReader.hpp:280
bool ReadToDescendant(const String &name)
reads the xml file until an element with name is reached or the current element is closed reads to th...
Definition: XmlReader.cpp:516
bool Skip()
skips the current element with its whole subtree (use SkipElement() because naming is more clear)
Definition: XmlReader.cpp:377
bool SkipElementContent()
skips the content of current element with its whole subtree but does not read end element tag
Definition: XmlReader.cpp:422
String ReadElementContent(void)
reads the content of the current element if a CDATA section is found, the CDATA enclosure is removed
Definition: XmlReader.cpp:770
~XmlReader(void)
Destructs this instance and frees all resources.
Definition: XmlReader.cpp:49
static XmlReader Create(const String &filename)
Creates a new Instance of the XmlReader
Definition: XmlReader.cpp:82
bool TryGetAttributeValueEnum(const char *attributeName, T defaultValue, Enum< T > &value)
tries to read an attribute value from the current element as enum if the attribute was not found or t...
Definition: XmlReader.hpp:260
static bool TryCreate(const String &filename, XmlReader &reader)
Tries to creates a new Instance of the XmlReader
Definition: XmlReader.cpp:100
long GetLineNumber()
Gets the actual line number of this XML reader
Definition: XmlReader.cpp:192
String GetElementLocalName(void)
Reads the local name of the current active element
Definition: XmlReader.cpp:171
bool TryReadEndElement(void)
tries to read until the next end element is reached skips over an empty element
Definition: XmlReader.cpp:729
bool ReadToFollowing(const String &name)
reads the xml file until an element with name is reached or end of file is reached
Definition: XmlReader.cpp:492
bool TryGetAttributeValueDuration(const char *attributeName, T &value)
trys reads an attribute value from the current element and converts the String to std::chrono::durati...
Definition: XmlReader.hpp:309
bool TryGetAttributeValue(const char *attributeName, T &value)
tries to read an attribute value from the current element
Definition: XmlReader.hpp:353
static Enum Parse(const String &input)
Parses the given input string.
Definition: Enum.ipp:90
std::uint8_t uint8
The Arp unsigned integer type of 1 byte size.
Definition: PrimitiveTypes.hpp:25
std::int8_t int8
The Arp integer type of 1 byte size.
Definition: PrimitiveTypes.hpp:27
Root namespace for the PLCnext API
class ARP_DEPRECATED("Use Arp::Enum<T> instead.") EnumStrings
Deprecated! The class implements an adapter for enums to define the string literals of the enum entri...
Definition: EnumStrings.hxx:38