diff --git a/include/mapnik/internal/dump_xml.hpp b/include/mapnik/internal/dump_xml.hpp index 35a0ad7c3..391b89d15 100644 --- a/include/mapnik/internal/dump_xml.hpp +++ b/include/mapnik/internal/dump_xml.hpp @@ -13,22 +13,22 @@ void dump_xml(xml_node const& xml, unsigned level=0) indent += " "; } xml_node::attribute_map const& attr = xml.get_attributes(); - std::cout << indent <<"[" << xml.name(); + std::cerr << indent <<"[" << xml.name(); xml_node::attribute_map::const_iterator aitr = attr.begin(); xml_node::attribute_map::const_iterator aend = attr.end(); for (;aitr!=aend; aitr++) { - std::cout << " (" << aitr->first << ", " << aitr->second.value << ", " << aitr->second.processed << ")"; + std::cerr << " (" << aitr->first << ", " << aitr->second.value << ", " << aitr->second.processed << ")"; } - std::cout << "]" << "\n"; - if (xml.is_text()) std::cout << indent << "text: '" << xml.text() << "'\n"; + std::cerr << "]" << "\n"; + if (xml.is_text()) std::cerr << indent << "text: '" << xml.text() << "'\n"; xml_node::const_iterator itr = xml.begin(); xml_node::const_iterator end = xml.end(); for (; itr!=end; itr++) { dump_xml(*itr, level+1); } - std::cout << indent << "[/" << xml.name() << "]" << "\n"; + std::cerr << indent << "[/" << xml.name() << "]" << "\n"; } diff --git a/include/mapnik/libxml2_loader.hpp b/include/mapnik/xml_loader.hpp similarity index 87% rename from include/mapnik/libxml2_loader.hpp rename to include/mapnik/xml_loader.hpp index 5acad070e..b102b61eb 100644 --- a/include/mapnik/libxml2_loader.hpp +++ b/include/mapnik/xml_loader.hpp @@ -29,8 +29,8 @@ namespace mapnik { class xml_node; -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=""); +void read_xml(std::string const & filename, xml_node &node); +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path=""); } #endif // MAPNIK_LIBXML2_LOADER_HPP diff --git a/src/build.py b/src/build.py index 9034a6de2..78df41b46 100644 --- a/src/build.py +++ b/src/build.py @@ -301,7 +301,7 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']: env2 = lib_env.Clone() env2.Append(CXXFLAGS = '-DHAVE_LIBXML2') libmapnik_cxxflags.append('-DHAVE_LIBXML2') - fixup = ['load_map.cpp','libxml2_loader.cpp'] + fixup = ['libxml2_loader.cpp'] for cpp in fixup: if cpp in source: source.remove(cpp) @@ -309,6 +309,12 @@ if env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']: source.insert(0,env2.StaticObject(cpp)) else: source.insert(0,env2.SharedObject(cpp)) +else: + source += Split( + """ + rapidxml_loader.cpp + """ + ) if env['CUSTOM_LDFLAGS']: linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag) diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index 5472d29c0..72e76372f 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -23,7 +23,7 @@ #ifdef HAVE_LIBXML2 // mapnik -#include +#include #include #include @@ -205,12 +205,12 @@ private: const char *url_; }; -void read_xml2(std::string const & filename, xml_node &node) +void read_xml(std::string const & filename, xml_node &node) { libxml2_loader loader; loader.load(filename, node); } -void read_xml2_string(std::string const & str, xml_node &node, std::string const & base_path) +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path) { libxml2_loader loader; loader.load_string(str, node, base_path); diff --git a/src/load_map.cpp b/src/load_map.cpp index 0330535b2..f519934c2 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -34,10 +34,7 @@ #include #include #include - -#ifdef HAVE_LIBXML2 -#include -#endif +#include #include #include @@ -141,19 +138,7 @@ void load_map(Map & map, std::string const& filename, bool strict) // TODO - use xml encoding? xml_tree tree("utf8"); tree.set_filename(filename); -#ifdef HAVE_LIBXML2 - read_xml2(filename, tree.root()); -#else - try - { - read_xml(filename, pt, boost::property_tree::xml_parser::no_concat_text|boost::property_tree::xml_parser::no_comments); - remove_empty_text_nodes(pt); - } - catch (const boost::property_tree::xml_parser_error & ex) - { - throw config_error( ex.what() ); - } -#endif + read_xml(filename, tree.root()); map_parser parser(strict, filename); parser.parse_map(map, tree.root()); dump_xml(tree.root()); @@ -163,25 +148,10 @@ void load_map_string(Map & map, std::string const& str, bool strict, std::string { // TODO - use xml encoding? xml_tree tree("utf8"); -#ifdef HAVE_LIBXML2 if (!base_path.empty()) - read_xml2_string(str, tree.root(), base_path); // accept base_path passed into function + read_xml_string(str, tree.root(), base_path); // accept base_path passed into function else - read_xml2_string(str, tree.root(), map.base_path()); // default to map base_path -#else - try - { - std::istringstream s(str); - // TODO - support base_path? - read_xml(s, pt, boost::property_tree::xml_parser::no_concat_text|boost::property_tree::xml_parser::no_comments); - remove_empty_text_nodes(pt); - } - catch (const boost::property_tree::xml_parser_error & ex) - { - throw config_error( ex.what() ) ; - } -#endif - + read_xml_string(str, tree.root(), map.base_path()); // default to map base_path map_parser parser(strict, base_path); parser.parse_map(map, tree.root(), base_path); } diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp new file mode 100644 index 000000000..c7be38b5b --- /dev/null +++ b/src/rapidxml_loader.cpp @@ -0,0 +1,171 @@ + + +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifdef HAVE_LIBXML2 +#error HAVE_LIBXML2 defined but compiling rapidxml_loader.cpp! +#endif + +// mapnik +#include +#include +#include +#include + +// boost +#include +#include + +// stl +#include +#include + +using namespace std; +namespace rapidxml = boost::property_tree::detail::rapidxml; +namespace mapnik +{ +class rapidxml_loader : boost::noncopyable +{ +public: + rapidxml_loader(const char *encoding = NULL) : + filename_() + { + + } + + ~rapidxml_loader() + { + } + + void load(const std::string & filename, xml_node &node) + { + filename_ = filename; + std::basic_ifstream stream(filename.c_str()); + if (!stream) + { + throw config_error("Could not load map file", 0, filename); + } +// TODO: stream.imbue(loc); + load(stream, node); + } + + void load(std::basic_istream &stream, xml_node &node) + { + stream.unsetf(std::ios::skipws); + std::vector v(std::istreambuf_iterator(stream.rdbuf()), + std::istreambuf_iterator()); + if (!stream.good()) + { + throw config_error("Could not load map file", 0, filename_); + } + v.push_back(0); // zero-terminate + try + { + // Parse using appropriate flags + const int f_tws = rapidxml::parse_normalize_whitespace + | rapidxml::parse_trim_whitespace; + rapidxml::xml_document<> doc; + doc.parse(&v.front()); + + for (rapidxml::xml_node *child = doc.first_node(); + child; child = child->next_sibling()) + { + populate_tree(child, node); + } + } + catch (rapidxml::parse_error &e) + { + long line = static_cast( + std::count(&v.front(), e.where(), '\n') + 1); + throw config_error(e.what(), line, filename_); + } + } + + void load_string(const std::string & buffer, xml_node &node, std::string const & base_path ) + { + +// if (!base_path.empty()) +// { +// boost::filesystem::path path(base_path); +// if (!boost::filesystem::exists(path)) { +// throw config_error(string("Could not locate base_path '") + +// base_path + "': file or directory does not exist"); +// } +// } + + + load(buffer, node); + } +private: + void populate_tree(rapidxml::xml_node *cur_node, xml_node &node) + { + switch (cur_node->type()) + { + case rapidxml::node_element: + { + xml_node &new_node = node.add_child((char *)cur_node->name(), 0, false); + // Copy attributes + for (rapidxml::xml_attribute *attr = cur_node->first_attribute(); + attr; attr = attr->next_attribute()) + { + new_node.add_attribute(attr->name(), attr->value()); + } + + // Copy children + for (rapidxml::xml_node *child = cur_node->first_node(); + child; child = child->next_sibling()) + { + populate_tree(child, new_node); + } + } + break; + + // Data nodes + case rapidxml::node_data: + case rapidxml::node_cdata: + { + std::string trimmed = boost::algorithm::trim_copy(std::string(cur_node->value())); + if (trimmed.empty()) break; //Don't add empty text nodes + node.add_child(trimmed, 0, true); + } + break; + default: + break; + } + } +private: + std::string filename_; +}; + +void read_xml(std::string const & filename, xml_node &node) +{ + rapidxml_loader loader; + loader.load(filename, node); +} +void read_xml_string(std::string const & str, xml_node &node, std::string const & base_path) +{ + rapidxml_loader loader; + loader.load_string(str, node, base_path); +} + +} // end of namespace mapnik