3 #include <boost/lexical_cast.hpp>
4 #include <boost/filesystem.hpp>
5 #include <boost/algorithm/string.hpp>
6 #include <libxml++/libxml++.h>
10 using namespace boost;
18 cxml::Node::Node (xmlpp::Node const * node)
25 cxml::Node::name () const
28 return _node->get_name ();
31 shared_ptr<cxml::Node>
32 cxml::Node::node_child (string name) const
34 list<shared_ptr<cxml::Node> > n = node_children (name);
36 throw cxml::Error ("duplicate XML tag " + name);
37 } else if (n.empty ()) {
38 throw cxml::Error ("missing XML tag " + name + " in " + _node->get_name());
44 shared_ptr<cxml::Node>
45 cxml::Node::optional_node_child (string name) const
47 list<shared_ptr<cxml::Node> > n = node_children (name);
49 throw cxml::Error ("duplicate XML tag " + name);
50 } else if (n.empty ()) {
51 return shared_ptr<cxml::Node> ();
57 list<shared_ptr<cxml::Node> >
58 cxml::Node::node_children (string name) const
60 /* XXX: using find / get_path should work here, but I can't follow
64 xmlpp::Node::NodeList c = _node->get_children ();
66 list<shared_ptr<cxml::Node> > n;
67 for (xmlpp::Node::NodeList::iterator i = c.begin (); i != c.end(); ++i) {
68 if ((*i)->get_name() == name) {
69 n.push_back (shared_ptr<Node> (new Node (*i)));
73 _taken.push_back (name);
78 cxml::Node::string_child (string c) const
80 return node_child(c)->content ();
84 cxml::Node::optional_string_child (string c) const
86 list<shared_ptr<Node> > nodes = node_children (c);
87 if (nodes.size() > 1) {
88 throw cxml::Error ("duplicate XML tag " + c);
92 return optional<string> ();
95 return nodes.front()->content();
99 cxml::Node::bool_child (string c) const
101 string const s = string_child (c);
102 return (s == "1" || s == "yes");
106 cxml::Node::optional_bool_child (string c) const
108 optional<string> s = optional_string_child (c);
110 return optional<bool> ();
113 return (s.get() == "1" || s.get() == "yes");
117 cxml::Node::ignore_child (string name) const
119 _taken.push_back (name);
123 cxml::Node::string_attribute (string name) const
125 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
127 throw cxml::Error ("missing attribute");
130 xmlpp::Attribute* a = e->get_attribute (name);
132 throw cxml::Error ("missing attribute");
135 return a->get_value ();
139 cxml::Node::optional_string_attribute (string name) const
141 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
143 return optional<string> ();
146 xmlpp::Attribute* a = e->get_attribute (name);
148 return optional<string> ();
151 return string (a->get_value ());
155 cxml::Node::bool_attribute (string name) const
157 string const s = string_attribute (name);
158 return (s == "1" || s == "yes");
162 cxml::Node::optional_bool_attribute (string name) const
164 optional<string> s = optional_string_attribute (name);
166 return optional<bool> ();
169 return (s.get() == "1" || s.get() == "yes");
173 cxml::Node::done () const
175 xmlpp::Node::NodeList c = _node->get_children ();
176 for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) {
177 if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) {
178 throw cxml::Error ("unexpected XML node " + (*i)->get_name());
184 cxml::Node::content () const
188 xmlpp::Node::NodeList c = _node->get_children ();
189 for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
190 xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i);
192 content += v->get_content ();
199 cxml::File::File (string file, string root_name)
201 if (!filesystem::exists (file)) {
202 throw cxml::Error ("XML file does not exist");
205 _parser = new xmlpp::DomParser;
206 _parser->parse_file (file);
208 throw cxml::Error ("could not parse XML");
211 _node = _parser->get_document()->get_root_node ();
212 if (_node->get_name() != root_name) {
213 throw cxml::Error ("unrecognised root node");