X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fcxml.cc;h=667da5515851b6a8ea8fd109f92cee71457fbc15;hb=c9a79405c38ef596a821a4db9955a33f4437b9d3;hp=2ca46ed46971f97d2964f0065d22856cb2219b25;hpb=088f3cc5d2f200c27d76c23c480153f1b93f8230;p=libcxml.git diff --git a/src/cxml.cc b/src/cxml.cc index 2ca46ed..667da55 100644 --- a/src/cxml.cc +++ b/src/cxml.cc @@ -1,13 +1,33 @@ -#include -#include -#include +/* + Copyright (C) 2012-2016 Carl Hetherington + + This file is part of libcxml. + + libcxml is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + libcxml is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libcxml. If not, see . + +*/ + +#include "cxml.h" +#include #include #include -#include -#include "cxml.h" +#include -using namespace std; -using namespace boost; +using std::string; +using std::list; +using boost::shared_ptr; +using boost::optional; cxml::Node::Node () : _node (0) @@ -24,7 +44,9 @@ cxml::Node::Node (xmlpp::Node* node) string cxml::Node::name () const { - assert (_node); + if (!_node) { + throw Error ("No node to read name from"); + } return _node->get_name (); } @@ -37,7 +59,7 @@ cxml::Node::node_child (string name) const } else if (n.empty ()) { throw cxml::Error ("missing XML tag " + name + " in " + _node->get_name()); } - + return n.front (); } @@ -50,10 +72,26 @@ cxml::Node::optional_node_child (string name) const } else if (n.empty ()) { return shared_ptr (); } - + return n.front (); } +list > +cxml::Node::node_children () const +{ + if (!_node) { + throw Error ("No node to read children from"); + } + xmlpp::Node::NodeList c = _node->get_children (); + + list > n; + for (xmlpp::Node::NodeList::iterator i = c.begin (); i != c.end(); ++i) { + n.push_back (shared_ptr (new Node (*i))); + } + + return n; +} + list > cxml::Node::node_children (string name) const { @@ -62,14 +100,14 @@ cxml::Node::node_children (string name) const */ 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 (shared_ptr (new Node (*i))); } } - + _taken.push_back (name); return n; } @@ -99,7 +137,7 @@ bool cxml::Node::bool_child (string c) const { string const s = string_child (c); - return (s == "1" || s == "yes"); + return (s == "1" || s == "yes" || s == "True"); } optional @@ -109,8 +147,8 @@ cxml::Node::optional_bool_child (string c) const if (!s) { return optional (); } - - return (s.get() == "1" || s.get() == "yes"); + + return (s.get() == "1" || s.get() == "yes" || s.get() == "True"); } void @@ -124,12 +162,12 @@ cxml::Node::string_attribute (string name) const { xmlpp::Element const * e = dynamic_cast (_node); if (!e) { - throw cxml::Error ("missing attribute"); + throw cxml::Error ("missing attribute " + name); } - + xmlpp::Attribute* a = e->get_attribute (name); if (!a) { - throw cxml::Error ("missing attribute"); + throw cxml::Error ("missing attribute " + name); } return a->get_value (); @@ -142,7 +180,7 @@ cxml::Node::optional_string_attribute (string name) const if (!e) { return optional (); } - + xmlpp::Attribute* a = e->get_attribute (name); if (!a) { return optional (); @@ -184,11 +222,11 @@ string cxml::Node::content () const { string content; - + xmlpp::Node::NodeList c = _node->get_children (); for (xmlpp::Node::NodeList::const_iterator i = c.begin(); i != c.end(); ++i) { xmlpp::ContentNode const * v = dynamic_cast (*i); - if (v) { + if (v && dynamic_cast(v)) { content += v->get_content (); } } @@ -214,26 +252,38 @@ cxml::Document::Document (string root_name) _parser = new xmlpp::DomParser; } +cxml::Document::Document (string root_name, boost::filesystem::path file) + : _root_name (root_name) +{ + _parser = new xmlpp::DomParser (); + read_file (file); +} + +cxml::Document::Document () +{ + _parser = new xmlpp::DomParser (); +} + cxml::Document::~Document () { delete _parser; } void -cxml::Document::read_file (filesystem::path file) +cxml::Document::read_file (boost::filesystem::path file) { - if (!filesystem::exists (file)) { - throw cxml::Error ("XML file does not exist"); + if (!boost::filesystem::exists (file)) { + throw cxml::Error ("XML file " + file.string() + " does not exist"); } - + _parser->parse_file (file.string ()); take_root_node (); } void -cxml::Document::read_stream (istream& stream) +cxml::Document::read_string (string s) { - _parser->parse_stream (stream); + _parser->parse_memory (s); take_root_node (); } @@ -245,8 +295,169 @@ cxml::Document::take_root_node () } _node = _parser->get_document()->get_root_node (); - if (_node->get_name() != _root_name) { - throw cxml::Error ("unrecognised root node"); + if (!_root_name.empty() && _node->get_name() != _root_name) { + throw cxml::Error ("unrecognised root node " + _node->get_name() + " (expecting " + _root_name + ")"); + } else if (_root_name.empty ()) { + _root_name = _node->get_name (); } } +static +string +make_local (string v) +{ + struct lconv* lc = localeconv (); + boost::algorithm::replace_all (v, ".", lc->decimal_point); + /* We hope it's ok not to add in thousands separators here */ + return v; +} + +template +P +locale_convert (Q x) +{ + /* We can't write a generic version of locale_convert; all required + versions must be specialised. + */ + BOOST_STATIC_ASSERT (sizeof(Q) == 0); +} + +template<> +int +locale_convert (string x) +{ + int y = 0; + sscanf (x.c_str(), "%d", &y); + return y; +} + +template<> +unsigned int +locale_convert (string x) +{ + unsigned int y = 0; + sscanf (x.c_str(), "%u", &y); + return y; +} + +template<> +long int +locale_convert (string x) +{ + long int y = 0; + sscanf (x.c_str(), "%ld", &y); + return y; +} + +template<> +long unsigned int +locale_convert (string x) +{ + long unsigned int y = 0; +#ifdef LIBCXML_WINDOWS + __mingw_sscanf (x.c_str(), "%lud", &y); +#else + sscanf (x.c_str(), "%lud", &y); +#endif + return y; +} + +template<> +long long +locale_convert (string x) +{ + long long y = 0; +#ifdef LIBCXML_WINDOWS + __mingw_sscanf (x.c_str(), "%lld", &y); +#else + sscanf (x.c_str(), "%lld", &y); +#endif + return y; +} + +template<> +long long unsigned +locale_convert (string x) +{ + long long unsigned y = 0; +#ifdef LIBCXML_WINDOWS + __mingw_sscanf (x.c_str(), "%llud", &y); +#else + sscanf (x.c_str(), "%llud", &y); +#endif + return y; +} + +template<> +float +locale_convert (string x) +{ + float y = 0; + sscanf (x.c_str(), "%f", &y); + return y; +} + +template <> +double +locale_convert (string x) +{ + double y = 0; + sscanf (x.c_str(), "%lf", &y); + return y; +} + +template <> +int +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +unsigned int +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +long int +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +long unsigned int +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +long long +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +long long unsigned +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +float +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +} + +template <> +double +cxml::raw_convert (string v) +{ + return locale_convert (make_local(v)); +}