2008-03-02 14:23:50 +01:00
|
|
|
// much of this is based on osm2pgsql
|
|
|
|
|
|
|
|
#include "osmparser.h"
|
|
|
|
#include "osm.h"
|
|
|
|
#include <string>
|
|
|
|
#include <cassert>
|
|
|
|
|
2011-11-14 04:37:50 +01:00
|
|
|
osm_item* osmparser::cur_item=NULL;
|
2012-12-20 04:24:52 +01:00
|
|
|
mapnik::value_integer osmparser::curID=0;
|
2011-11-14 04:37:50 +01:00
|
|
|
bool osmparser::in_node=false, osmparser::in_way=false;
|
|
|
|
osm_dataset* osmparser::components=NULL;
|
|
|
|
std::string osmparser::error="";
|
|
|
|
std::map<long,osm_node*> osmparser::tmp_node_store=std::map<long,osm_node*>();
|
2008-03-02 14:23:50 +01:00
|
|
|
|
|
|
|
void osmparser::processNode(xmlTextReaderPtr reader)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
xmlChar *name = xmlTextReaderName(reader);
|
|
|
|
if(name==NULL)
|
|
|
|
name=xmlStrdup(BAD_CAST "--");
|
2008-03-02 14:23:50 +01:00
|
|
|
|
2011-11-14 04:37:50 +01:00
|
|
|
switch(xmlTextReaderNodeType(reader))
|
|
|
|
{
|
2011-04-02 05:45:50 +02:00
|
|
|
case XML_READER_TYPE_ELEMENT:
|
2011-11-14 04:37:50 +01:00
|
|
|
startElement(reader,name);
|
|
|
|
break;
|
2008-03-02 14:23:50 +01:00
|
|
|
|
2011-04-02 05:45:50 +02:00
|
|
|
case XML_READER_TYPE_END_ELEMENT:
|
2011-11-14 04:37:50 +01:00
|
|
|
endElement(name);
|
|
|
|
}
|
|
|
|
xmlFree(name);
|
2008-03-02 14:23:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void osmparser::startElement(xmlTextReaderPtr reader, const xmlChar *name)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
std::string tags;
|
|
|
|
xmlChar *xid, *xlat, *xlon, *xk, *xv;
|
2008-03-02 14:23:50 +01:00
|
|
|
|
2011-04-02 05:45:50 +02:00
|
|
|
if(xmlStrEqual(name,BAD_CAST "node"))
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
curID = 0;
|
|
|
|
in_node = true;
|
|
|
|
osm_node *node=new osm_node;
|
|
|
|
xlat=xmlTextReaderGetAttribute(reader,BAD_CAST "lat");
|
|
|
|
xlon=xmlTextReaderGetAttribute(reader,BAD_CAST "lon");
|
|
|
|
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "id");
|
|
|
|
assert(xlat);
|
|
|
|
assert(xlon);
|
|
|
|
assert(xid);
|
|
|
|
node->lat=atof((char*)xlat);
|
|
|
|
node->lon=atof((char*)xlon);
|
|
|
|
node->id = atol((char*)xid);
|
|
|
|
cur_item = node;
|
|
|
|
tmp_node_store[node->id] = node;
|
|
|
|
xmlFree(xid);
|
|
|
|
xmlFree(xlon);
|
|
|
|
xmlFree(xlat);
|
2011-04-02 05:45:50 +02:00
|
|
|
}
|
2011-11-14 04:37:50 +01:00
|
|
|
else if (xmlStrEqual(name,BAD_CAST "way"))
|
2011-04-02 05:45:50 +02:00
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
curID=0;
|
|
|
|
in_way = true;
|
|
|
|
osm_way *way=new osm_way;
|
|
|
|
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "id");
|
|
|
|
assert(xid);
|
|
|
|
way->id = atol((char*)xid);
|
|
|
|
cur_item = way;
|
|
|
|
xmlFree(xid);
|
2011-04-02 05:45:50 +02:00
|
|
|
}
|
|
|
|
else if (xmlStrEqual(name,BAD_CAST "nd"))
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
xid=xmlTextReaderGetAttribute(reader,BAD_CAST "ref");
|
|
|
|
assert(xid);
|
|
|
|
long ndid = atol((char*)xid);
|
|
|
|
if(tmp_node_store.find(ndid)!=tmp_node_store.end())
|
|
|
|
{
|
|
|
|
(static_cast<osm_way*>(cur_item))->nodes.push_back
|
|
|
|
(tmp_node_store[ndid]);
|
|
|
|
}
|
|
|
|
xmlFree(xid);
|
2011-04-02 05:45:50 +02:00
|
|
|
}
|
|
|
|
else if (xmlStrEqual(name,BAD_CAST "tag"))
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
std::string key="", value="";
|
|
|
|
xk = xmlTextReaderGetAttribute(reader,BAD_CAST "k");
|
|
|
|
xv = xmlTextReaderGetAttribute(reader,BAD_CAST "v");
|
|
|
|
assert(xk);
|
|
|
|
assert(xv);
|
|
|
|
cur_item->keyvals[(char*)xk] = (char*)xv;
|
|
|
|
xmlFree(xk);
|
|
|
|
xmlFree(xv);
|
2011-04-02 05:45:50 +02:00
|
|
|
}
|
2012-03-20 23:03:01 +01:00
|
|
|
if (xmlTextReaderIsEmptyElement(reader))
|
|
|
|
{
|
|
|
|
// Fake endElement for empty nodes
|
|
|
|
endElement(name);
|
|
|
|
}
|
2008-03-02 14:23:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void osmparser::endElement(const xmlChar* name)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
if(xmlStrEqual(name,BAD_CAST "node"))
|
|
|
|
{
|
|
|
|
in_node = false;
|
|
|
|
components->add_node(static_cast<osm_node*>(cur_item));
|
|
|
|
}
|
|
|
|
else if(xmlStrEqual(name,BAD_CAST "way"))
|
|
|
|
{
|
|
|
|
in_way = false;
|
|
|
|
components->add_way(static_cast<osm_way*>(cur_item));
|
|
|
|
}
|
2008-03-02 14:23:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool osmparser::parse(osm_dataset *ds, const char* filename)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
components=ds;
|
|
|
|
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename);
|
|
|
|
int ret=do_parse(reader);
|
|
|
|
xmlFreeTextReader(reader);
|
|
|
|
return (ret==0) ? true:false;
|
2009-02-15 14:51:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool osmparser::parse(osm_dataset *ds,char* data, int nbytes)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
// from cocoasamurai.blogspot.com/2008/10/getting-some-xml-love-with-
|
|
|
|
// libxml2.html, converted from Objective-C to straight C
|
|
|
|
|
|
|
|
components=ds;
|
|
|
|
xmlTextReaderPtr reader = xmlReaderForMemory(data,nbytes,NULL,NULL,0);
|
|
|
|
int ret=do_parse(reader);
|
|
|
|
xmlFreeTextReader(reader);
|
|
|
|
return (ret==0) ? true:false;
|
2009-02-15 14:51:07 +01:00
|
|
|
}
|
|
|
|
|
2011-11-14 04:37:50 +01:00
|
|
|
|
2009-02-15 14:51:07 +01:00
|
|
|
int osmparser::do_parse(xmlTextReaderPtr reader)
|
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
int ret=-1;
|
|
|
|
if(reader!=NULL)
|
2011-04-02 05:45:50 +02:00
|
|
|
{
|
2011-11-14 04:37:50 +01:00
|
|
|
ret = xmlTextReaderRead(reader);
|
|
|
|
while(ret==1)
|
|
|
|
{
|
|
|
|
processNode(reader);
|
|
|
|
ret=xmlTextReaderRead(reader);
|
|
|
|
}
|
2011-04-02 05:45:50 +02:00
|
|
|
}
|
2011-11-14 04:37:50 +01:00
|
|
|
return ret;
|
2008-03-02 14:23:50 +01:00
|
|
|
}
|