Add XML functions.

This commit is contained in:
Hermann Kraus 2012-03-07 03:57:31 +01:00
parent f214675c69
commit 9a05dc1828
3 changed files with 207 additions and 13 deletions

View file

@ -40,6 +40,7 @@ class color;
class xml_attribute
{
public:
xml_attribute(std::string const& value);
std::string value;
mutable bool processed;
};
@ -47,16 +48,34 @@ public:
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(std::string node_name);
virtual const char* what() const throw();
~node_not_found() throw ();
private:
std::string node_name_;
};
class attribute_not_found: public std::exception
{
public:
attribute_not_found(std::string const& node_name, std::string const& attribute_name);
virtual const char* what() const throw();
~attribute_not_found() throw ();
private:
std::string node_name_;
std::string attribute_name_;
};
class more_than_one_child: public std::exception
{
public:
more_than_one_child(std::string const& node_name);
virtual const char* what() const throw();
~more_than_one_child() throw ();
private:
std::string node_name_;
};
class xml_node
{
public:
@ -70,14 +89,15 @@ public:
xml_node &add_child(std::string const& name, unsigned line=0, bool text_node = false);
void add_attribute(std::string const& name, std::string const& value);
void set_processed(bool processed);
void set_processed(bool processed) const;
const_iterator begin() const;
const_iterator end() const;
xml_node & get_child(std::string const& name);
xml_node const& get_child(std::string const& name) const;
xml_node *get_opt_child(std::string const& name) const;
xml_node const* get_opt_child(std::string const& name) const;
bool has_child(std::string const& name) const;
template <typename T>

View file

@ -708,7 +708,7 @@ void map_parser::parse_rule(feature_type_style & style, xml_node const& r)
name = r.get_attr("name", std::string());
rule rule(name);
xml_node *child = r.get_opt_child("Filter");
xml_node const* child = r.get_opt_child("Filter");
if (child)
{
rule.set_filter(child->get_value<expression_ptr>());

View file

@ -25,6 +25,8 @@
#include <mapnik/util/conversions.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/gamma_method.hpp>
#include <mapnik/line_symbolizer.hpp>
//boost
#include <boost/lexical_cast.hpp>
@ -152,6 +154,68 @@ xml_node &xml_tree::root()
return node_;
}
/****************************************************************************/
xml_attribute::xml_attribute(std::string const& value_)
: value(value_), processed(false)
{
}
/****************************************************************************/
node_not_found::node_not_found(std::string node_name)
: node_name_(node_name)
{
}
const char* node_not_found::what() const throw()
{
return ("Node "+node_name_+ "not found").c_str();
}
node_not_found::~node_not_found() throw()
{
}
attribute_not_found::attribute_not_found(
std::string const& node_name,
std::string const& attribute_name)
:
node_name_(node_name),
attribute_name_(attribute_name)
{
}
const char* attribute_not_found::what() const throw()
{
return ("Attribute '" + attribute_name_ +"' not found in node '"+node_name_+ "'").c_str();
}
attribute_not_found::~attribute_not_found() throw()
{
}
more_than_one_child::more_than_one_child(std::string const& node_name)
: node_name_(node_name)
{
}
const char* more_than_one_child::what() const throw()
{
return ("More than one child node in node '" + node_name_ +"'").c_str();
}
more_than_one_child::~more_than_one_child() throw()
{
}
/****************************************************************************/
xml_node::xml_node(xml_tree &tree, std::string name, unsigned line, bool text_node)
@ -169,7 +233,7 @@ std::string xml_node::name() const
if (!text_node_)
return name_;
else
return "<xmltext>"; //TODO: throw
return "<xmltext>";
}
std::string xml_node::text() const
@ -180,9 +244,19 @@ std::string xml_node::text() const
return "NOT A TEXT NODE"; //TODO: throw
}
void xml_node::set_processed(bool processed)
bool xml_node::is_text() const
{
processed_ = processed;
return text_node_;
}
bool xml_node::is(std::string const& name) const
{
if (name_ == name)
{
processed_ = true;
return true;
}
return false;
}
xml_node &xml_node::add_child(std::string const& name, unsigned line, bool text_node)
@ -191,6 +265,26 @@ xml_node &xml_node::add_child(std::string const& name, unsigned line, bool text_
return children_.back();
}
void xml_node::add_attribute(std::string const& name, std::string const& value)
{
attributes_.insert(std::make_pair(name,xml_attribute(value)));
}
void xml_node::set_processed(bool processed) const
{
processed_ = processed;
}
xml_node::const_iterator xml_node::begin() const
{
return children_.begin();
}
xml_node::const_iterator xml_node::end() const
{
return children_.end();
}
xml_node & xml_node::get_child(std::string const& name)
{
std::list<xml_node>::iterator itr = children_.begin();
@ -206,20 +300,100 @@ xml_node & xml_node::get_child(std::string const& name)
throw node_not_found(name);
}
xml_node const& xml_node::get_child(std::string const& name) const
{
xml_node const* node = get_opt_child(name);
if (!node) throw node_not_found(name);
return *node;
}
xml_node const* xml_node::get_opt_child(std::string const& name) const
{
const_iterator itr = children_.begin();
const_iterator end = children_.end();
for (; itr != end; itr++)
{
if (!(itr->text_node_) && itr->name_ == name)
{
itr->set_processed(true);
return &(*itr);
}
}
return 0;
}
bool xml_node::has_child(std::string const& name) const
{
return get_opt_child(name) != 0;
}
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);
itr->second.processed = true;
boost::optional<T> result = fast_cast<T>(tree_, itr->second.value);
if (!result)
{
throw config_error(std::string("Failed to parse attribute '") +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + itr->second + "'");
" but got '" + itr->second.value + "'");
}
return result;
}
template <typename T>
T xml_node::get_attr(std::string const& name, T const& default_value) const
{
boost::optional<T> value = get_opt_attr<T>(name);
if (value) return *value;
return default_value;
}
template <typename T>
T xml_node::get_attr(std::string const& name) const
{
boost::optional<T> value = get_opt_attr<T>(name);
if (value) return *value;
throw attribute_not_found(name_, name);
}
std::string xml_node::get_text() const
{
if (children_.size() == 0)
{
return "";
}
if (children_.size() == 1)
{
return children_.front().text();
}
throw more_than_one_child(name_);
}
template <typename T>
T xml_node::get_value() const
{
boost::optional<T> result = fast_cast<T>(get_text());
if (!result)
{
throw config_error(std::string("Failed to parse value in node '") +
name_ + "'. Expected " + name_trait<T>::name() +
" but got '" + get_text() + "'");
}
return result;
}
#define compile_get_opt_attr(T) template boost::optional<T> xml_node::get_opt_attr<T>(std::string const&) const
//compile_get_opt_attr(boolean);
compile_get_opt_attr(std::string);
compile_get_opt_attr(unsigned);
compile_get_opt_attr(float);
compile_get_opt_attr(double);
compile_get_opt_attr(color);
compile_get_opt_attr(gamma_method_e);
compile_get_opt_attr(line_rasterizer_e);
} //ns mapnik