zen::Xml: bind.h Source File

| zen::Xml Simple C++ XML Processing

- Main Page
- Namespaces
- Classes

All Classes Namespaces Functions Variables Pages
bind.h
1 // *****************************************************************************
2 // * This file is part of the FreeFileSync project. It is distributed under *
3 // * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
4 // * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
5 // *****************************************************************************
6
7 #ifndef BIND_H_9081740816593478258435
8 #define BIND_H_9081740816593478258435
9
10 #include <set>
11 #include "cvrt_struc.h"
12 #include "parser.h"
13 #include "io.h"
14
15 namespace zen
16 {
22
32 template <class String> inline
33 XmlDoc load(const String& filename) //throw XmlFileError, XmlParsingError
34 {
35 std::string stream = loadStream(filename); //throw XmlFileError
36 return parse(stream); //throw XmlParsingError
37 }
38
39
41
51 template <class String> inline
52 void save(const XmlDoc& doc,
53 const String& filename,
54 const std::string& lineBreak = "\r\n",
55 const std::string& indent = " ") //throw XmlFileError
56 {
57 std::string stream = serialize(doc, lineBreak, indent); //throw ()
58 saveStream(stream, filename); //throw XmlFileError
59 }
60
61
63 class XmlOut
64 {
65 public:
67
88 XmlOut(XmlDoc& doc) : ref_(&doc.root()) {}
90
93 XmlOut(XmlElement& element) : ref_(&element) {}
94
96
101 template <class String>
102 XmlOut operator[](const String& name) const
103 {
104 const std::string utf8name = utfCvrtTo<std::string>(name);
105 XmlElement* child = ref_->getChild(utf8name);
106 return child ? *child : ref_->addChild(utf8name);
107 }
108
110
114 template <class T>
115 void operator()(const T& value) { writeStruc(value, *ref_); }
116
118
142 template <class String, class T>
143 void attribute(const String& name, const T& value) { ref_->setAttribute(name, value); }
144
146 XmlElement& ref() { return *ref_; }
147
148 private:
149 XmlElement* ref_; //always bound!
150 };
151
152
154 class XmlIn
155 {
156 class ErrorLog;
157
158 public:
160
170 XmlIn(const XmlDoc& doc) : log(std::make_shared<ErrorLog>()) { refList.push_back(&doc.root()); }
172
175 XmlIn(const XmlElement* element) : log(std::make_shared<ErrorLog>()) { refList.push_back(element); }
177
180 XmlIn(const XmlElement& element) : log(std::make_shared<ErrorLog>()) { refList.push_back(&element); }
181
183
188 template <class String>
189 XmlIn operator[](const String& name) const
190 {
191 std::vector<const XmlElement*> childList;
192
193 if (refIndex < refList.size())
194 {
195 auto iterPair = refList[refIndex]->getChildren(name);
196 std::for_each(iterPair.first, iterPair.second,
197 [&](const XmlElement& child) { childList.push_back(&child); });
198 }
199
200 return XmlIn(childList, childList.empty() ? getChildNameFormatted(name) : std::string(), log);
201 }
202
204
224 void next() { ++refIndex; }
225
227
232 template <class T>
233 bool operator()(T& value) const
234 {
235 if (refIndex < refList.size())
236 {
237 bool success = readStruc(*refList[refIndex], value);
238 if (!success)
239 log->notifyConversionError(getNameFormatted());
240 return success;
241 }
242 else
243 {
244 log->notifyMissingElement(getNameFormatted());
245 return false;
246 }
247 }
248
250
267 template <class String, class T>
268 bool attribute(const String& name, T& value) const
269 {
270 if (refIndex < refList.size())
271 {
272 bool success = refList[refIndex]->getAttribute(name, value);
273 if (!success)
274 log->notifyMissingAttribute(getNameFormatted(), utfCvrtTo<std::string>(name));
275 return success;
276 }
277 else
278 {
279 log->notifyMissingElement(getNameFormatted());
280 return false;
281 }
282 }
283
285 const XmlElement* get() const { return refIndex < refList.size() ? refList[refIndex] : nullptr; }
286
288
297 explicit operator bool() const { return get() != nullptr; }
298
300
319 bool errorsOccured() const { return !log->elementList().empty(); }
320
322
326 template <class String>
327 std::vector<String> getErrorsAs() const
328 {
329 std::vector<String> output;
330 const auto& elements = log->elementList();
331 std::transform(elements.begin(), elements.end(), std::back_inserter(output), [](const std::string& str) { return utfCvrtTo<String>(str); });
332 return output;
333 }
334
335 private:
336 XmlIn(const std::vector<const XmlElement*>& siblingList, const std::string& elementNameFmt, const std::shared_ptr<ErrorLog>& sharedlog) :
337 refList(siblingList), formattedName(elementNameFmt), log(sharedlog)
338 { assert((!siblingList.empty() && elementNameFmt.empty()) || (siblingList.empty() && !elementNameFmt.empty())); }
339
340 static std::string getNameFormatted(const XmlElement& elem) //"<Root> <Level1> <Level2>"
341 {
342 return (elem.parent() ? getNameFormatted(*elem.parent()) + " " : std::string()) + "<" + elem.getNameAs<std::string>() + ">";
343 }
344
345 std::string getNameFormatted() const
346 {
347 if (refIndex < refList.size())
348 {
349 assert(formattedName.empty());
350 return getNameFormatted(*refList[refIndex]);
351 }
352 else
353 return formattedName;
354 }
355
356 std::string getChildNameFormatted(const std::string& childName) const
357 {
358 std::string parentName = getNameFormatted();
359 return (parentName.empty() ? std::string() : (parentName + " ")) + "<" + childName + ">";
360 }
361
362 class ErrorLog
363 {
364 public:
365 void notifyConversionError (const std::string& displayName) { insert(displayName); }
366 void notifyMissingElement (const std::string& displayName) { insert(displayName); }
367 void notifyMissingAttribute(const std::string& displayName, const std::string& attribName) { insert(displayName + " @" + attribName); }
368
369 const std::vector<std::string>& elementList() const { return failedElements; }
370
371 private:
372 void insert(const std::string& newVal)
373 {
374 if (usedElements.insert(newVal).second)
375 failedElements.push_back(newVal);
376 }
377
378 std::vector<std::string> failedElements; //unique list of failed elements
379 std::set<std::string> usedElements;
380 };
381
382 std::vector<const XmlElement*> refList; //all sibling elements with same name (all pointers bound!)
383 size_t refIndex = 0; //this sibling's index in refList
384 std::string formattedName; //contains full and formatted element name if (and only if) refList is empty
385 std::shared_ptr<ErrorLog> log; //always bound
386 };
387 }
388
389 #endif //BIND_H_9081740816593478258435
zen::XmlIn::errorsOccured
bool errorsOccured() const
Notifies errors while mapping the XML to user data.
Definition: bind.h:319
zen::save
void save(const XmlDoc &doc, const String &filename, const std::string &lineBreak="\r\n", const std::string &indent=" ")
Save XML document to a file.
Definition: bind.h:52
zen::XmlDoc::root
const XmlElement & root() const
Get a const reference to the document's root element.
Definition: dom.h:264
zen::parse
XmlDoc parse(const std::string &stream)
Load XML document from a byte stream.
Definition: parser.h:576
zen::serialize
std::string serialize(const XmlDoc &doc, const std::string &lineBreak="\r\n", const std::string &indent=" ")
Save XML document as a byte stream.
Definition: parser.h:255
zen::XmlOut::XmlOut
XmlOut(XmlDoc &doc)
Construct an output proxy for an XML document.
Definition: bind.h:88
zen::XmlOut::ref
XmlElement & ref()
Return a reference to the underlying Xml element.
Definition: bind.h:146
zen::saveStream
void saveStream(const std::string &stream, const String &filename)
Save byte stream to a file.
Definition: io.h:66
zen::XmlIn
Proxy class to conveniently convert XML structure to user data.
Definition: bind.h:154
zen::XmlOut::operator()
void operator()(const T &value)
Write user data to the underlying XML element.
Definition: bind.h:115
zen::loadStream
std::string loadStream(const String &filename)
Load byte stream from a file.
Definition: io.h:94
zen::XmlIn::XmlIn
XmlIn(const XmlDoc &doc)
Construct an input proxy for an XML document.
Definition: bind.h:170
zen::XmlIn::XmlIn
XmlIn(const XmlElement &element)
Construct an input proxy for a single XML element.
Definition: bind.h:180
zen::XmlIn::next
void next()
Refer to next sibling element with the same name.
Definition: bind.h:224
std
STL namespace.
zen::XmlElement
An XML element.
Definition: dom.h:20
zen::XmlOut::attribute
void attribute(const String &name, const T &value)
Write user data to an XML attribute.
Definition: bind.h:143
zen
The zen::Xml namespace.
Definition: bind.h:15
zen::XmlIn::operator[]
XmlIn operator[](const String &name) const
Retrieve a handle to an XML child element for reading.
Definition: bind.h:189
zen::XmlDoc
The complete XML document.
Definition: dom.h:246
zen::XmlIn::attribute
bool attribute(const String &name, T &value) const
Read user data from an XML attribute.
Definition: bind.h:268
zen::XmlIn::getErrorsAs
std::vector< String > getErrorsAs() const
Get a list of XML element and attribute names which failed to convert to user data.
Definition: bind.h:327
zen::XmlOut
Proxy class to conveniently convert user data into XML structure.
Definition: bind.h:63
zen::XmlIn::operator()
bool operator()(T &value) const
Read user data from the underlying XML element.
Definition: bind.h:233
zen::XmlElement::addChild
XmlElement & addChild(const String &name)
Create a new child element and return a reference to it.
Definition: dom.h:95
zen::XmlElement::getChild
const XmlElement * getChild(const String &name) const
Retrieve a child element with the given name.
Definition: dom.h:111
zen::readStruc
bool readStruc(const XmlElement &input, T &value)
Convert XML element to structured user data.
Definition: cvrt_struc.h:204
zen::XmlElement::setAttribute
void setAttribute(const String &name, const T &value)
Create or update an XML attribute.
Definition: dom.h:75
zen::writeStruc
void writeStruc(const T &value, XmlElement &output)
Convert structured user data into an XML element.
Definition: cvrt_struc.h:197
zen::XmlOut::operator[]
XmlOut operator[](const String &name) const
Retrieve a handle to an XML child element for writing.
Definition: bind.h:102
zen::XmlIn::XmlIn
XmlIn(const XmlElement *element)
Construct an input proxy for a single XML element, may be nullptr.
Definition: bind.h:175
zen::XmlOut::XmlOut
XmlOut(XmlElement &element)
Construct an output proxy for a single XML element.
Definition: bind.h:93
zen::load
XmlDoc load(const String &filename)
Load XML document from a file.
Definition: bind.h:33