Convert first function to new XML structure.

This commit is contained in:
Hermann Kraus 2012-03-06 15:18:11 +01:00
parent 481271cb76
commit 191d0f907a
4 changed files with 203 additions and 57 deletions

View file

@ -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

View file

@ -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_;

View 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();

View file

@ -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