mapnik/plugins/input/osm/osmparser.cpp

163 lines
4.4 KiB
C++
Raw Normal View History

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>
using std::cerr;
using std::endl;
osm_item* osmparser::cur_item=NULL;
long osmparser::curID=0;
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)
{
xmlChar *name = xmlTextReaderName(reader);
if(name==NULL)
name=xmlStrdup(BAD_CAST "--");
2008-03-02 14:23:50 +01:00
switch(xmlTextReaderNodeType(reader))
{
2011-04-02 05:45:50 +02:00
case XML_READER_TYPE_ELEMENT:
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:
endElement(name);
}
xmlFree(name);
2008-03-02 14:23:50 +01:00
}
void osmparser::startElement(xmlTextReaderPtr reader, const xmlChar *name)
{
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"))
{
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
}
else if (xmlStrEqual(name,BAD_CAST "way"))
2011-04-02 05:45:50 +02: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;
// Prevent ways with no name being assigned a name of "0"
cur_item->keyvals["name"] = "";
// HACK: allows comparison with "" in the XML file. Otherwise it
// doesn't work. Only do for the most crucial tags for Freemap's
// purposes. TODO investigate why this is
cur_item->keyvals["width"] = "";
cur_item->keyvals["horse"] = "";
cur_item->keyvals["foot"] = "";
cur_item->keyvals["bicycle"] = "";
xmlFree(xid);
2011-04-02 05:45:50 +02:00
}
else if (xmlStrEqual(name,BAD_CAST "nd"))
{
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"))
{
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
}
if (xmlTextReaderIsEmptyElement(reader))
{
// Fake endElement for empty nodes
endElement(name);
}
2008-03-02 14:23:50 +01:00
}
void osmparser::endElement(const xmlChar* name)
{
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)
{
components=ds;
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename);
int ret=do_parse(reader);
xmlFreeTextReader(reader);
return (ret==0) ? true:false;
}
bool osmparser::parse(osm_dataset *ds,char* data, int nbytes)
{
// 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;
}
int osmparser::do_parse(xmlTextReaderPtr reader)
{
int ret=-1;
if(reader!=NULL)
2011-04-02 05:45:50 +02:00
{
ret = xmlTextReaderRead(reader);
while(ret==1)
{
processNode(reader);
ret=xmlTextReaderRead(reader);
}
2011-04-02 05:45:50 +02:00
}
return ret;
2008-03-02 14:23:50 +01:00
}