#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2012 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) 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 General Public License # along with this program. If not, see . # See the file COPYING for details. """ Utilitaries """ import urllib2 from lxml import etree from django.core.exceptions import ObjectDoesNotExist class ImportManager: u""" Generic class for specific importers """ def __init__(self, importer_instance): self.importer_instance = importer_instance def get(self): pass def put(self): pass class KMLManager(ImportManager): u""" KML importer/exporter The filtr argument has to be defined as a correct Xpath string pointing to Placemark nodes. A typical XPath string looks like: "//kml:Folder/kml:name[text()='Subcategory 1']/../kml:Placemark" """ def __init__(self, importer_instance, ns=''): self.importer_instance = importer_instance self.ns = ns def get(self): u""" Get data from the source Return a tuple with: - number of new item ; - number of item updated ; - error detail on error """ from models import Marker new_item, updated_item, msg = 0, 0, '' try: source = urllib2.urlopen(self.importer_instance.source_url) except ValueError: # assume it is a local file try: source = open(self.importer_instance.source_url) except IOError, msg: return (new_item, updated_item, msg) except urllib2.URLError as error: return (new_item, updated_item, error.reason) tree = etree.parse(source) # try to get default namespace if not self.ns: self.ns = tree.getroot().nsmap[None] for placemark in tree.xpath(self.importer_instance.filtr, namespaces={'kml':self.ns}): name, point, linestring = None, None, None pl_id = placemark.attrib.get('id') ns = '{%s}' % self.ns for item in placemark: if item.tag == ns + 'name': name = item.text elif item.tag == ns + 'description': description = item.text elif item.tag == ns + 'Point': for coord in item: if coord.tag == ns + 'coordinates': x, y, z = coord.text.split(',') point = 'SRID=4326;POINT(%s %s)' % (x, y) if point: dct = {'point':point, 'description':description, 'name':name,} m = None if pl_id: dct_import = { 'import_key':pl_id, 'import_source':self.importer_instance.source_url} try: m = Marker.objects.get(**dct_import) for k in dct: setattr(m, k, dct[k]) m.save() updated_item += 1 except ObjectDoesNotExist: m = None dct.update(dct_import) if not m: dct['status'] = 'I' m = Marker.objects.create(**dct) new_item += 1 m.categories.clear() for cat in self.importer_instance.categories.all(): m.categories.add(cat) return (new_item, updated_item, msg) class OSMManager(ImportManager): pass