PLCnext API Documentation 25.0.2.69
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
15#include <sstream>
16#include "boost/lexical_cast.hpp"
17
18namespace Arp { namespace System { namespace Commons { namespace Xml
19{
20
21class LibXmlErrorHandler;
22
25{
26public: // typedefs
27public: // construction/destruction
28 XmlReader(void);
29 XmlReader(XmlReader&& arg);
30 ~XmlReader(void);
31
32private: // construction/destruction
33 XmlReader(void* pReader);
34 XmlReader(const XmlReader& arg) = delete;
35 XmlReader& operator=(const XmlReader& arg) = delete;
36
37public: // static factory operations
38 static XmlReader Create(const String& filename);
39 static bool TryCreate(const String& filename, XmlReader& reader);
40
41 static XmlReader Create(const String& filename, const String& xsdFile);
42 static XmlReader CreateForString(const String& buffer);
43
44public: // setter/getter operations
46 long GetLineNumber();
48
49public: // operations
50 bool Read();
51 XmlNodeType GetCurrentNodeType();
52 bool IsEmptyElement();
53 int GetCurrentDepth();
54
55 ARP_DEPRECATED("Use SkipElement() instead.")
56 bool Skip();
57 bool SkipElement();
58 bool SkipElementContent();
59
60 bool MoveToElement();
61
62 bool ReadToFollowing(const String& name);
63 bool ReadToDescendant(const String& name);
64 bool ReadToNextSibling(const String& name);
65
66 void ReadStartElement(const char* elementName = nullptr);
67 bool TryReadStartElement(const char* elementName = nullptr);
68 bool TryReadStartElement(String& elementName, bool conditioned = true);
69
70 void ReadEndElement(void);
71 bool TryReadEndElement(void);
73
81 template<class T>
83 {
84 String elementString = this->ReadElementContent();
85 try
86 {
87 return boost::lexical_cast<T>(elementString);
88 }
89 catch (std::exception& e)
90 {
92 this->GetDocumentFileName(),
93 this->GetLineNumber(),
94 "Cannot convert '{}' to {}: {}", elementString, TypeName<T>().GetFullName(), e.what());
95 }
96 }
97
109 template<class T>
110 T GetAttributeValue(const char* attributeName)
111 {
112 T returnValue;
113 if (TryGetAttributeValue<T>(attributeName, returnValue))
114 {
115 return returnValue;
116 }
117 else
118 {
119 throw XmlException(
120 "GetAttributeValue failed for mandatory attribute: {0} elementName: {1}",
121 attributeName, GetElementLocalName());
122 }
123 }
124
136 template<class T>
137 Enum<T> GetAttributeValueEnum(const char* attributeName)
138 {
139 Enum<T> returnValue;
140
141 if (TryGetAttributeValueEnum<T>(attributeName, returnValue))
142 {
143 return returnValue;
144 }
145 else
146 {
147 throw XmlException(
148 "GetAttributeValueEnum failed for mandatory attribute: {0} elementName: {1}",
149 attributeName, GetElementLocalName());
150 }
151 }
152
164 template<class T>
165 T GetAttributeValueOfEnum(const char* attributeName)
166 {
167 T result;
168 if (!TryGetAttributeValueEnum<T>(attributeName, result))
169 {
170 throw XmlException(
171 "GetAttributeValueOfEnum failed for mandatory attribute: {0} elementName: {1}", attributeName, GetElementLocalName());
172 }
173 return result;
174 }
175
190 template<class T>
191 bool TryGetAttributeValueEnum(const char* attributeName, T& value)
192 {
193 char* charValue = GetAttributeValueInternal(attributeName);
194 if (charValue == nullptr)
195 {
196 return false;
197 }
198 std::istringstream iss(charValue);
199 iss >> value;
200 FreeInternalAttributeValue(charValue);
201 return true;
202 }
203
218 template<class T>
219 bool TryGetAttributeValueEnum(const char* attributeName, Enum<T>& value)
220 {
221 char* charValue = GetAttributeValueInternal(attributeName);
222 if (charValue == nullptr)
223 {
224 return false;
225 }
226
227 value = Enum<T>::Parse(charValue);
228 FreeInternalAttributeValue(charValue);
229 return true;
230 }
231
249 template<class T>
250 bool TryGetAttributeValueEnum(const char* attributeName, T defaultValue, Enum<T>& value)
251 {
252 value = defaultValue;
253 return TryGetAttributeValueEnum<T>(attributeName, value);
254 }
255
256
269 template<class T>
270 T GetAttributeValueDuration(const char* attributeName)
271 {
272 T returnValue;
273
274 if (TryGetAttributeValueDuration<T>(attributeName, returnValue))
275 {
276 return returnValue;
277 }
278 else
279 {
280 throw XmlException(
281 "GetAttributeValueDuration failed for mandatory attribute: {0} elementName: {1}",
282 attributeName, GetElementLocalName());
283 }
284 }
298 template<class T>
299 bool TryGetAttributeValueDuration(const char* attributeName, T& value)
300 {
301 return this->TryGetAttributeValue(attributeName, value);
302 }
303
321 template<class T>
322 bool TryGetAttributeValueDuration(const char* attributeName, T defaultValue, T& value)
323 {
324 value = defaultValue;
325 return TryGetAttributeValueDuration<T>(attributeName, value);
326 }
327
328
342 template<class T>
343 bool TryGetAttributeValue(const char* attributeName, T& value)
344 {
345 char* charValue = nullptr;
346 try
347 {
348 charValue = GetAttributeValueInternal(attributeName);
349 if (charValue == nullptr)
350 {
351 return false;
352 }
353
354 value = boost::lexical_cast<T>(charValue);
355 FreeInternalAttributeValue(charValue);
356 return true;
357 }
358 catch (boost::bad_lexical_cast&)
359 {
360
361 String strValue(charValue);
362 FreeInternalAttributeValue(charValue);
363 throw XmlException("Cast of attribute {0} to {1} failed value: {2}", attributeName,
364 TypeName<T>(), strValue);
365 }
366 }
367
368
386 template<class T>
387 bool TryGetAttributeValue(const char* attributeName, T defaultValue, T& value)
388 {
389
390 value = defaultValue;
391 return TryGetAttributeValue<T>(attributeName, value);
392 }
393
394 void EnableValidationException();
395 void DisableValidationException();
396
406 template<typename... Args>
407 XmlException CreateException(const char* message, const Args& ... args);
408
409protected: // operations
410private: // static methods
411private: // methods
412 int ReaderState();
413 char* GetAttributeValueInternal(const char* attributeName);
414 void FreeInternalAttributeValue(char* attributeValue);
415 XmlNodeType MoveToContent();
416 void EnableValidation(const String& xsdFile);
417 void CheckForValidationException();
418 bool MoveToNextElement(void);
419
420private: // fields
421 String filename;
422 // internal reader ptr
423 void* reader;
424 bool validationEnabled;
425 LibXmlErrorHandler* errorHandler;
426 bool exceptionOnValidationError; // defines whether to throw an exception when a validation
427 // error occurs while parsing
428 String lastError;
429 bool startElementRead;
430
431private: // static fields
432};
433
434// gcc does not allow full template specialization in class definition
435// boost::lexical_cast does not understand true and false so implement special version
436template<>
437bool XmlReader::TryGetAttributeValue(const char*, bool& value);
438
439template<>
440bool XmlReader::TryGetAttributeValue(const char* attributeName, String& value);
441
442template<>
443bool XmlReader::TryGetAttributeValue(const char* attributeName, Chrono::Duration& value);
444
445template<>
446bool XmlReader::TryGetAttributeValue(const char* attributeName, uint8& value);
447
448template<>
449bool XmlReader::TryGetAttributeValue(const char* attributeName, int8& value);
450
452// inline methods of class XmlReader
453template<typename... Args>
454inline XmlException XmlReader::CreateException(const char* message, const Args& ... args)
455{
456 return XmlException::Create(this->filename, this->GetLineNumber(), message, args...);
457}
458
459}}}} // 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 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:25
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:191
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:454
T ReadElementContent()
reads the content of the current element if a CDATA section is found, the CDATA enclosure is removed
Definition: XmlReader.hpp:82
T GetAttributeValue(const char *attributeName)
reads an attribute value from the current element
Definition: XmlReader.hpp:110
int GetCurrentDepth()
gets the current depth of the current element inside the xml document
Definition: XmlReader.cpp:330
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:137
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:524
bool IsEmptyElement()
test if the current element is an empty element
Definition: XmlReader.cpp:307
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:387
bool SkipElement()
skips the current element with its whole subtree
Definition: XmlReader.cpp:361
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:322
XmlReader(void)
Default contructor.
Definition: XmlReader.cpp:23
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:219
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:566
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:587
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:165
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:687
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:270
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:489
bool Skip()
skips the current element with its whole subtree (use SkipElement() because naming is more clear)
Definition: XmlReader.cpp:350
bool SkipElementContent()
skips the content of current element with its whole subtree but does not read end element tag
Definition: XmlReader.cpp:395
String ReadElementContent(void)
reads the content of the current element if a CDATA section is found, the CDATA enclosure is removed
Definition: XmlReader.cpp:743
~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:250
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:702
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:465
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:299
bool TryGetAttributeValue(const char *attributeName, T &value)
tries to read an attribute value from the current element
Definition: XmlReader.hpp:343
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