23 #include <boost/filesystem/path.hpp> 24 #include <boost/unordered_map.hpp> 25 #include <boost/filesystem/operations.hpp> 26 #include <boost/type_traits/is_same.hpp> 27 #include <unordered_set> 29 #include "../../extras/eaglexml/eaglexml.hpp" 30 #include "../../extras/eaglexml/eaglexml_iterators.hpp" 43 using boost::filesystem::path;
44 using nl = std::numeric_limits<double>;
53 :
public eaglexml::stream_cache<>::stream_cache_observer
58 | eaglexml::parse_normalize_whitespace
59 | eaglexml::parse_trim_whitespace
60 | eaglexml::parse_validate_closing_tags
61 | eaglexml::parse_default;
93 void parse(
const path& xml_file)
99 std::ifstream xml_stream(xml_file.string());
104 LOG_SEV(importer_log, info) <<
"Load xml-file \"" << xml_file.string() <<
"\"";
106 fileSize = boost::filesystem::file_size(xml_file);
108 LOG_SEV(importer_log, info) <<
"File size is " <<
fileSize / (1024) <<
"kb";
110 nodes = boost::make_shared<std::vector<Node> >();
111 ways = boost::make_shared<std::vector<Way> >();
112 relations = boost::make_shared<std::vector<Relation> >();
115 eaglexml::stream_cache<> cache(xml_stream, 8 * 1024 * 1024);
116 eaglexml::xml_document<> document;
119 cache.max_segments_to_read(1);
120 cache.observer(
this);
125 document.parse<parser_flags>(&cache);
127 eaglexml::xml_node<>* osm = document.first_node(
"osm");
137 }
catch(eaglexml::parse_error& e)
196 std::map<std::string, void (OsmXmlParser::*)(eaglexml::xml_node<>*)> entities;
204 for(eaglexml::node_iterator<> it(osmRoot);
205 it != eaglexml::node_iterator<>();
208 auto entityIt = entities.find(it->name());
210 if(!ignoreUnknownEntities && entityIt == entities.end())
214 (this->*(entityIt->second))(&*it);
216 const auto id = *boost::get_error_info<excp::InfoUnresolvableId>(e);
218 LOG_SEV(importer_log, warning) <<
"Bad osm id[" <<
id <<
"]. Entity is skipped!";
233 LOG_SEV(importer_log, info) <<
"Bounds tag in osm data is ignored by this software!";
256 parseProperties<Node>(node->first_node(), &tags,
nullptr,
nullptr,
nullptr,
nullptr);
279 std::vector<NodeId> nodeIds;
281 parseProperties<Way>(way->first_node(), &tags, &nodeIds,
nullptr,
nullptr,
nullptr);
283 if (nodeIds.size() == 0)
287 ways->push_back(
Way(nodeIds, tags));
303 std::vector<NodeId> nodeIds;
304 std::vector<WayId> wayIds;
309 parseProperties<Relation>(relation->first_node(), &tags, &nodeIds, &nodeRoles, &wayIds, &wayRoles);
311 if (nodeIds.size() == 0 && wayIds.size() == 0)
333 template<
typename Target>
336 std::vector<NodeId>* nodeRefIds,
338 std::vector<WayId>* wayRefIds,
341 BOOST_STATIC_ASSERT((boost::is_same<Target, Node>::value || boost::is_same<Target, Way>::value || boost::is_same<Target, Relation>::value));
345 eaglexml::xml_node<>* prop = firstProp;
346 for(;prop; prop = prop->next_sibling())
348 const char* propName = firstProp->name();
350 if(std::strcmp(propName,
"tag") == 0)
358 (*tagMap)[key] = value;
360 }
else if(boost::is_same<Target, Way>::value && std::strcmp(propName,
"nd") == 0)
368 }
else if(boost::is_same<Target, Relation>::value && std::strcmp(propName,
"member") == 0)
377 eaglexml::xml_attribute<>*
attr = prop->first_attribute(
"type");
379 if(!attr || attr->value_size() == 0)
387 const char* type = attr->value();
388 if(std::strcmp(type,
"node") == 0)
391 nodeRefIds->push_back(nodeId);
393 }
else if(std::strcmp(type,
"way") == 0)
396 wayRefIds->push_back(wayId);
398 }
else if(std::strcmp(type,
"relation") == 0) {
402 LOG_SEV(importer_log, warning) <<
"This software does not support relation member in relations!";
403 LOG_SEV(importer_log, warning) <<
"Reference is ignored!";
431 eaglexml::xml_attribute<>*
attr = node->first_attribute(attrname.c_str(), attrname.size());
436 const char* value = attr->value();
438 *dest = boost::lexical_cast<T>(value);
439 }
catch(boost::bad_lexical_cast& e)
456 template<
typename IdType>
457 IdType
resolveOsmId(OsmIdType osmId,
const boost::unordered_map<OsmIdType, IdType>& table)
459 auto it = table.find(osmId);
461 if(it == table.end())
468 virtual void on_fetch(
unsigned int chars_left,
unsigned int need, node_type* active_node ) {}
476 int after = int(100 * (
double)
alreadyRead / (
double)fileSize);
479 LOG_SEV(importer_log, info) <<
"Loading [" << std::min(after, 99) <<
"%]";
504 shared_ptr< std::vector<Node> >
nodes;
507 shared_ptr< std::vector<Way> >
ways;
554 LOG_SEV(importer_log, info) <<
"Clipping nodes with [lon: " << bounds.
minX <<
" to " << bounds.
maxX <<
", lat: " << bounds.
minY <<
" to " << bounds.
maxY <<
"]";
556 shared_ptr<Geodata> geodata = boost::make_shared<Geodata>();
559 LOG_SEV(importer_log, info) <<
"Start parsing...";
560 parser.
parse(xml_file);
562 LOG_SEV(importer_log, info) <<
"Insert into geodata...";
shared_ptr< std::vector< Relation > > getParsedRelations() const
Returns a vector with parsed relations.
std::numeric_limits< double > nl
void parseNode(eaglexml::xml_node<> *node)
parses a node entity
IdType resolveOsmId(OsmIdType osmId, const boost::unordered_map< OsmIdType, IdType > &table)
Resolves a osm id into an internal id.
bool ignoreUnknownEntities
Specifies weather the parser should ignore unknown entities.
shared_ptr< std::vector< Node > > nodes
List to be filled with nodes.
void parseEntities(eaglexml::xml_node<> *osmRoot)
parses the osm-root element and creates given objects
static const char * check_xml_entities
Check all xml entities.
boost::unordered_map< OsmIdType, WayId > wayIdMapping
Mapping from osm ids to internal ids for ways.
std::uintmax_t alreadyRead
Bytes already read from the xml file.
shared_ptr< std::vector< Way > > ways
List to be filled with ways.
boost::error_info< struct TagXmlEntityName, string > InfoXmlEntityName
Use this this to specify the exception related xml entity.
TESTABLE shared_ptr< Geodata > importXML()
Parses an osm xml file specified in configuration containing osm data.
static const char * max_lat
maximum node latitude to include into imported data
Thrown if an osm id was not specified before resolving.
shared_ptr< std::vector< Node > > getParsedNodes() const
Returns a vector with parsed nodes.
void parseProperties(eaglexml::xml_node<> *firstProp, DataMap< CachedString, CachedString > *tagMap, std::vector< NodeId > *nodeRefIds, DataMap< NodeId, CachedString > *nodeRoleMap, std::vector< WayId > *wayRefIds, DataMap< WayId, CachedString > *wayRoleMap)
parses properties of an osm-object
boost::error_info< struct TagBadSourceValue, string > InfoBadSourceValue
String representation of a bad source value.
bool contains(const basic_vector2< T > &p) const
static const char * min_lat
minimum node latitude to include into imported data
virtual void on_read_begin(unsigned int segments)
Importer(const shared_ptr< Configuration > &config)
Initializes the importer.
OsmXmlParser(bool ignoreUnknownEntities, const FloatRect &bounds={-nl::max(),-nl::max(), nl::max(), nl::max()})
Creates a new parser and sets default settings.
static const char * path_to_osmdata
Option to get the path to osm xml file (type: string)
std::uintmax_t fileSize
Size of the xml file in bytes.
virtual void on_segment_read()
const FloatRect clippingBounds
Specifies the rectangular area in which the nodes are kept.
boost::unordered_map< OsmIdType, NodeId > nodeIdMapping
Mapping from osm ids to internal ids for nodes.
#define LOG_SEV(log, lvl)
boost::error_info< struct TagWhatInfo, string > InfoWhat
Use this info to give an what msg to the exception.
unsigned int segmentSize
Number of bytes read by one read operation.
uint64_t OsmIdType
Type, where osm ids stored in.
bool outputIgnoreRelation
Booleans for some output, which should only appear once.
boost::error_info< struct TagUnresolvableId, long > InfoUnresolvableId
Specifies the id, which was not resolvable.
Thrown if a file was not found.
static const char * min_lon
minimum node longitude to include into imported data
shared_ptr< Configuration > config
void parseWay(eaglexml::xml_node<> *way)
parses the way entity
void parse(const path &xml_file)
Will parse a given xml file.
basic_vector2< double > FloatPoint
void extractAttributeFromNode(const string &attrname, eaglexml::xml_node<> *node, T *dest)
Extracts the value of a specified xml-attribute from a given node.
static const char * max_lon
maximum node longitude to include into imported data
void parseBounds(eaglexml::xml_node<> *node)
parses the bound entity
std::unordered_set< OsmIdType > clippedNodes
Id of clipped nodes.
static const int parser_flags
flags for parsing the xml file
shared_ptr< std::vector< Way > > getParsedWays() const
Returns a vector with parsed ways.
Represents a string which is cached into an internal cache.
shared_ptr< std::vector< Relation > > relations
List to be filled with relations.
std::size_t getNumberOfClippedNodes() const
Returns the number of clipped nodes.
void parseRelation(eaglexml::xml_node<> *relation)
parses the relation entity
virtual void on_fetch(unsigned int chars_left, unsigned int need, node_type *active_node)
boost::error_info< struct TagFileName, string > InfoFileName
Use this to inform about a file name.
virtual void on_buffer_resize()