3 #include <boost/lexical_cast.hpp>
4 #include <boost/filesystem.hpp>
5 #include <boost/algorithm/string.hpp>
6 #include <libxml++/libxml++.h>
8 #include "exceptions.h"
12 using namespace boost;
13 using namespace libdcp;
21 XMLNode::XMLNode (xmlpp::Node const * node)
28 XMLNode::node_child (string name)
30 list<xmlpp::Node*> n = node_children (name);
32 boost::throw_exception (XMLError ("duplicate XML tag " + name));
33 } else if (n.empty ()) {
34 boost::throw_exception (XMLError ("missing XML tag " + name + " in " + _node->get_name()));
41 XMLNode::node_children (string name)
43 /* XXX: using find / get_path should work here, but I can't follow
47 xmlpp::Node::NodeList c = _node->get_children ();
50 for (xmlpp::Node::NodeList::iterator i = c.begin (); i != c.end(); ++i) {
51 if ((*i)->get_name() == name) {
56 _taken.push_back (name);
61 XMLNode::string_child (string name)
63 return XMLNode (node_child (name)).content ();
67 XMLNode::optional_string_child (string name)
69 list<xmlpp::Node*> nodes = node_children (name);
70 if (nodes.size() > 2) {
71 boost::throw_exception (XMLError ("duplicate XML tag " + name));
78 return string_child (name);
82 XMLNode::kind_child (string name)
84 return content_kind_from_string (string_child (name));
88 XMLNode::fraction_child (string name)
90 return Fraction (string_child (name));
94 XMLNode::int64_child (string name)
96 string s = string_child (name);
98 return lexical_cast<int64_t> (s);
102 XMLNode::optional_int64_child (string name)
104 list<xmlpp::Node*> nodes = node_children (name);
105 if (nodes.size() > 2) {
106 boost::throw_exception (XMLError ("duplicate XML tag " + name));
109 if (nodes.empty ()) {
113 return int64_child (name);
117 XMLNode::float_child (string name)
119 return lexical_cast<float> (string_child (name));
123 XMLNode::ignore_child (string name)
125 _taken.push_back (name);
129 XMLNode::time_attribute (string name)
131 return Time (string_attribute (name));
135 XMLNode::string_attribute (string name)
137 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
139 boost::throw_exception (XMLError ("missing attribute"));
142 xmlpp::Attribute* a = e->get_attribute (name);
144 boost::throw_exception (XMLError ("missing attribute"));
147 return a->get_value ();
151 XMLNode::optional_string_attribute (string name)
153 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
158 xmlpp::Attribute* a = e->get_attribute (name);
163 return a->get_value ();
167 XMLNode::float_attribute (string name)
169 return lexical_cast<float> (string_attribute (name));
173 XMLNode::int64_attribute (string name)
175 return lexical_cast<int64_t> (string_attribute (name));
179 XMLNode::optional_int64_attribute (string name)
181 string const s = optional_string_attribute (name);
186 return lexical_cast<int64_t> (s);
190 XMLNode::optional_bool_attribute (string name)
192 string const s = optional_string_attribute (name);
194 return optional<bool> ();
197 if (s == "1" || s == "yes") {
198 return optional<bool> (true);
201 return optional<bool> (false);
205 XMLNode::optional_color_attribute (string name)
207 string const s = optional_string_attribute (name);
209 return optional<Color> ();
212 return optional<Color> (Color (s));
218 xmlpp::Node::NodeList c = _node->get_children ();
219 for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) {
220 if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) {
221 boost::throw_exception (XMLError ("unexpected XML node " + (*i)->get_name()));
231 xmlpp::Node::NodeList c = _node->get_children ();
232 for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) {
233 xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (*i);
235 content += v->get_content ();
242 XMLFile::XMLFile (string file, string root_name)
244 if (!filesystem::exists (file)) {
245 boost::throw_exception (FileError ("XML file does not exist", file));
248 _parser = new xmlpp::DomParser;
249 _parser->parse_file (file);
251 boost::throw_exception (XMLError ("could not parse XML"));
254 _node = _parser->get_document()->get_root_node ();
255 if (_node->get_name() != root_name) {
256 boost::throw_exception (XMLError ("unrecognised root node"));