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);
146 xmlpp::Attribute* a = e->get_attribute (name);
151 return a->get_value ();
155 XMLNode::float_attribute (string name)
157 return lexical_cast<float> (string_attribute (name));
161 XMLNode::int64_attribute (string name)
163 return lexical_cast<int64_t> (string_attribute (name));
167 XMLNode::optional_int64_attribute (string name)
169 string const s = string_attribute (name);
174 return lexical_cast<int64_t> (s);
178 XMLNode::optional_bool_attribute (string name)
180 string const s = string_attribute (name);
182 return optional<bool> ();
185 if (s == "1" || s == "yes") {
186 return optional<bool> (true);
189 return optional<bool> (false);
195 xmlpp::Node::NodeList c = _node->get_children ();
196 for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) {
197 if (dynamic_cast<xmlpp::Element *> (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) {
198 throw XMLError ("unexpected XML node " + (*i)->get_name());
206 xmlpp::Node::NodeList c = _node->get_children ();
209 throw XMLError ("unexpected content in XML node");
216 xmlpp::ContentNode const * v = dynamic_cast<xmlpp::ContentNode const *> (c.front());
218 throw XMLError ("missing content in XML node");
221 return v->get_content ();
224 XMLFile::XMLFile (string file, string root_name)
226 if (!filesystem::exists (file)) {
227 throw FileError ("XML file does not exist", file);
230 _parser = new xmlpp::DomParser;
231 _parser->parse_file (file);
233 throw XMLError ("could not parse XML");
236 _node = _parser->get_document()->get_root_node ();
237 if (_node->get_name() != root_name) {
238 throw XMLError ("unrecognised root node");