/* open source routing machine Copyright (C) Dennis Luxen, others 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by the Free Software Foundation; either version 3 of the License, or any later version. This program 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 General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ #include "XMLParser.h" #include "ExtractorStructs.h" #include "../DataStructures/HashTable.h" #include "../DataStructures/InputReaderFactory.h" #include XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) { WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); inputReader = inputReaderFactory(filename); } bool XMLParser::ReadHeader() { return (xmlTextReaderRead( inputReader ) == 1); } bool XMLParser::Parse() { while ( xmlTextReaderRead( inputReader ) == 1 ) { const int type = xmlTextReaderNodeType( inputReader ); //1 is Element if ( type != 1 ) { continue; } xmlChar* currentName = xmlTextReaderName( inputReader ); if ( currentName == NULL ) { continue; } if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { ImportNode n = _ReadXMLNode(); ParseNodeInLua( n, luaState ); extractor_callbacks->nodeFunction(n); // if(!extractor_callbacks->nodeFunction(n)) // std::cerr << "[XMLParser] dense node not parsed" << std::endl; } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { ExtractionWay way = _ReadXMLWay( ); ParseWayInLua( way, luaState ); extractor_callbacks->wayFunction(way); // if(!extractor_callbacks->wayFunction(way)) // std::cerr << "[PBFParser] way not parsed" << std::endl; } if( use_turn_restrictions ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { _RawRestrictionContainer r = _ReadXMLRestriction(); if(r.fromWay != UINT_MAX) { if(!extractor_callbacks->restrictionFunction(r)) { std::cerr << "[XMLParser] restriction not parsed" << std::endl; } } } } xmlFree( currentName ); } return true; } _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { _RawRestrictionContainer restriction; std::string except_tag_string; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); if ( childType != 1 && childType != 15 ) { continue; } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); if ( childName == NULL ) { continue; } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { xmlFree( childName ); break; } if ( childType != 1 ) { xmlFree( childName ); continue; } if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); if ( k != NULL && value != NULL ) { if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ if(0 == std::string((const char *) value).find("only_")) { restriction.restriction.flags.isOnly = true; } } if ( xmlStrEqual(k, (const xmlChar *) "except") ) { except_tag_string = (const char*) value; } } if ( k != NULL ) { xmlFree( k ); } if ( value != NULL ) { xmlFree( value ); } } else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); if ( ref != NULL ) { xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { restriction.toWay = stringToUint((const char*) ref); } if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { restriction.fromWay = stringToUint((const char*) ref); } if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { restriction.restriction.viaNode = stringToUint((const char*) ref); } if(NULL != type) { xmlFree( type ); } if(NULL != role) { xmlFree( role ); } if(NULL != ref) { xmlFree( ref ); } } } xmlFree( childName ); } } if( ShouldIgnoreRestriction(except_tag_string) ) { restriction.fromWay = UINT_MAX; //workaround to ignore the restriction } return restriction; } ExtractionWay XMLParser::_ReadXMLWay() { ExtractionWay way; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); if ( childType != 1 && childType != 15 ) { continue; } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); if ( childName == NULL ) { continue; } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); way.id = stringToUint((char*)id); xmlFree(id); xmlFree( childName ); break; } if ( childType != 1 ) { xmlFree( childName ); continue; } if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); // cout << "->k=" << k << ", v=" << value << endl; if ( k != NULL && value != NULL ) { way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); } if ( k != NULL ) { xmlFree( k ); } if ( value != NULL ) { xmlFree( value ); } } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); if ( ref != NULL ) { way.path.push_back( stringToUint(( const char* ) ref ) ); xmlFree( ref ); } } xmlFree( childName ); } } return way; } ImportNode XMLParser::_ReadXMLNode() { ImportNode node; xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); if ( attribute != NULL ) { node.lat = static_cast(COORDINATE_PRECISION*atof(( const char* ) attribute ) ); xmlFree( attribute ); } attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); if ( attribute != NULL ) { node.lon = static_cast(COORDINATE_PRECISION*atof(( const char* ) attribute )); xmlFree( attribute ); } attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); if ( attribute != NULL ) { node.id = stringToUint(( const char* ) attribute ); xmlFree( attribute ); } if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { const int childType = xmlTextReaderNodeType( inputReader ); // 1 = Element, 15 = EndElement if ( childType != 1 && childType != 15 ) { continue; } const int childDepth = xmlTextReaderDepth( inputReader ); xmlChar* childName = xmlTextReaderName( inputReader ); if ( childName == NULL ) { continue; } if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { xmlFree( childName ); break; } if ( childType != 1 ) { xmlFree( childName ); continue; } if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); if ( k != NULL && value != NULL ) { node.keyVals.Add(std::string( reinterpret_cast(k) ), std::string( reinterpret_cast(value))); } if ( k != NULL ) { xmlFree( k ); } if ( value != NULL ) { xmlFree( value ); } } xmlFree( childName ); } } return node; }