Mana
Loading...
Searching...
No Matches
xml.h
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include "utils/stringutils.h"
25
26#include <libxml/parser.h>
27#include <libxml/tree.h>
28#include <libxml/xmlwriter.h>
29
30#include <string_view>
31
35namespace XML
36{
37 class Node
38 {
39 public:
40 Node(xmlNodePtr node = nullptr)
41 : node(node)
42 {}
43
44 operator bool() const { return node != nullptr; }
45
46 std::string_view name() const { return (const char *) node->name; }
47 std::string_view textContent() const;
48
49 template<typename T>
50 bool attribute(const char *name, T &value) const;
51
52 bool hasAttribute(const char *name) const;
53 int getProperty(const char *name, int def) const;
54 double getFloatProperty(const char *name, double def) const;
55 std::string getProperty(const char *name, const std::string &def) const;
56 bool getBoolProperty(const char *name, bool def) const;
57 Node findFirstChildByName(const char *name) const;
58
64 {
65 public:
67 {
68 public:
69 explicit Iterator(xmlNodePtr node) : mNode(node)
70 {
71 while (mNode && mNode->type != XML_ELEMENT_NODE)
72 mNode = mNode->next;
73 }
74
75 bool operator!=(const Iterator &other) const { return mNode != other.mNode; }
77 {
78 do {
79 mNode = mNode->next;
80 } while (mNode && mNode->type != XML_ELEMENT_NODE);
81 }
82 Node operator*() const { return mNode; }
83
84 private:
85 xmlNodePtr mNode;
86 };
87
88 explicit Children(xmlNodePtr node) : mNode(node) {}
89
90 Iterator begin() const { return Iterator(mNode->children); }
91 Iterator end() const { return Iterator(nullptr); }
92
93 private:
94 xmlNodePtr mNode;
95 };
96
97 Children children() const { return Children(node); }
98
99 private:
100 const char *attribute(const char *name) const;
101
102 xmlNodePtr node;
103 };
104
105 inline std::string_view Node::textContent() const
106 {
107 if (node->children && node->children->type == XML_TEXT_NODE)
108 return (const char *) node->children->content;
109 return {};
110 }
111
112 inline const char *Node::attribute(const char *name) const
113 {
114 if (node->type != XML_ELEMENT_NODE)
115 return nullptr;
116
117 for (xmlAttrPtr prop = node->properties; prop; prop = prop->next) {
118 if (xmlStrEqual(prop->name, BAD_CAST name)) {
119 if (prop->children)
120 return reinterpret_cast<const char*>(prop->children->content);
121 else
122 return nullptr;
123 }
124 }
125 return nullptr;
126 }
127
128 template<typename T>
129 inline bool Node::attribute(const char *name, T &value) const
130 {
131 if (const char *str = attribute(name))
132 {
133 fromString(str, value);
134 return true;
135 }
136 return false;
137 }
138
139 inline bool Node::hasAttribute(const char *name) const
140 {
141 return attribute(name) != nullptr;
142 }
143
144 inline int Node::getProperty(const char *name, int def) const
145 {
146 int ret = def;
147 if (const char *str = attribute(name))
148 fromString(str, ret);
149 return ret;
150 }
151
152 inline double Node::getFloatProperty(const char *name, double def) const
153 {
154 double ret = def;
155 if (const char *str = attribute(name))
156 fromString(str, ret);
157 return ret;
158 }
159
160 inline std::string Node::getProperty(const char *name, const std::string &def) const
161 {
162 if (const char *str = attribute(name))
163 return str;
164
165 return def;
166 }
167
168 inline bool Node::getBoolProperty(const char *name, bool def) const
169 {
170 bool ret = def;
171 if (const char *str = attribute(name))
172 ret = getBoolFromString(str, def);
173 return ret;
174 }
175
176 inline Node Node::findFirstChildByName(const char *name) const
177 {
178 for (auto child : children())
179 if (child.name() == name)
180 return child;
181
182 return nullptr;
183 }
184
190 {
191 public:
196 Document(const std::string &filename, bool useResman = true);
197
201 ~Document();
202
207 Node rootNode() const;
208
209 private:
210 xmlDocPtr mDoc;
211 };
212
214 {
215 return mDoc ? xmlDocGetRootElement(mDoc) : nullptr;
216 }
217
221 void init();
222
228 class Writer
229 {
230 public:
231 Writer(const std::string &fileName);
232 ~Writer();
233
234 bool isValid() const { return mWriter != nullptr; }
235
236 void startElement(const char *name);
237 void endElement();
238
239 void addAttribute(const char *name, const std::string &value);
240 void addAttribute(const char *name, const char *value);
241 void addAttribute(const char *name, int value);
242 void addAttribute(const char *name, unsigned value);
243 void addAttribute(const char *name, float value);
244 void addAttribute(const char *name, bool value);
245
246 template<typename Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true>
247 void addAttribute(const char *name, Enum &value);
248
249 void writeText(const std::string &text);
250
251 private:
252 xmlTextWriterPtr mWriter;
253 };
254
255 template<typename Enum, std::enable_if_t<std::is_enum_v<Enum>, bool>>
256 inline void Writer::addAttribute(const char *name, Enum &value)
257 {
258 return addAttribute(name, static_cast<int>(value));
259 }
260
261 inline void Writer::startElement(const char *name)
262 {
263 xmlTextWriterStartElement(mWriter, BAD_CAST name);
264 }
265
266 inline void Writer::endElement()
267 {
268 xmlTextWriterEndElement(mWriter);
269 }
270
271 inline void Writer::addAttribute(const char *name, const std::string &value)
272 {
273 addAttribute(name, value.c_str());
274 }
275
276 inline void Writer::addAttribute(const char *name, const char *value)
277 {
278 xmlTextWriterWriteAttribute(mWriter, BAD_CAST name, BAD_CAST value);
279 }
280
281 inline void Writer::addAttribute(const char *name, int value)
282 {
283 xmlTextWriterWriteAttribute(mWriter, BAD_CAST name, BAD_CAST toString(value).c_str());
284 }
285
286 inline void Writer::addAttribute(const char *name, unsigned value)
287 {
288 xmlTextWriterWriteAttribute(mWriter, BAD_CAST name, BAD_CAST toString(value).c_str());
289 }
290
291 inline void Writer::addAttribute(const char *name, float value)
292 {
293 xmlTextWriterWriteAttribute(mWriter, BAD_CAST name, BAD_CAST toString(value).c_str());
294 }
295
296 inline void Writer::addAttribute(const char *name, bool value)
297 {
298 xmlTextWriterWriteAttribute(mWriter, BAD_CAST name, BAD_CAST (value ? "1" : "0"));
299 }
300
301 inline void Writer::writeText(const std::string &text)
302 {
303 xmlTextWriterWriteString(mWriter, BAD_CAST text.c_str());
304 }
305}
A helper class for parsing an XML document, which also cleans it up again (RAII).
Definition xml.h:190
~Document()
Destructor.
Definition xml.cpp:89
Node rootNode() const
Returns the root node of the document (or NULL if there was a load error).
Definition xml.h:213
xmlDocPtr mDoc
Definition xml.h:210
Iterator(xmlNodePtr node)
Definition xml.h:69
bool operator!=(const Iterator &other) const
Definition xml.h:75
Node operator*() const
Definition xml.h:82
Helper class to iterate over the children of a node.
Definition xml.h:64
Iterator end() const
Definition xml.h:91
Iterator begin() const
Definition xml.h:90
xmlNodePtr mNode
Definition xml.h:94
Children(xmlNodePtr node)
Definition xml.h:88
std::string_view name() const
Definition xml.h:46
int getProperty(const char *name, int def) const
Definition xml.h:144
double getFloatProperty(const char *name, double def) const
Definition xml.h:152
Node(xmlNodePtr node=nullptr)
Definition xml.h:40
Node findFirstChildByName(const char *name) const
Definition xml.h:176
xmlNodePtr node
Definition xml.h:102
Children children() const
Definition xml.h:97
std::string_view textContent() const
Definition xml.h:105
bool hasAttribute(const char *name) const
Definition xml.h:139
bool attribute(const char *name, T &value) const
Definition xml.h:129
bool getBoolProperty(const char *name, bool def) const
Definition xml.h:168
Helper class for writing out XML data.
Definition xml.h:229
void writeText(const std::string &text)
Definition xml.h:301
void startElement(const char *name)
Definition xml.h:261
xmlTextWriterPtr mWriter
Definition xml.h:252
void addAttribute(const char *name, const std::string &value)
Definition xml.h:271
void endElement()
Definition xml.h:266
bool isValid() const
Definition xml.h:234
XML helper functions.
Definition xml.cpp:31
void init()
Initializes the XML engine.
Definition xml.cpp:95
bool getBoolFromString(std::string text, bool def)
Returns a bool value depending on the given string value.
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
Definition stringutils.h:68
void fromString(const char *str, FillMode &value)
Definition theme.cpp:640