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* 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 xmlpp::NodeSet c = _node->find (name);
62 list<shared_ptr<cxml::Node> > n;
63 for (xmlpp::NodeSet::iterator i = c.begin (); i != c.end(); ++i) {
64 n.push_back (shared_ptr<Node> (new Node (*i)));
67 _taken.push_back (name);
72 cxml::Node::string_child (string c) const
74 return node_child(c)->content ();
78 cxml::Node::optional_string_child (string c) const
80 list<shared_ptr<Node> > nodes = node_children (c);
81 if (nodes.size() > 1) {
82 throw cxml::Error ("duplicate XML tag " + c);
86 return optional<string> ();
89 return nodes.front()->content();
93 cxml::Node::bool_child (string c) const
95 string const s = string_child (c);
96 return (s == "1" || s == "yes");
100 cxml::Node::optional_bool_child (string c) const
102 optional<string> s = optional_string_child (c);
104 return optional<bool> ();
107 return (s.get() == "1" || s.get() == "yes");
111 cxml::Node::ignore_child (string name) const
113 _taken.push_back (name);
117 cxml::Node::string_attribute (string name) const
119 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
121 throw cxml::Error ("missing attribute");
124 xmlpp::Attribute* a = e->get_attribute (name);
126 throw cxml::Error ("missing attribute");
129 return a->get_value ();
133 cxml::Node::optional_string_attribute (string name) const
135 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
137 return optional<string> ();
140 xmlpp::Attribute* a = e->get_attribute (name);
142 return optional<string> ();
145 return string (a->get_value ());
149 cxml::Node::bool_attribute (string name) const
151 string const s = string_attribute (name);
152 return (s == "1" || s == "yes");
156 cxml::Node::optional_bool_attribute (string name) const
158 optional<string> s = optional_string_attribute (name);
160 return optional<bool> ();
163 return (s.get() == "1" || s.get() == "yes");
167 cxml::Node::done () const
169 xmlpp::Node::NodeList c = _node->get_children ();
170 for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) {
171 if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) {
172 throw cxml::Error ("unexpected XML node " + (*i)->get_name());
178 cxml::Node::content () const
182 xmlpp::Node::NodeList c = _node->get_children ();
183 for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
184 xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i);
186 content += v->get_content ();
194 cxml::Node::namespace_uri () const
196 return _node->get_namespace_uri ();
200 cxml::Node::namespace_prefix () const
202 return _node->get_namespace_prefix ();
205 cxml::Document::Document (string root_name)
206 : _root_name (root_name)
208 _parser = new xmlpp::DomParser;
211 cxml::Document::~Document ()
217 cxml::Document::read_file (filesystem::path file)
219 if (!filesystem::exists (file)) {
220 throw cxml::Error ("XML file does not exist");
223 _parser->parse_file (file.string ());
228 cxml::Document::read_stream (istream& stream)
230 _parser->parse_stream (stream);
235 cxml::Document::take_root_node ()
238 throw cxml::Error ("could not parse XML");
241 _node = _parser->get_document()->get_root_node ();
242 if (_node->get_name() != _root_name) {
243 throw cxml::Error ("unrecognised root node");