GXml.hpp
11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/***************************************************************************
* GXml.hpp - XML class *
* ----------------------------------------------------------------------- *
* copyright (C) 2010-2014 by Juergen Knoedlseder *
* ----------------------------------------------------------------------- *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
***************************************************************************/
/**
* @file GXml.hpp
* @brief XML class interface definition
* @author Juergen Knoedlseder
*/
#ifndef GXML_HPP
#define GXML_HPP
/* __ Includes ___________________________________________________________ */
#include <string>
#include "GContainer.hpp"
#include "GUrl.hpp"
#include "GXmlNode.hpp"
#include "GXmlDocument.hpp"
#include "GXmlElement.hpp"
#include "GXmlText.hpp"
/* __ Forward declarations _______________________________________________ */
/***********************************************************************//**
* @class GXml
*
* @brief XML class
*
* This class holds the content of an Extensible Markup Language (XML)
* document. An XML document is composed of a list of nodes, each of which
* may contain lists of nodes, which again can contain list of nodes and so
* on. This produces a tree made of nodes with an arbitrary complexity.
* Nodes that do not contain any further nodes are the endpoints of the tree
* that are called leafs.
*
* An example of an XML document is shown below
*
* <?xml version="1.0" encoding="UTF-8" ?>
* <element type="Measurement">
* <parameter name="Flux" value="1.0"/>
* </element>
* <element>
* <list>
* <string>This is a text</string>
* <integer>17</integer>
* </list>
* </element>
*
* An XML document is a plain ASCII file. Every XML document begins by a
* declaration of the XML version and an optional information about the
* encoding of the text.
*
* The XML document is structured using @b tags. A tag is a markup construct
* that begins with @< and ends with @>. Tags come in three flavors:
* - start-tags; for example: @<section@>
* - end-tags; for example: @</section@>
* - empty-element tags; for example: @<line-break /@>
*
* The header line of an XML document is an empty-element tag. Each tag may
* contain an arbitrary number of @b attributes of the form
*
* version="1.0"
*
* Alternative quotes ' are also allowed.
*
* A logical document component which either begins with a start-tag and ends
* with a matching end-tag or consists only of an empty-element tag is called
* an @b element. The characters between the start- and end-tags, if any, are
* the element's content, and may contain markup, including other elements,
* which are called @b child @b elements. An example of an element is
*
*
* <string>This is a text</string>
*
* Another is
*
* <parameter name="Flux" value="1.0"/>
*
* This last example has two attributes. The first word in an element is
* called the @b element @b name. Every element has a name. Elements can
* therefore be accessed by name, however, several elements with the same
* name may exist.
*
* GammaLib implements the XML document in form of a master class GXml
* which contains the root node of the document. The root node is
* realized by the GXmlDocument class. GXmlDocument derives from GXmlNode,
* which defines the abstract interface for all XML nodes. The following
* XML nodes exist:
* - GXmlElement: implements an element
* - GXmlText: implements a text leaf
* - GXmlPI: implements a Processing Instruction
* - GXmlComment: implement a comment
*
* XML element attributes are implemented using GXmlAttribute.
*
* The GXml class provides methods to access the nodes of the XML document,
* and to load and save the document from a URL. GXml derives from GContainer
* as it behaves like a container class. It does, however, not contain an
* explicit list, as the only data member of the class is a single instance
* of GXmlDocument. GXmlDocument contains the hierarchical list of all XML
* nodes.
*
* To manipulate the child nodes of GXmlDocument, the usual container class
* methods are available. size() returns the number of child nodes that
* exist in the XML document root (in the above example there would be two
* child elements with name @p element). The child nodes are accessed using
* the operator[]. The is_empty() method checks whether the document root has
* no children.
*
* The set() method allows to set a specific child node, the append() method
* appends a child node to the XML document root. There is a second variant
* of the append() method that appends a element of type GXmlElement to the
* XML document root and that returns a pointer to this element. As argument,
* this second method takes a text string that defines the element name and
* attributes. For example, the first node in the above example could have
* been generated using
*
* GXml xml;
* xml.append("element type=\"Measurement\"");
*
* Note that the @< and @> symbols are not part of the text string that is
* passed to the append() method.
*
* The insert() method inserts a child node at the specified index in the
* XML root document. The remove() method removes the child node at the
* specified index from the document root. The reserve() method reserves
* space for a specified number of child nodes in the XML document root.
* And the extend() method appends all child nodes that are found in the
* specified argument to the XML document root.
*
* Most of the nodes encountered in a XML document will be @b element
* @b nodes, hence special methods for handling element nodes have been
* implemented. The elements() method returns the number of child elements
* that are present in the XML document root. A variant that takes a string
* argument counts the number of child elements with a given name. The
* element() method allows to access the child elements. There are again
* two flavours, one that simply takes an index to loop over all child
* elements, and another that takes a name and a index to loop over all
* child elements of a given name. For element access, non-const and const
* variants exist.
*
* Finally, the load() and save() methods enable loading and saving a XML
* document from and to disk. The read() and write() method, which do the
* actual job of reading and writing, operate on general Unified Resource
* Locators, so that XML documents can also through other media than flat
* files.
*
* The print() method does not print the full XML document into a string
* but shows a concise summary that reflects the tree structure. For writing
* the document in a string, use the write() method to write in a string URL
* object (GUrlString).
***************************************************************************/
class GXml : public GContainer {
// Friend classes
friend class GXmlNode;
friend class GXmlDocument;
friend class GXmlText;
public:
// Constructors and destructors
GXml(void);
GXml(const GXml& xml);
explicit GXml(const std::string& xml);
virtual ~GXml(void);
// Operators
GXml& operator=(const GXml& xml);
GXmlNode* operator[](const int& index);
const GXmlNode* operator[](const int& index) const;
// Methods
void clear(void);
GXml* clone(void) const;
std::string classname(void) const;
int size(void) const;
bool is_empty(void) const;
GXmlNode* set(const int& index, const GXmlNode& node);
GXmlNode* append(const GXmlNode& node);
GXmlElement* append(const std::string& segment);
GXmlNode* insert(const int& index, const GXmlNode& node);
void remove(const int& index);
void reserve(const int& num);
void extend(const GXmlNode& node);
int elements(void) const;
int elements(const std::string& name) const;
GXmlElement* element(const int& index);
const GXmlElement* element(const int& index) const;
GXmlElement* element(const std::string& name);
const GXmlElement* element(const std::string& name) const;
GXmlElement* element(const std::string& name, const int& index);
const GXmlElement* element(const std::string& name, const int& index) const;
void load(const std::string& filename);
void save(const std::string& filename);
void read(const GUrl& url);
void write(GUrl& url, const int& indent = 0) const;
std::string print(const GChatter& chatter = NORMAL) const;
std::string print(const GChatter& chatter = NORMAL,
const int& indent = 0) const;
protected:
// Protected enumerators
enum MarkupType {
MT_ELEMENT_START,
MT_ELEMENT_END,
MT_ELEMENT_EMPTY,
MT_COMMENT,
MT_DECLARATION,
MT_PROCESSING,
MT_INVALID
};
// Protected methods
void init_members(void);
void copy_members(const GXml& xml);
void free_members(void);
void parse(const GUrl& url);
void process_markup(GXmlNode** current, const std::string& segment);
void process_text(GXmlNode** current, const std::string& segment);
MarkupType get_markuptype(const std::string& segment) const;
// Protected members
GXmlDocument m_root; //!< Root document node
};
/***********************************************************************//**
* @brief Return class name
*
* @return String containing the class name ("GXml").
***************************************************************************/
inline
std::string GXml::classname(void) const
{
return ("GXml");
}
/***********************************************************************//**
* @brief Return number of child nodes
*
* @return Number of child nodes in node.
***************************************************************************/
inline
int GXml::size(void) const
{
return m_root.size();
}
/***********************************************************************//**
* @brief Signals if document has no child nodes
*
* @return True if document has no child nodes.
***************************************************************************/
inline
bool GXml::is_empty(void) const
{
return m_root.is_empty();
}
#endif /* GXML_HPP */