2 Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef LIBCXML_CXML_H
21 #define LIBCXML_CXML_H
28 #include <boost/shared_ptr.hpp>
29 #include <boost/optional.hpp>
30 #include <boost/filesystem.hpp>
31 #include <boost/algorithm/string/erase.hpp>
32 #include <boost/enable_shared_from_this.hpp>
34 /* Hack for OS X compile failure; see https://bugs.launchpad.net/hugin/+bug/910160 */
46 /** @brief An error */
47 class Error : public std::exception
50 /** Construct an Error exception.
51 * @param message Error message.
53 Error (std::string const & message) : _message (message) {}
55 /** Error destructor */
58 /** @return error message. Caller must not free the returned
61 char const * what () const throw () {
62 return _message.c_str ();
71 typedef boost::shared_ptr<cxml::Node> NodePtr;
72 typedef std::list<NodePtr> NodeList;
73 typedef boost::shared_ptr<const cxml::Node> ConstNodePtr;
74 typedef std::list<std::pair<std::string, std::string> > KeyValueList;
76 class Node : public boost::enable_shared_from_this<Node>
80 Node (xmlpp::Node const *);
82 /* A set of methods which look up a child of this node by
83 * its name, and return its contents as some type or other.
85 * If, for example, this object has been created with
86 * a node named "Fred", we might have the following XML:
92 * string_child ("Jim") would return "42"
93 * number_child<int64_t> ("Jim") would return 42.
96 * The methods not marked "optional" will throw an exception
97 * if the child node is not present. The "optional" methods
98 * will return an empty boost::optional<> in that case.
100 * All methods will also throw an exception if there is more
101 * than one of the specified child node.
104 std::string string_child (std::string c) const;
105 boost::optional<std::string> optional_string_child (std::string) const;
107 bool bool_child (std::string) const;
108 boost::optional<bool> optional_bool_child (std::string) const;
111 T number_child (std::string c) const
113 std::string s = string_child (c);
114 boost::erase_all (s, " ");
116 t.imbue (std::locale::classic ());
124 boost::optional<T> optional_number_child (std::string c) const
126 boost::optional<std::string> s = optional_string_child (c);
128 return boost::optional<T> ();
131 std::string t = s.get ();
132 boost::erase_all (t, " ");
134 u.imbue (std::locale::classic ());
142 /* These methods look for an attribute of this node, in the
143 * same way as the child methods do.
146 std::string string_attribute (std::string) const;
147 boost::optional<std::string> optional_string_attribute (std::string) const;
149 bool bool_attribute (std::string) const;
150 boost::optional<bool> optional_bool_attribute (std::string) const;
153 T number_attribute (std::string c) const
155 std::string s = string_attribute (c);
156 boost::erase_all (s, " ");
158 t.imbue (std::locale::classic ());
166 boost::optional<T> optional_number_attribute (std::string c) const
168 boost::optional<std::string> s = optional_string_attribute (c);
170 return boost::optional<T> ();
173 std::string t = s.get ();
174 boost::erase_all (t, " ");
176 u.imbue (std::locale::classic ());
184 /* Access to child nodes */
186 boost::shared_ptr<Node> child (std::string) const;
187 boost::shared_ptr<Node> optional_child (std::string) const;
188 NodeList children () const;
189 NodeList children (std::string) const;
192 /** Add a child node with a given name */
193 NodePtr add_child (std::string name, std::string namespace_prefix = "")
195 NodePtr n (new cxml::Node ());
196 n->set_namespace_prefix (namespace_prefix);
198 _children.push_back (n);
202 void set_namespace_declaration (std::string uri, std::string prefix = "");
204 KeyValueList namespace_declarations () const {
205 return _namespace_declarations;
208 void set_content (std::string c) {
212 /** @return The content of this node */
213 std::string content () const;
215 void set_attribute (std::string name, std::string value);
217 void set_namespace_prefix (std::string p) {
218 _namespace_prefix = p;
221 /** @return namespace prefix of this node */
222 std::string namespace_prefix () const;
223 /** This will mark a child as to be ignored when calling done() */
224 void ignore_child (std::string) const;
225 /** Check whether all children of this Node have been looked up
226 * or passed to ignore_child(). If not, an exception is thrown.
229 /** Set the name of the node.
232 void set_name (std::string n) {
235 /** @return Node name */
236 std::string name () const {
240 /* We use xmlpp for parsing and writing XML out; these
241 methods help with that.
243 void read (xmlpp::Node const *);
244 void write (xmlpp::Node *, std::map<cxml::ConstNodePtr, xmlpp::Node*>* mapping = 0) const;
251 std::string _content;
252 std::string _namespace_prefix;
253 KeyValueList _attributes;
254 KeyValueList _namespace_declarations;
255 mutable std::list<std::string> _taken;
258 cxml::NodePtr read_file (boost::filesystem::path);
259 cxml::NodePtr read_stream (std::istream &);
260 cxml::NodePtr read_string (std::string);
262 void write_to_xmlpp_document (cxml::ConstNodePtr, xmlpp::Document &, std::map<cxml::ConstNodePtr, xmlpp::Node*>* mapping = 0);
263 void write_to_file (cxml::ConstNodePtr, boost::filesystem::path);
264 void write_to_file_formatted (cxml::ConstNodePtr, boost::filesystem::path);
265 void write_to_stream_formatted (cxml::ConstNodePtr, std::ostream& stream);
266 std::string write_to_string (cxml::ConstNodePtr);
267 std::string write_to_string_formatted (cxml::ConstNodePtr);