-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathcascadenik-extract-dscfg.py
194 lines (153 loc) · 6.16 KB
/
cascadenik-extract-dscfg.py
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/env python
import os, sys
import math
import pprint
import urllib
import urlparse
import tempfile
import StringIO
import os.path
import zipfile
import itertools
import re
import ConfigParser
import codecs
import optparse
# Solves nasty problems:
# http://bytes.com/topic/python/answers/40109-missing-sys-setappdefaultencoding
reload(sys)
sys.setdefaultencoding('utf-8')
try:
import lxml.etree as ElementTree
from lxml.etree import Element, tostring
except ImportError:
try:
import xml.etree.ElementTree as ElementTree
from xml.etree.ElementTree import Element, tostring
except ImportError:
import elementtree.ElementTree as ElementTree
from elementtree.ElementTree import Element, tostring
standard_projections = {
'srs900913' : '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs',
'srsMerc' : '+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs',
'srs4326' : '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
}
def add_source(sources, ds_name, params):
if ds_name not in sources:
sources[ds_name] = params
return ds_name
op = sources[ds_name]
c = 0
while True:
for k,v in op.items():
# dicts are unequal
if k not in params or op[k] != params[k]:
c += 1
nds_name = "%s_%d" % (ds_name, c)
if nds_name in sources:
op = sources[nds_name]
break
sources[nds_name] = params
return nds_name
else: # equal, return!
return ds_name
#
class MyConfigParser(ConfigParser.RawConfigParser):
def write(self, fp):
"""Write an .ini-format representation of the configuration state."""
if self._defaults:
fp.write("[%s]\n" % ConfigParser.DEFAULTSECT)
for (key, value) in sorted(self._defaults.items(), key=lambda x: x[0]):
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
fp.write("\n")
for section in sorted(self._sections):
fp.write("[%s]\n" % section)
for (key, value) in sorted(self._sections[section].items(), key=lambda x: x[0]):
if key != "__name__":
fp.write("%s = %s\n" %
(key, str(value).replace('\n', '\n\t')))
fp.write("\n")
def convert(src, outmml, outconfig, opts):
if os.path.exists(src): # local file
# using 'file:' enables support on win32
# for opening local files with urllib.urlopen
# Note: this must only be used with abs paths to local files
# otherwise urllib will think they are absolute,
# therefore in the future it will likely be
# wiser to just open local files with open()
if os.path.isabs(src) and sys.platform == "win32":
src = 'file:%s' % src
doc = ElementTree.parse(urllib.urlopen(src))
map = doc.getroot()
defaults = standard_projections
sources = {}
all_srs = dict([(v,k) for k,v in standard_projections.items()])
name_filter = re.compile("\W")
for layer in map.findall("Layer"):
if not opts.extract_all and layer.attrib.get('status',"on").lower() == "off":
map.remove(layer)
continue
srs = layer.attrib['srs']
srs_name = all_srs.get(srs)
if not srs_name:
srs_name = "srs%d"%len(all_srs)
defaults[srs_name] = srs
all_srs[srs] = srs_name
id = layer.attrib.get('id')
classes = layer.attrib.get('class')
keys = []
if id:
keys.append("%s_" % id)
if classes:
keys.extend(classes.split(" "))
ds_name = name_filter.sub("_", " ".join(keys))
params = {}
for param in layer.find("Datasource").findall("Parameter"):
params[param.attrib['name']] = param.text
params.update(layer.find("Datasource").attrib)
params['layer_srs'] = "%%(%s)s" % srs_name
ds_name = add_source(sources, ds_name, params)
layer.attrib['source_name'] = ds_name
del layer.attrib['srs']
layer.remove(layer.find("Datasource"))
# now generate unique bases
g_params = {}
for name, params in sources.items():
gp = {}
name_base = None
if params.get('type') == 'postgis':
param_set = ("port","host","user","layer_srs","password","type","dbname","estimate_extent","extent")
name_base = "postgis_conn_%d"
# elif params.get('type') == 'shape':
# param_set = ("type","file","source_srs")
# name_base = "shapefile_%d"
else:
continue
for p in param_set:
if p in params:
gp[p] = params[p]
del params[p]
gp_name,gp_data = g_params.get(repr(gp),(None,None))
if not gp_name:
gp_name = name_base % len(g_params)
g_params[repr(gp)] = gp_name,gp
params['template'] = gp_name
config = MyConfigParser(defaults)
for name,params in itertools.chain(g_params.values(), sources.items()):
config.add_section(name)
for pn,pv in params.items():
if pn == 'table': pv = pv.strip()
config.set(name,pn,pv)
with codecs.open(outconfig,"w","utf-8") as oc:
config.write(oc)
map.insert(0,Element("DataSourcesConfig", src=outconfig))
doc.write(outmml, encoding="utf8")
if __name__ == "__main__":
parser = optparse.OptionParser(usage= "usage: %s [options] <source.mml> <output.mml> <output.cfg>" % sys.argv[0])
parser.add_option('-a', '--all', dest='extract_all', default=False, action="store_true",
help='Include disabled layers')
(options, args) = parser.parse_args()
if len(args) != 3:
parser.error("Please specify <source.mml> <output.mml> <output.cfg>")
inmml, outmml, outcfg = args
convert(inmml, outmml, outcfg, options)