Convert first function to new XML structure.
This commit is contained in:
parent
481271cb76
commit
191d0f907a
4 changed files with 203 additions and 57 deletions
|
@ -23,16 +23,14 @@
|
||||||
#ifndef MAPNIK_LIBXML2_LOADER_HPP
|
#ifndef MAPNIK_LIBXML2_LOADER_HPP
|
||||||
#define MAPNIK_LIBXML2_LOADER_HPP
|
#define MAPNIK_LIBXML2_LOADER_HPP
|
||||||
|
|
||||||
// boost
|
|
||||||
#include <boost/property_tree/ptree.hpp>
|
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
void read_xml2( std::string const & filename, boost::property_tree::ptree & pt);
|
class xml_node;
|
||||||
void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path="");
|
void read_xml2( std::string const & filename, xml_node &node);
|
||||||
|
void read_xml2_string( std::string const & str, xml_node &node, std::string const & base_path="");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MAPNIK_LIBXML2_LOADER_HPP
|
#endif // MAPNIK_LIBXML2_LOADER_HPP
|
||||||
|
|
|
@ -23,13 +23,19 @@
|
||||||
#ifndef MAPNIK_XML_TREE_H
|
#ifndef MAPNIK_XML_TREE_H
|
||||||
#define MAPNIK_XML_TREE_H
|
#define MAPNIK_XML_TREE_H
|
||||||
|
|
||||||
|
//boost
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
//stl
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
class xml_tree;
|
class xml_tree;
|
||||||
|
class color;
|
||||||
|
|
||||||
class xml_attribute
|
class xml_attribute
|
||||||
{
|
{
|
||||||
|
@ -38,6 +44,19 @@ public:
|
||||||
bool processed;
|
bool processed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class node_not_found: public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
node_not_found(std::string node_name) : node_name_(node_name) {}
|
||||||
|
virtual const char* what() const throw()
|
||||||
|
{
|
||||||
|
return ("Node "+node_name_+ "not found").c_str();
|
||||||
|
}
|
||||||
|
~node_not_found() throw ();
|
||||||
|
private:
|
||||||
|
std::string node_name_;
|
||||||
|
};
|
||||||
|
|
||||||
class xml_node
|
class xml_node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -49,6 +68,15 @@ public:
|
||||||
xml_node &add_child(std::string name, unsigned line=0, bool text_node = false);
|
xml_node &add_child(std::string name, unsigned line=0, bool text_node = false);
|
||||||
void add_attribute(std::string name, std::string value);
|
void add_attribute(std::string name, std::string value);
|
||||||
void set_processed(bool processed);
|
void set_processed(bool processed);
|
||||||
|
|
||||||
|
xml_node & get_child(std::string name);
|
||||||
|
xml_node const& get_child(std::string name) const;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
boost::optional<T> get_opt_attr(std::string const& name) const;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get_attr(std::string const& name, T const& default_value) const;
|
||||||
private:
|
private:
|
||||||
xml_tree &tree_;
|
xml_tree &tree_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
@ -66,7 +94,7 @@ public:
|
||||||
xml_tree();
|
xml_tree();
|
||||||
void set_filename(std::string fn);
|
void set_filename(std::string fn);
|
||||||
std::string filename() const;
|
std::string filename() const;
|
||||||
xml_node &node();
|
xml_node &root();
|
||||||
private:
|
private:
|
||||||
xml_node node_;
|
xml_node node_;
|
||||||
std::string file_;
|
std::string file_;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/load_map.hpp>
|
#include <mapnik/load_map.hpp>
|
||||||
|
|
||||||
|
#include <mapnik/xml_tree.hpp>
|
||||||
#include <mapnik/version.hpp>
|
#include <mapnik/version.hpp>
|
||||||
#include <mapnik/image_reader.hpp>
|
#include <mapnik/image_reader.hpp>
|
||||||
#include <mapnik/color.hpp>
|
#include <mapnik/color.hpp>
|
||||||
|
@ -94,7 +95,7 @@ public:
|
||||||
expr_grammar_(tr_)
|
expr_grammar_(tr_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void parse_map(Map & map, ptree const & sty, std::string const& base_path="");
|
void parse_map(Map & map, xml_node const& sty, std::string const& base_path="");
|
||||||
private:
|
private:
|
||||||
void parse_map_include( Map & map, ptree const & include);
|
void parse_map_include( Map & map, ptree const & include);
|
||||||
void parse_style(Map & map, ptree const & sty);
|
void parse_style(Map & map, ptree const & sty);
|
||||||
|
@ -166,9 +167,10 @@ void remove_empty_text_nodes(ptree &pt)
|
||||||
//#include <mapnik/internal/dump_xml.hpp>
|
//#include <mapnik/internal/dump_xml.hpp>
|
||||||
void load_map(Map & map, std::string const& filename, bool strict)
|
void load_map(Map & map, std::string const& filename, bool strict)
|
||||||
{
|
{
|
||||||
ptree pt;
|
xml_tree tree;
|
||||||
|
tree.set_filename(filename);
|
||||||
#ifdef HAVE_LIBXML2
|
#ifdef HAVE_LIBXML2
|
||||||
read_xml2(filename, pt);
|
read_xml2(filename, tree.root());
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -180,18 +182,18 @@ void load_map(Map & map, std::string const& filename, bool strict)
|
||||||
throw config_error( ex.what() );
|
throw config_error( ex.what() );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
map_parser parser( strict, filename);
|
map_parser parser(strict, filename);
|
||||||
parser.parse_map(map, pt);
|
// parser.parse_map(map, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_map_string(Map & map, std::string const& str, bool strict, std::string const& base_path)
|
void load_map_string(Map & map, std::string const& str, bool strict, std::string const& base_path)
|
||||||
{
|
{
|
||||||
ptree pt;
|
xml_tree tree;
|
||||||
#ifdef HAVE_LIBXML2
|
#ifdef HAVE_LIBXML2
|
||||||
if (!base_path.empty())
|
if (!base_path.empty())
|
||||||
read_xml2_string(str, pt, base_path); // accept base_path passed into function
|
read_xml2_string(str, tree.root(), base_path); // accept base_path passed into function
|
||||||
else
|
else
|
||||||
read_xml2_string(str, pt, map.base_path()); // default to map base_path
|
read_xml2_string(str, tree.root(), map.base_path()); // default to map base_path
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -206,8 +208,8 @@ void load_map_string(Map & map, std::string const& str, bool strict, std::string
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
map_parser parser( strict, base_path);
|
map_parser parser(strict, base_path);
|
||||||
parser.parse_map(map, pt, base_path);
|
// parser.parse_map(map, tree.root(), base_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
expression_ptr map_parser::parse_expr(std::string const& str)
|
expression_ptr map_parser::parse_expr(std::string const& str)
|
||||||
|
@ -244,44 +246,31 @@ boost::optional<color> map_parser::get_opt_color_attr(boost::property_tree::ptre
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base_path )
|
void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& base_path)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ptree const & map_node = pt.get_child("Map");
|
xml_node const& map_node = pt.get_child("Map");
|
||||||
|
|
||||||
std::ostringstream s("");
|
|
||||||
s << "background-color,"
|
|
||||||
<< "background-image,"
|
|
||||||
<< "srs,"
|
|
||||||
<< "buffer-size,"
|
|
||||||
<< "paths-from-xml,"
|
|
||||||
<< "minimum-version,"
|
|
||||||
<< "font-directory,"
|
|
||||||
<< "maximum-extent,"
|
|
||||||
<< "base";
|
|
||||||
ensure_attrs(map_node, "Map", s.str());
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parameters extra_attr;
|
parameters extra_attr;
|
||||||
|
|
||||||
// Check if relative paths should be interpreted as relative to/from XML location
|
// Check if relative paths should be interpreted as relative to/from XML location
|
||||||
// Default is true, and map_parser::ensure_relative_to_xml will be called to modify path
|
// Default is true, and map_parser::ensure_relative_to_xml will be called to modify path
|
||||||
optional<boolean> paths_from_xml = get_opt_attr<boolean>(map_node, "paths-from-xml");
|
optional<boolean> paths_from_xml = map_node.get_opt_attr<boolean>("paths-from-xml");
|
||||||
if (paths_from_xml)
|
if (paths_from_xml)
|
||||||
{
|
{
|
||||||
relative_to_xml_ = *paths_from_xml;
|
relative_to_xml_ = *paths_from_xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> base_path_from_xml = get_opt_attr<std::string>(map_node, "base");
|
optional<std::string> base_path_from_xml = map_node.get_opt_attr<std::string>("base");
|
||||||
if (!base_path.empty())
|
if (!base_path.empty())
|
||||||
{
|
{
|
||||||
map.set_base_path( base_path );
|
map.set_base_path(base_path);
|
||||||
}
|
}
|
||||||
else if (base_path_from_xml)
|
else if (base_path_from_xml)
|
||||||
{
|
{
|
||||||
map.set_base_path( *base_path_from_xml );
|
map.set_base_path(*base_path_from_xml);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -293,30 +282,30 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
|
||||||
std::string base = xml_path.branch_path().string();
|
std::string base = xml_path.branch_path().string();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
map.set_base_path( base );
|
map.set_base_path(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<color> bgcolor = get_opt_color_attr(map_node, "background-color");
|
optional<color> bgcolor = map_node.get_opt_attr<color>("background-color");
|
||||||
if (bgcolor)
|
if (bgcolor)
|
||||||
{
|
{
|
||||||
map.set_background( * bgcolor );
|
map.set_background(*bgcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> image_filename = get_opt_attr<std::string>(map_node, "background-image");
|
optional<std::string> image_filename = map_node.get_opt_attr<std::string>("background-image");
|
||||||
if (image_filename)
|
if (image_filename)
|
||||||
{
|
{
|
||||||
map.set_background_image(ensure_relative_to_xml(image_filename));
|
map.set_background_image(ensure_relative_to_xml(image_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
map.set_srs( get_attr(map_node, "srs", map.srs() ));
|
map.set_srs(map_node.get_attr("srs", map.srs()));
|
||||||
|
|
||||||
optional<unsigned> buffer_size = get_opt_attr<unsigned>(map_node,"buffer-size");
|
optional<unsigned> buffer_size = map_node.get_opt_attr<unsigned>("buffer-size");
|
||||||
if (buffer_size)
|
if (buffer_size)
|
||||||
{
|
{
|
||||||
map.set_buffer_size(*buffer_size);
|
map.set_buffer_size(*buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> maximum_extent = get_opt_attr<std::string>(map_node,"maximum-extent");
|
optional<std::string> maximum_extent = map_node.get_opt_attr<std::string>("maximum-extent");
|
||||||
if (maximum_extent)
|
if (maximum_extent)
|
||||||
{
|
{
|
||||||
box2d<double> box;
|
box2d<double> box;
|
||||||
|
@ -327,33 +316,33 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::ostringstream s_err;
|
std::ostringstream s_err;
|
||||||
s << "failed to parse 'maximum-extent'";
|
s_err << "failed to parse 'maximum-extent'";
|
||||||
if ( strict_ )
|
if (strict_)
|
||||||
throw config_error(s_err.str());
|
throw config_error(s_err.str());
|
||||||
else
|
else
|
||||||
std::clog << "### WARNING: " << s.str() << std::endl;
|
std::clog << "### WARNING: " << s_err.str() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> font_directory = get_opt_attr<std::string>(map_node,"font-directory");
|
optional<std::string> font_directory = map_node.get_opt_attr<std::string>("font-directory");
|
||||||
if (font_directory)
|
if (font_directory)
|
||||||
{
|
{
|
||||||
extra_attr["font-directory"] = *font_directory;
|
extra_attr["font-directory"] = *font_directory;
|
||||||
freetype_engine::register_fonts( ensure_relative_to_xml(font_directory), false);
|
freetype_engine::register_fonts(ensure_relative_to_xml(font_directory), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> min_version_string = get_opt_attr<std::string>(map_node, "minimum-version");
|
optional<std::string> min_version_string = map_node.get_opt_attr<std::string>("minimum-version");
|
||||||
|
|
||||||
if (min_version_string)
|
if (min_version_string)
|
||||||
{
|
{
|
||||||
extra_attr["minimum-version"] = *min_version_string;
|
extra_attr["minimum-version"] = *min_version_string;
|
||||||
boost::char_separator<char> sep(".");
|
boost::char_separator<char> sep(".");
|
||||||
boost::tokenizer<boost::char_separator<char> > tokens(*min_version_string,sep);
|
boost::tokenizer<boost::char_separator<char> > tokens(*min_version_string, sep);
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
int n[3];
|
int n[3];
|
||||||
for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tokens.begin();
|
for (boost::tokenizer<boost::char_separator<char> >::iterator beg = tokens.begin();
|
||||||
beg!=tokens.end();++beg)
|
beg != tokens.end(); ++beg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -391,15 +380,15 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_map_include( map, map_node );
|
// parse_map_include( map, map_node );
|
||||||
}
|
}
|
||||||
catch (const boost::property_tree::ptree_bad_path &)
|
catch (node_not_found const&)
|
||||||
{
|
{
|
||||||
throw config_error("Not a map file. Node 'Map' not found.");
|
throw config_error("Not a map file. Node 'Map' not found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_parser::parse_map_include( Map & map, ptree const & include )
|
void map_parser::parse_map_include(Map & map, xml_node const& include )
|
||||||
{
|
{
|
||||||
ptree::const_iterator itr = include.begin();
|
ptree::const_iterator itr = include.begin();
|
||||||
ptree::const_iterator end = include.end();
|
ptree::const_iterator end = include.end();
|
||||||
|
|
137
src/xml_tree.cpp
137
src/xml_tree.cpp
|
@ -19,11 +19,112 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
//mapnik
|
||||||
#include <mapnik/xml_tree.hpp>
|
#include <mapnik/xml_tree.hpp>
|
||||||
|
#include <mapnik/util/conversions.hpp>
|
||||||
|
#include <mapnik/enumeration.hpp>
|
||||||
|
|
||||||
|
//boost
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline boost::optional<T> fast_cast(xml_tree const& tree, std::string const& value)
|
||||||
|
{
|
||||||
|
return boost::lexical_cast<T>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline boost::optional<int> fast_cast(xml_tree const& tree, std::string const& value)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if (mapnik::conversions::string2int(value, result))
|
||||||
|
return boost::optional<int>(result);
|
||||||
|
return boost::optional<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline boost::optional<double> fast_cast(xml_tree const& tree, std::string const& value)
|
||||||
|
{
|
||||||
|
double result;
|
||||||
|
if (mapnik::conversions::string2double(value, result))
|
||||||
|
return boost::optional<double>(result);
|
||||||
|
return boost::optional<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline boost::optional<float> fast_cast(xml_tree const& tree, std::string const& value)
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
if (mapnik::conversions::string2float(value, result))
|
||||||
|
return boost::optional<float>(result);
|
||||||
|
return boost::optional<float>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline boost::optional<std::string> fast_cast(xml_tree const& tree, std::string const& value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
class boolean;
|
||||||
|
template <typename T>
|
||||||
|
struct name_trait
|
||||||
|
{
|
||||||
|
static std::string name()
|
||||||
|
{
|
||||||
|
return "<unknown>";
|
||||||
|
}
|
||||||
|
// missing name_trait for type ...
|
||||||
|
// if you get here you are probably using a new type
|
||||||
|
// in the XML file. Just add a name trait for the new
|
||||||
|
// type below.
|
||||||
|
BOOST_STATIC_ASSERT( sizeof(T) == 0 );
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_NAME_TRAIT( type, type_name ) \
|
||||||
|
template <> \
|
||||||
|
struct name_trait<type> \
|
||||||
|
{ \
|
||||||
|
static std::string name() { return std::string("type ") + type_name; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_NAME_TRAIT( double, "double")
|
||||||
|
DEFINE_NAME_TRAIT( float, "float")
|
||||||
|
DEFINE_NAME_TRAIT( unsigned, "unsigned")
|
||||||
|
DEFINE_NAME_TRAIT( boolean, "boolean")
|
||||||
|
DEFINE_NAME_TRAIT( int, "integer" )
|
||||||
|
DEFINE_NAME_TRAIT( std::string, "string" )
|
||||||
|
DEFINE_NAME_TRAIT( color, "color" )
|
||||||
|
|
||||||
|
template <typename ENUM, int MAX>
|
||||||
|
struct name_trait< mapnik::enumeration<ENUM, MAX> >
|
||||||
|
{
|
||||||
|
typedef enumeration<ENUM, MAX> Enum;
|
||||||
|
|
||||||
|
static std::string name()
|
||||||
|
{
|
||||||
|
std::string value_list("one of [");
|
||||||
|
for (unsigned i = 0; i < Enum::MAX; ++i)
|
||||||
|
{
|
||||||
|
value_list += Enum::get_string( i );
|
||||||
|
if ( i + 1 < Enum::MAX ) value_list += ", ";
|
||||||
|
}
|
||||||
|
value_list += "]";
|
||||||
|
|
||||||
|
return value_list;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
xml_tree::xml_tree()
|
xml_tree::xml_tree()
|
||||||
: node_(*this, "<root>")
|
: node_(*this, "<root>")
|
||||||
{
|
{
|
||||||
|
@ -39,7 +140,7 @@ std::string xml_tree::filename() const
|
||||||
return file_;
|
return file_;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml_node &xml_tree::node()
|
xml_node &xml_tree::root()
|
||||||
{
|
{
|
||||||
return node_;
|
return node_;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +162,7 @@ std::string xml_node::name() const
|
||||||
if (!text_node_)
|
if (!text_node_)
|
||||||
return name_;
|
return name_;
|
||||||
else
|
else
|
||||||
return "<xmltext>";
|
return "<xmltext>"; //TODO: throw
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string xml_node::text() const
|
std::string xml_node::text() const
|
||||||
|
@ -69,7 +170,7 @@ std::string xml_node::text() const
|
||||||
if (text_node_)
|
if (text_node_)
|
||||||
return name_;
|
return name_;
|
||||||
else
|
else
|
||||||
return "NOT A TEXT NODE";
|
return "NOT A TEXT NODE"; //TODO: throw
|
||||||
}
|
}
|
||||||
|
|
||||||
void xml_node::set_processed(bool processed)
|
void xml_node::set_processed(bool processed)
|
||||||
|
@ -83,5 +184,35 @@ xml_node &xml_node::add_child(std::string name, unsigned line, bool text_node)
|
||||||
return children_.back();
|
return children_.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xml_node & xml_node::get_child(std::string name)
|
||||||
|
{
|
||||||
|
std::list<xml_node>::iterator itr = children_.begin();
|
||||||
|
std::list<xml_node>::iterator end = children_.end();
|
||||||
|
for (; itr != end; itr++)
|
||||||
|
{
|
||||||
|
if (!(itr->text_node_) && itr->name_ == name)
|
||||||
|
{
|
||||||
|
itr->set_processed(true);
|
||||||
|
return *itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw node_not_found(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
boost::optional<T> xml_node::get_opt_attr(std::string const& name) const
|
||||||
|
{
|
||||||
|
std::map<std::string, xml_attribute>::const_iterator itr = attributes_.find(name);
|
||||||
|
if (itr == attributes_.end()) return boost::optional<T>();
|
||||||
|
boost::optional<T> result = fast_cast<T>(itr->second);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
throw config_error(std::string("Failed to parse attribute '") +
|
||||||
|
name + "'. Expected " + name_trait<T>::name() +
|
||||||
|
" but got '" + itr->second + "'");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} //ns mapnik
|
} //ns mapnik
|
||||||
|
|
Loading…
Reference in a new issue