#include #include #include #include #include #include #include "xml.h" #include "exceptions.h" #include "util.h" using namespace std; using namespace boost; using namespace libdcp; XMLNode::XMLNode () : _node (0) { } XMLNode::XMLNode (xmlpp::Node const * node) : _node (node) { } xmlpp::Node * XMLNode::xml_node (string name) { list n = xml_nodes (name); if (n.size() > 1) { throw XMLError ("duplicate XML tag " + name); } else if (n.empty ()) { throw XMLError ("missing XML tag " + name + " in " + _node->get_name()); } return n.front (); } list XMLNode::xml_nodes (string name) { /* XXX: using find / get_path should work here, but I can't follow how get_path works. */ xmlpp::Node::NodeList c = _node->get_children (); list n; for (xmlpp::Node::NodeList::iterator i = c.begin (); i != c.end(); ++i) { if ((*i)->get_name() == name) { n.push_back (*i); } } _taken.push_back (name); return n; } string XMLNode::string_node (string name) { return XMLNode (xml_node (name)).content (); } string XMLNode::optional_string_node (string name) { list nodes = xml_nodes (name); if (nodes.size() > 2) { throw XMLError ("duplicate XML tag " + name); } if (nodes.empty ()) { return ""; } return string_node (name); } ContentKind XMLNode::kind_node (string name) { return content_kind_from_string (string_node (name)); } Fraction XMLNode::fraction_node (string name) { return Fraction (string_node (name)); } int64_t XMLNode::int64_node (string name) { return lexical_cast (string_node (name)); } int64_t XMLNode::optional_int64_node (string name) { list nodes = xml_nodes (name); if (nodes.size() > 2) { throw XMLError ("duplicate XML tag " + name); } if (nodes.empty ()) { return 0; } return int64_node (name); } float XMLNode::float_node (string name) { return lexical_cast (string_node (name)); } void XMLNode::ignore_node (string name) { _taken.push_back (name); } Time XMLNode::time_attribute (string name) { return Time (string_attribute (name)); } string XMLNode::string_attribute (string name) { xmlpp::Element const * e = dynamic_cast (_node); if (!e) { throw XMLError ("missing attribute"); } xmlpp::Attribute* a = e->get_attribute (name); if (!a) { throw XMLError ("missing attribute"); } return a->get_value (); } string XMLNode::optional_string_attribute (string name) { xmlpp::Element const * e = dynamic_cast (_node); if (!e) { return ""; } xmlpp::Attribute* a = e->get_attribute (name); if (!a) { return ""; } return a->get_value (); } float XMLNode::float_attribute (string name) { return lexical_cast (string_attribute (name)); } int64_t XMLNode::int64_attribute (string name) { return lexical_cast (string_attribute (name)); } int64_t XMLNode::optional_int64_attribute (string name) { string const s = optional_string_attribute (name); if (s.empty ()) { return 0; } return lexical_cast (s); } optional XMLNode::optional_bool_attribute (string name) { string const s = optional_string_attribute (name); if (s.empty ()) { return optional (); } if (s == "1" || s == "yes") { return optional (true); } return optional (false); } optional XMLNode::optional_color_attribute (string name) { string const s = optional_string_attribute (name); if (s.empty ()) { return optional (); } return optional (Color (s)); } void XMLNode::done () { xmlpp::Node::NodeList c = _node->get_children (); for (xmlpp::Node::NodeList::iterator i = c.begin(); i != c.end(); ++i) { if (dynamic_cast (*i) && find (_taken.begin(), _taken.end(), (*i)->get_name()) == _taken.end ()) { throw XMLError ("unexpected XML node " + (*i)->get_name()); } } } string XMLNode::content () { xmlpp::Node::NodeList c = _node->get_children (); if (c.size() > 1) { throw XMLError ("unexpected content in XML node"); } if (c.empty ()) { return ""; } xmlpp::ContentNode const * v = dynamic_cast (c.front()); if (!v) { throw XMLError ("missing content in XML node"); } return v->get_content (); } XMLFile::XMLFile (string file, string root_name) { if (!filesystem::exists (file)) { throw FileError ("XML file does not exist", file); } _parser = new xmlpp::DomParser; _parser->parse_file (file); if (!_parser) { throw XMLError ("could not parse XML"); } _node = _parser->get_document()->get_root_node (); if (_node->get_name() != root_name) { throw XMLError ("unrecognised root node"); } } XMLFile::~XMLFile () { delete _parser; }