Now using libxml2

This commit is contained in:
Nick Whitelegg 2008-03-02 13:23:50 +00:00
parent 415c8a6c92
commit b117de1bdb
16 changed files with 181 additions and 400 deletions

View file

@ -1,141 +0,0 @@
#include "ExpatParser.h"
#include "osm.h"
#include <string>
using std::cerr;
using std::endl;
osm_item* ExpatParser::cur_item=NULL;
int ExpatParser::curID=0;
bool ExpatParser::in_node=false, ExpatParser::in_way=false;
osm_dataset* ExpatParser::components=NULL;
std::string ExpatParser::error="";
std::map<int,osm_node*> ExpatParser::tmp_node_store = std::map<int,osm_node*>();
void ExpatParser::startElement(void *d,const XML_Char* element,
const XML_Char** attrs)
{
double lat, lon;
int from, to;
std::string tags;
if(!strcmp(element,"node"))
{
curID = 0;
in_node = true;
int count=0;
osm_node *node=new osm_node;
while(attrs[count])
{
if(!strcmp(attrs[count],"lat"))
node->lat = atof(attrs[count+1]);
if(!strcmp(attrs[count],"lon"))
node->lon = atof(attrs[count+1]);
if(!strcmp(attrs[count],"id"))
node->id = atoi(attrs[count+1]);
count+=2;
}
cur_item = node;
tmp_node_store[node->id] = node;
}
else if (!strcmp(element,"way"))
{
curID=0;
in_way = true;
osm_way *way=new osm_way;
for(int count=0; attrs[count]; count+=2)
{
if(!strcmp(attrs[count],"id"))
way->id = atoi(attrs[count+1]);
}
cur_item = way;
}
else if (!strcmp(element,"nd") && (in_way))
{
int ndid;
for(int count=0; attrs[count]; count+=2)
{
if(!strcmp(attrs[count],"ref"))
{
ndid=atoi(attrs[count+1]);
if(tmp_node_store.find(ndid)!=tmp_node_store.end())
{
(static_cast<osm_way*>(cur_item))->nodes.push_back
(tmp_node_store[ndid]);
}
}
}
}
else if (!strcmp(element,"tag"))
{
std::string key="", value="";
for(int count=0; attrs[count]; count+=2)
{
if(!strcmp(attrs[count],"k"))
key = attrs[count+1];
if(!strcmp(attrs[count],"v"))
value = attrs[count+1];
}
cur_item->keyvals[key] = value;
}
}
void ExpatParser::endElement(void *d,const XML_Char* name)
{
if(!strcmp(name,"node"))
{
in_node = false;
components->add_node(static_cast<osm_node*>(cur_item));
}
else if(!strcmp(name,"way"))
{
in_way = false;
components->add_way(static_cast<osm_way*>(cur_item));
}
}
void ExpatParser::characters(void*, const XML_Char* txt,int txtlen)
{
}
bool ExpatParser::parse(osm_dataset *ds, std::istream &in)
{
int done, count=0, n;
char buf[4096];
XML_Parser p = XML_ParserCreate(NULL);
if(!p)
{
error = "Error creating parser";
return false;
}
XML_SetElementHandler(p,ExpatParser::startElement,ExpatParser::endElement);
XML_SetCharacterDataHandler(p,ExpatParser::characters);
components = ds ;
// straight from example
do
{
in.read(buf,4096);
n = in.gcount();
done = (n!=4096);
if(XML_Parse(p,buf,n,done) == XML_STATUS_ERROR)
{
error = "xml parsing error";
return false;
}
count += n;
} while (!done);
XML_ParserFree(p);
return true;
}

View file

@ -1,28 +0,0 @@
#include <expat.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include "osm.h"
#include <map>
class ExpatParser
{
private:
static osm_item *cur_item;
static int curID;
static bool in_node, in_way;
static osm_dataset* components;
static std::string error;
static std::map<int,osm_node*> tmp_node_store;
static void startElement(void *d,const XML_Char* name,
const XML_Char** attrs);
static void endElement(void *d,const XML_Char* name);
static void characters(void*, const XML_Char* txt,int txtlen);
public:
static bool parse(osm_dataset*,std::istream&);
static std::string getError() { return error; }
};

View file

@ -1,110 +0,0 @@
#include <libxml/parser.h>
#include <cstring>
#include <map>
#include "LibxmlParser.h"
#include <iostream>
using namespace std;
void startElement (void *user_state, const xmlChar *name, const xmlChar **attrs)
{
cerr<<"Start element"<<endl;
int count=0;
read_state *state = static_cast<read_state*>(user_state);
std::string cur_key, cur_value;
if(!xmlStrcmp(name,(const xmlChar*)("node")))
{
cerr<<"Found a node"<<endl;
state->in_node=true;
osm_node *node = new osm_node;
if(attrs!=NULL)
{
while(attrs[count]!=NULL)
{
if(!xmlStrcmp(attrs[count],(const xmlChar*)"lat"))
node->lat = atof((const char*)attrs[count+1]);
else if(!xmlStrcmp(attrs[count],
(const xmlChar*)"lon"))
{
node->lon = atof((const char*)attrs[count+1]);
}
else if(!xmlStrcmp
(attrs[count],(const xmlChar*)"id"))
{
node->id = atoi((const char*)attrs[count+1]);
}
count+=2;
}
}
state->cur_osm_item = node;
state->tmp_node_store[node->id] = node;
}
else if (!xmlStrcmp(name,(const xmlChar*)"tag") &&
(state->in_node==true || state->in_way==true) )
{
while(attrs[count]!=NULL)
{
if(!xmlStrcmp(attrs[count],(const xmlChar*)"k"))
cur_key = (const char*) attrs[count+1];
else if(!xmlStrcmp(attrs[count],(const xmlChar*)"v"))
cur_value = (const char*) attrs[count+1];
count+=2;
}
state->cur_osm_item->keyvals[cur_key] = cur_value;
}
else if(!xmlStrcmp(name,(const xmlChar*)"way"))
{
cerr<<"Found a way"<<endl;
state->in_way=true;
osm_way *way = new osm_way;
if(attrs!=NULL)
{
while(attrs[count]!=NULL)
{
if(!xmlStrcmp(attrs[count],(const xmlChar*)"id"))
way->id = atoi((const char*)attrs[count+1]);
count+=2;
}
}
state->cur_osm_item = way;
}
else if(!xmlStrcmp(name,(const xmlChar*)"nd") &&
state->in_way==true)
{
while(attrs[count]!=NULL)
{
if(!xmlStrcmp(attrs[count],(const xmlChar*)"ref"))
{
int id = atoi((const char*)attrs[count+1]);
if(state->tmp_node_store.find(id)!=state->tmp_node_store.end())
{
(static_cast<osm_way*>(state->cur_osm_item))->nodes.
push_back(state->tmp_node_store[id]);
}
}
count+=2;
}
}
}
void endElement (void *user_state, const xmlChar *name)
{
read_state *state = static_cast<read_state*>(user_state);
if(!xmlStrcmp(name,(const xmlChar*)"node"))
{
state->in_node=false;
state->osm_items->add_node(static_cast<osm_node*>
(state->cur_osm_item));
}
if(!xmlStrcmp(name,(const xmlChar*)"way"))
{
state->in_way=false;
state->osm_items->add_way(static_cast<osm_way*>
(state->cur_osm_item));
}
}
void characters (void *user_state, const xmlChar *ch, int len)
{
}

View file

@ -1,21 +0,0 @@
#ifndef XMLPARSE_H
#define XMLPARSE_H
#include <libxml/parser.h>
#include <map>
#include "osm.h"
void startElement (void *user_data, const xmlChar *name, const xmlChar **attrs);
void endElement (void *user_data, const xmlChar *name);
void characters (void *user_data, const xmlChar *ch, int len);
struct read_state
{
bool in_node,
in_way;
osm_item *cur_osm_item;
osm_dataset *osm_items;
std::map<int,osm_node*> tmp_node_store;
} ;
#endif

View file

@ -1,16 +1,9 @@
CXXFLAGS = `xml2-config --cflags` -I/usr/local/include/mapnik -I/usr/include/boost -I/usr/include/freetype2 -I/home/nick/mapnik-osm/agg/include -g
LDFLAGS = `xml2-config --libs` -L/usr/local/lib -lexpat
LDFLAGS2 = -L/usr/local/lib -lexpat `xml2-config --libs`
#LDFLAGS3 = -L/usr/local/lib -lmapnik -lexpat
#LDFLAGS4 = `xml2-config --libs` -L/usr/local/lib -lmapnik
LDFLAGS5 = `xml2-config --libs` -L/usr/local/lib -lmapnik -lexpat
OBJ = test.o LibxmlParser.o osm.o ExpatParser.o
OBJ2 = test2.o ExpatParser.o osm.o
LDFLAGS = `xml2-config --libs` -L/usr/local/lib
LDFLAGS5 = `xml2-config --libs` -L/usr/local/lib -lmapnik
OBJ = test.o osm.o osmparser.o
test: $(OBJ)
g++ -o test $(OBJ) $(LDFLAGS)
test2: $(OBJ2)
g++ -o test2 $(OBJ2) $(LDFLAGS2)
render: render.o
g++ -o render render.o $(LDFLAGS5)

View file

@ -1,4 +1,4 @@
CXXFLAGS = `xml2-config --cflags` -I/usr/local/include/mapnik -I/usr/include/boost -I/usr/include/freetype2 -I/home/nick/mapnik-osm/agg/include -fPIC -g
MAPNIK_OSM_OBJ = ExpatParser.o LibxmlParser.o osm.o osm_datasource.o osm_featureset.o
CXXFLAGS = `xml2-config --cflags` -I/usr/local/include/mapnik -I/usr/include/boost -I/usr/include/freetype2 -fPIC -g
MAPNIK_OSM_OBJ = osmparser.o osm.o osm_datasource.o osm_featureset.o
osm.input: $(MAPNIK_OSM_OBJ)
g++ -shared -o osm.input $(MAPNIK_OSM_OBJ)

View file

@ -1,6 +1,5 @@
#include "osm.h"
#include "LibxmlParser.h"
#include "ExpatParser.h"
#include "osmparser.h"
#include <libxml/parser.h>
#include <iostream>
#include <fstream>
@ -13,36 +12,9 @@ using namespace std;
bool osm_dataset::load(const char* filename,const std::string& parser)
{
if(parser=="libxml2")
if (parser=="libxml2")
{
cerr<<"osm::dataset::load";
xmlSAXHandler my_handler;
cerr<<"memset"<<endl;
memset(&my_handler,0, sizeof(my_handler));
cerr<<"setting up my_handler"<<endl;
my_handler.startElement = startElement;
my_handler.endElement = endElement;
my_handler.characters=characters;
read_state my_state;
my_state.in_node = my_state.in_way = false;
my_state.osm_items = this;
cerr<<"parsing file`"<<endl;
if (xmlSAXUserParseFile(&my_handler, &my_state, filename)<0)
{
std::cerr<<"Error";
return false;
}
return true;
}
else if (parser=="expat")
{
std::ifstream in(filename);
if(!in.good())
return false;
return ExpatParser::parse(this,in);
return osmparser::parse(this,filename);
}
return false;
}

View file

@ -21,7 +21,7 @@ struct bounds
struct osm_item
{
int id;
long id;
std::map<std::string,std::string> keyvals;
virtual std::string to_string();
};

View file

@ -48,7 +48,7 @@ osm_datasource::osm_datasource(const parameters &params)
{
osm_data_ = new osm_dataset;
std::string osm_filename= *params.get<std::string>("file","");
std::string parser = *params.get<std::string>("parser","expat");
std::string parser = *params.get<std::string>("parser","libxml2");
// load the data
if (osm_data_->load(osm_filename.c_str(),parser)==false)
{
@ -86,9 +86,6 @@ featureset_ptr osm_datasource::features(const query& q) const
{
filter_in_box filter(q.get_bbox());
// so we need to filter osm features by bbox here...
std::cout << "Box details" << filter.box_.minx()
<< " " << filter.box_.miny() << " "
<< filter.box_.maxx() <<" " << filter.box_.maxy() << std::endl;
return featureset_ptr
(new osm_featureset<filter_in_box>(filter,

View file

@ -81,9 +81,6 @@ feature_ptr osm_featureset<filterT>::next()
if(cur_item != NULL)
{
std::cout << "Way " << cur_item->id <<
"(" << b.w<<" "<<b.s<<" "<<b.e<<" "<<b.n<<") passes"
<< std::endl;
if(static_cast<osm_way*>(cur_item)->nodes.size())
{
feature=feature_ptr(new Feature(count_++));

View file

@ -0,0 +1,131 @@
// 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*>();
void osmparser::processNode(xmlTextReaderPtr reader)
{
xmlChar *name = xmlTextReaderName(reader);
if(name==NULL)
name=xmlStrdup(BAD_CAST "--");
switch(xmlTextReaderNodeType(reader))
{
case XML_READER_TYPE_ELEMENT:
startElement(reader,name);
break;
case XML_READER_TYPE_END_ELEMENT:
endElement(name);
}
xmlFree(name);
}
void osmparser::startElement(xmlTextReaderPtr reader, const xmlChar *name)
{
double lat, lon;
int from, to;
std::string tags;
xmlChar *xid, *xlat, *xlon, *xk, *xv;
if(xmlStrEqual(name,BAD_CAST "node"))
{
curID = 0;
in_node = true;
int count=0;
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);
}
else if (xmlStrEqual(name,BAD_CAST "way"))
{
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);
}
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);
}
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);
}
}
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));
}
}
bool osmparser::parse(osm_dataset *ds, const char* filename)
{
components=ds;
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename);
int ret=-1;
if(reader!=NULL)
{
ret = xmlTextReaderRead(reader);
while(ret==1)
{
processNode(reader);
ret=xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
}
return (ret==0) ? true:false;
}

View file

@ -0,0 +1,26 @@
#include <libxml/xmlreader.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include "osm.h"
#include <map>
class osmparser
{
private:
static osm_item *cur_item;
static long curID;
static bool in_node, in_way;
static osm_dataset* components;
static std::string error;
static std::map<long,osm_node*> tmp_node_store;
public:
static void processNode(xmlTextReaderPtr reader);
static void startElement(xmlTextReaderPtr reader, const xmlChar *name);
static void endElement(const xmlChar* name);
static bool parse(osm_dataset *ds, const char* filename);
};

View file

@ -25,7 +25,7 @@ int main()
Map m (800,800);
load_map(m,"test.xml");
Envelope<double> bbox (-1.42,50.93,-1.38,50.97);
Envelope<double> bbox (-1.45,50.90,-1.35,51.00);
m.zoomToBox(bbox);

View file

@ -5,25 +5,21 @@ using std::endl;
int main(int argc,char* argv[])
{
osm_dataset dataset(argv[1]);
//std::cout << dataset.to_string() << std::endl;
bounds b = dataset.get_bounds();
cout << b.w << " "<<b.s << " "<< b.e << " " << b.n << endl;
osm_item *item;
dataset.rewind();
/*
while((item=dataset.next_item())!=NULL)
if(argc>=2)
{
std::cerr << item->to_string() << endl;
osm_dataset dataset(argv[1]);
bounds b = dataset.get_bounds();
osm_item *item;
dataset.rewind();
while((item=dataset.next_item())!=NULL)
{
std::cerr << item->to_string() << endl;
}
}
*/
osm_way *way;
while((way=dataset.next_way())!=NULL)
else
{
std::cerr << item->to_string() << endl;
bounds b;
std::cerr << "w=" << b.w << " s=" << b.s << " e="<<b.e << " n="<<b.n
<<endl;
std::cerr<<"Usage: test OSMfile"<<std::endl;
exit(1);
}
return 0;
}

View file

@ -496,7 +496,7 @@
<StyleName>motorway</StyleName>
<Datasource>
<Parameter name="type">osm</Parameter>
<Parameter name="parser">expat</Parameter>
<Parameter name="parser">libxml2</Parameter>
<Parameter name="file">test2.osm</Parameter>
</Datasource>
</Layer>

View file

@ -1,31 +0,0 @@
#include "osm.h"
#include "ExpatParser.h"
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
int main(int argc,char* argv[])
{
osm_dataset dataset;
dataset.load(argv[1],"expat");
bounds b = dataset.get_bounds();
cout << b.w << " "<<b.s << " "<< b.e << " " << b.n << endl;
osm_item *item;
dataset.rewind();
/*
while((item=dataset.next_item())!=NULL)
{
std::cerr << item->to_string() << endl;
}
*/
osm_way *way;
while((way=dataset.next_way())!=NULL)
{
std::cerr << way->to_string() << endl;
bounds b = way->get_bounds();
std::cerr << "w=" << b.w << " s=" << b.s << " e="<<b.e << " n="<<b.n
<<endl;
}
return 0;
}