2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of libcxml.
6 libcxml is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 libcxml is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with libcxml. If not, see <http://www.gnu.org/licenses/>.
21 #ifndef LIBCXML_CXML_H
22 #define LIBCXML_CXML_H
24 #include <boost/optional.hpp>
25 #include <boost/filesystem.hpp>
26 #include <boost/algorithm/string/erase.hpp>
32 /* Hack for OS X compile failure; see https://bugs.launchpad.net/hugin/+bug/910160 */
45 /** @brief An error */
46 class Error : public std::exception
49 /** Construct an Error exception.
50 * @param message Error message.
52 Error (std::string const & message) : _message (message) {}
54 /** Error destructor */
57 /** @return error message. Caller must not free the returned
60 char const * what () const noexcept override {
61 return _message.c_str ();
69 /** A sort-of version of boost::lexical_cast that does uses the "C"
70 * locale (i.e. no thousands separators and a . for the decimal separator).
72 template <typename P, typename Q>
76 /* We can't write a generic version of raw_convert; all required
77 versions must be specialised.
79 BOOST_STATIC_ASSERT (sizeof(Q) == 0);
84 raw_convert (std::string v);
88 raw_convert (std::string v);
92 raw_convert (std::string v);
96 raw_convert (std::string v);
100 raw_convert (std::string v);
104 raw_convert (std::string v);
108 raw_convert (std::string v);
112 raw_convert (std::string v);
114 /** @brief A wrapper for a xmlpp::Node which simplifies parsing */
120 /** Construct a Node from an xmlpp::Node. This class will
121 * not destroy the xmlpp::Node.
122 * @param node xmlpp::Node.
124 Node (xmlpp::Node* node);
126 std::string name () const;
128 /* A set of methods which look up a child of this node by
129 * its name, and return its contents as some type or other.
131 * If, for example, this object has been created with
132 * a node named "Fred", we might have the following XML:
138 * string_child ("Jim") would return "42"
139 * number_child<int64_t> ("Jim") would return 42.
142 * The methods not marked "optional" will throw an exception
143 * if the child node is not present. The "optional" methods
144 * will return an empty boost::optional<> in that case.
146 * All methods will also throw an exception if there is more
147 * than one of the specified child node.
150 std::string string_child (std::string c) const;
151 boost::optional<std::string> optional_string_child (std::string) const;
153 bool bool_child (std::string) const;
154 boost::optional<bool> optional_bool_child (std::string) const;
157 T number_child (std::string c) const
159 auto s = string_child (c);
160 boost::erase_all (s, " ");
161 return raw_convert<T> (s);
165 boost::optional<T> optional_number_child (std::string c) const
167 auto s = optional_string_child (c);
173 boost::erase_all (t, " ");
174 return raw_convert<T> (t);
177 /** This will mark a child as to be ignored when calling done() */
178 void ignore_child (std::string) const;
180 /** Check whether all children of this Node have been looked up
181 * or passed to ignore_child(). If not, an exception is thrown.
185 /* These methods look for an attribute of this node, in the
186 * same way as the child methods do.
189 std::string string_attribute (std::string) const;
190 boost::optional<std::string> optional_string_attribute (std::string) const;
192 bool bool_attribute (std::string) const;
193 boost::optional<bool> optional_bool_attribute (std::string) const;
196 T number_attribute (std::string c) const
198 std::string s = string_attribute (c);
199 boost::erase_all (s, " ");
200 return raw_convert<T> (s);
204 boost::optional<T> optional_number_attribute (std::string c) const
206 auto s = optional_string_attribute (c);
208 return boost::optional<T> ();
212 boost::erase_all (t, " ");
213 return raw_convert<T> (t);
216 /** @return The text content of this node (excluding comments or CDATA) */
217 std::string content () const;
219 /** @return namespace URI of this node */
220 std::string namespace_uri () const;
222 /** @return namespace prefix of this node */
223 std::string namespace_prefix () const;
225 std::shared_ptr<Node> node_child (std::string) const;
226 std::shared_ptr<Node> optional_node_child (std::string) const;
228 std::vector<std::shared_ptr<Node>> node_children () const;
229 std::vector<std::shared_ptr<Node>> node_children (std::string) const;
231 xmlpp::Node* node () const {
235 bool is_text() const;
241 mutable std::vector<std::string> _taken;
244 typedef std::shared_ptr<cxml::Node> NodePtr;
245 typedef std::shared_ptr<const cxml::Node> ConstNodePtr;
247 class Document : public Node
251 explicit Document(std::string root_name);
252 Document (std::string root_name, boost::filesystem::path);
254 Document (Document const&) = delete;
255 Document& operator= (Document const&) = delete;
257 virtual ~Document ();
259 void read_file (boost::filesystem::path);
260 void read_string (std::string);
262 std::string root_name () const {
267 void take_root_node ();
269 xmlpp::DomParser* _parser;
270 std::string _root_name;
274 xmlpp::Element* add_child(xmlpp::Element* parent, std::string const& name);
275 void add_text_child(xmlpp::Element* parent, std::string const& name, std::string const& text);