1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# 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 <http://www.gnu.org/licenses/>.
# 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
|