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::xml_node (string name)
30 list<xmlpp::Node*> n = xml_nodes (name);
32 throw XMLError ("duplicate XML tag " + name);
33 } else if (n.empty ()) {
34 throw XMLError ("missing XML tag " + name);
41 XMLNode::xml_nodes (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_node (string name)
63 return XMLNode (xml_node (name)).content ();
67 XMLNode::optional_string_node (string name)
69 list<xmlpp::Node*> nodes = xml_nodes (name);
70 if (nodes.size() > 2) {
71 throw XMLError ("duplicate XML tag " + name);
78 return string_node (name);
82 XMLNode::kind_node (string name)
84 return content_kind_from_string (string_node (name));
88 XMLNode::fraction_node (string name)
90 return Fraction (string_node (name));
94 XMLNode::int64_node (string name)
96 return lexical_cast<int64_t> (string_node (name));
100 XMLNode::optional_int64_node (string name)
102 list<xmlpp::Node*> nodes = xml_nodes (name);
103 if (nodes.size() > 2) {
104 throw XMLError ("duplicate XML tag " + name);
107 if (nodes.empty ()) {
111 return int64_node (name);
115 XMLNode::float_node (string name)
117 return lexical_cast<float> (string_node (name));
121 XMLNode::ignore_node (string name)
123 _taken.push_back (name);
127 XMLNode::time_attribute (string name)
129 string const t = string_attribute (name);
132 boost::split (b, t, is_any_of (":"));
133 assert (b.size() == 4);
135 return Time (lexical_cast<int> (b[0]), lexical_cast<int> (b[1]), lexical_cast<int> (b[2]), lexical_cast<int> (b[3]));
139 XMLNode::string_attribute (string name)
141 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
143 throw XMLError ("missing attribute");
146 xmlpp::Attribute* a = e->get_attribute (name);
148 throw XMLError ("missing attribute");
151 return a->get_value ();
155 XMLNode::optional_string_attribute (string name)
157 xmlpp::Element const * e = dynamic_cast<const xmlpp::Element *> (_node);
162 xmlpp::Attribute* a = e->get_attribute (name);
167 return a->get_value ();
171 XMLNode::float_attribute (string name)
173 return lexical_cast<float> (string_attribute (name));
177 XMLNode::int64_attribute (string name)
179 return lexical_cast<int64_t> (string_attribute (name));
183 XMLNode::optional_int64_attribute (string name)
185 string const s = optional_string_attribute (name);
190 return lexical_cast<int64_t> (s);
194 XMLNode::optional_bool_attribute (string name)
196 string const s = optional_string_attribute (name);
198 return optional<bool> ();
201 if (s == "1" || s == "yes") {
202 return optional<bool> (true);
205 return optional<bool> (false);
209 XMLNode::optional_color_attribute (string name)
211 string const s = optional_string_attribute (name);
213 return optional<Color> ();
216 return optional<Color> (Color (s));
222 xmlpp::Node::NodeList c = _node->get_children ();
223 for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) {
224 if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) {
225 throw XMLError ("unexpected XML node " + (*i)->get_name());
233 xmlpp::Node::NodeList c = _node->get_children ();
236 throw XMLError ("unexpected content in XML node");
243 xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (c.front());
245 throw XMLError ("missing content in XML node");
248 return v->get_content ();
251 XMLFile::XMLFile (string file, string root_name)
253 if (!filesystem::exists (file)) {
254 throw FileError ("XML file does not exist", file);
257 _parser = new xmlpp::DomParser;
258 _parser->parse_file (file);
260 throw XMLError ("could not parse XML");
263 _node = _parser->get_document()->get_root_node ();
264 if (_node->get_name() != root_name) {
265 throw XMLError ("unrecognised root node");