/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/load.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/Model/load.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 525 - (hide annotations)
Wed Mar 12 19:12:30 2003 UTC (21 years, 11 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/load.py
File MIME type: text/x-python
File size: 10993 byte(s)
Testing fix for xml reader exceptions.

1 bh 75 # Copyright (C) 2001, 2002 by Intevation GmbH
2 bh 6 # Authors:
3     # Jan-Oliver Wagner <[email protected]>
4 bh 267 # Bernhard Herzog <[email protected]>
5 jonathan 413 # Jonathan Coles <[email protected]>
6 bh 6 #
7     # This program is free software under the GPL (>=v2)
8     # Read the file COPYING coming with GRASS for details.
9    
10     """
11     Parser for thuban session files.
12     """
13    
14     __version__ = "$Revision$"
15    
16     import sys, string, os
17 bh 267
18     import xml.sax
19     import xml.sax.handler
20     from xml.sax import make_parser, ErrorHandler
21    
22 jan 374 from Thuban import _
23 jonathan 413 from Thuban.common import *
24    
25 jonathan 473 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
26     FIELDTYPE_STRING
27    
28 bh 6 from Thuban.Model.session import Session
29     from Thuban.Model.map import Map
30     from Thuban.Model.layer import Layer
31     from Thuban.Model.color import Color
32     from Thuban.Model.proj import Projection
33 jonathan 413 from Thuban.Model.classification import Classification, \
34 jonathan 439 ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
35     ClassGroupProperties
36 bh 6
37    
38 bh 267 def parse_color(color):
39     """Return the color object for the string color.
40 bh 6
41 bh 267 Color may be either 'None' or of the form '#RRGGBB' in the usual
42     HTML color notation
43 bh 6 """
44     color = string.strip(color)
45     if color == "None":
46 jonathan 413 result = Color.None
47 bh 6 elif color[0] == '#':
48     if len(color) == 7:
49     r = string.atoi(color[1:3], 16) / 255.0
50     g = string.atoi(color[3:5], 16) / 255.0
51     b = string.atoi(color[5:7], 16) / 255.0
52     result = Color(r, g, b)
53     else:
54 jan 374 raise ValueError(_("Invalid hexadecimal color specification %s")
55 bh 6 % color)
56     else:
57 jan 374 raise ValueError(_("Invalid color specification %s") % color)
58 bh 6 return result
59    
60    
61 bh 267 class ProcessSession(xml.sax.handler.ContentHandler):
62 bh 6
63 bh 267 # Dictionary mapping element names (or (URI, element name) pairs for
64 jonathan 365 # documents using namespaces) to method names. The methods should
65 bh 267 # accept the same parameters as the startElement (or startElementNS)
66     # methods. The start_dispatcher is used by the default startElement
67     # and startElementNS methods to call a method for the open tag of an
68     # element.
69     start_dispatcher = {}
70    
71     # end_dispatcher works just like start_dispatcher but it's used by
72     # endElement and endElementNS. The method whose names it maps to
73     # should accept the same parameters as endElement and endElementNS.
74     end_dispatcher = {}
75    
76    
77 bh 6 def __init__(self, directory):
78     """Inititialize the Sax handler.
79    
80 bh 267 The directory parameter should be the directory containing the
81     session file. It's needed to interpret embedded relative
82     filenames.
83 bh 6 """
84     self.directory = directory
85     self.chars = ''
86     self.theSession = None
87     self.aMap = None
88     self.aLayer = None
89    
90 bh 267 def startElementNS(self, name, qname, attrs):
91     """Call the method given for name in self.start_dispatcher
92     """
93     if name[0] is None:
94     method_name = self.start_dispatcher.get(name[1])
95     else:
96     # Dispatch with namespace
97     method_name = self.start_dispatcher.get(name)
98     if method_name is not None:
99     getattr(self, method_name)(name, qname, attrs)
100 bh 6
101 bh 267 def endElementNS(self, name, qname):
102     """Call the method given for name in self.end_dispatcher
103     """
104     if name[0] is None:
105     method_name = self.end_dispatcher.get(name[1])
106     else:
107     # Dispatch with namespace
108     method_name = self.end_dispatcher.get(name)
109     if method_name is not None:
110     getattr(self, method_name)(name, qname)
111 bh 6
112 bh 267 def start_session(self, name, qname, attrs):
113     self.theSession = Session(attrs.get((None, 'title'), None))
114     start_dispatcher['session'] = "start_session"
115 bh 6
116 bh 267 def end_session(self, name, qname):
117     pass
118     end_dispatcher['session'] = "end_session"
119 bh 6
120 bh 267 def start_map(self, name, qname, attrs):
121     """Start a map."""
122     self.aMap = Map(attrs.get((None, 'title'), None))
123     start_dispatcher['map'] = "start_map"
124    
125     def end_map(self, name, qname):
126     self.theSession.AddMap(self.aMap)
127     end_dispatcher['map'] = "end_map"
128    
129     def start_projection(self, name, qname, attrs):
130     self.ProjectionParams = [ ]
131     start_dispatcher['projection'] = "start_projection"
132    
133     def end_projection(self, name, qname):
134     self.aMap.SetProjection(Projection(self.ProjectionParams))
135     end_dispatcher['projection'] = "end_projection"
136    
137     def start_parameter(self, name, qname, attrs):
138     s = attrs.get((None, 'value'))
139     s = str(s) # we can't handle unicode in proj
140     self.ProjectionParams.append(s)
141     start_dispatcher['parameter'] = "start_parameter"
142    
143     def start_layer(self, name, qname, attrs, layer_class = Layer):
144     """Start a layer
145    
146     Instantiate a layer of class layer_class from the attributes in
147     attrs which may be a dictionary as well as the normal SAX attrs
148     object and bind it to self.aLayer.
149     """
150     title = attrs.get((None, 'title'), "")
151     filename = attrs.get((None, 'filename'), "")
152     filename = os.path.join(self.directory, filename)
153     fill = parse_color(attrs.get((None, 'fill'), "None"))
154     stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
155     stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
156     self.aLayer = layer_class(title, filename, fill = fill,
157 jonathan 465 stroke = stroke, lineWidth = stroke_width)
158 bh 267 start_dispatcher['layer'] = "start_layer"
159    
160     def end_layer(self, name, qname):
161     self.aMap.AddLayer(self.aLayer)
162     end_dispatcher['layer'] = "end_layer"
163    
164 jonathan 365 def start_classification(self, name, qname, attrs):
165 jonathan 465 field = attrs.get((None, 'field'), None)
166    
167     fieldType = attrs.get((None, 'field_type'), None)
168     dbFieldType = self.aLayer.GetFieldType(field)
169    
170     if fieldType != dbFieldType:
171     raise ValueError(_("xml field type differs from database!"))
172    
173     # setup conversion routines depending on the kind of data
174     # we will be seeing later on
175     if fieldType == FIELDTYPE_STRING:
176     self.conv = str
177     elif fieldType == FIELDTYPE_INT:
178     self.conv = lambda p: int(float(p))
179     elif fieldType == FIELDTYPE_DOUBLE:
180     self.conv = float
181    
182     self.aLayer.GetClassification().SetField(field)
183    
184 jonathan 365 start_dispatcher['classification'] = "start_classification"
185    
186     def end_classification(self, name, qname):
187     pass
188     end_dispatcher['classification'] = "end_classification"
189    
190     def start_clnull(self, name, qname, attrs):
191 jonathan 439 self.cl_group = ClassGroupDefault()
192     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
193     self.cl_prop = ClassGroupProperties()
194 jonathan 365 start_dispatcher['clnull'] = "start_clnull"
195    
196     def end_clnull(self, name, qname):
197 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
198     self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
199     del self.cl_group, self.cl_prop
200 jonathan 365 end_dispatcher['clnull'] = "end_clnull"
201    
202     def start_clpoint(self, name, qname, attrs):
203     attrib_value = attrs.get((None, 'value'), "0")
204    
205 jonathan 465 #try:
206     #value = Str2Num(attrib_value)
207     #except:
208     #value = attrib_value
209 jonathan 365
210 jonathan 465 value = self.conv(attrib_value)
211    
212 jonathan 439 self.cl_group = ClassGroupSingleton(value)
213     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
214     self.cl_prop = ClassGroupProperties()
215 jonathan 413
216 jonathan 365 start_dispatcher['clpoint'] = "start_clpoint"
217    
218     def end_clpoint(self, name, qname):
219 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
220     self.aLayer.GetClassification().AddGroup(self.cl_group)
221     del self.cl_group, self.cl_prop
222 jonathan 365 end_dispatcher['clpoint'] = "end_clpoint"
223    
224     def start_clrange(self, name, qname, attrs):
225    
226     try:
227 jonathan 465 min = self.conv(attrs.get((None, 'min'), "0"))
228     max = self.conv(attrs.get((None, 'max'), "0"))
229     #min = Str2Num(attrs.get((None, 'min'), "0"))
230     #max = Str2Num(attrs.get((None, 'max'), "0"))
231 jonathan 365 except ValueError:
232 jan 374 raise ValueError(_("Classification range is not a number!"))
233 jonathan 365
234 jonathan 439 self.cl_group = ClassGroupRange(min, max)
235     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
236     self.cl_prop = ClassGroupProperties()
237 jonathan 413
238 jonathan 365 start_dispatcher['clrange'] = "start_clrange"
239    
240     def end_clrange(self, name, qname):
241 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
242     self.aLayer.GetClassification().AddGroup(self.cl_group)
243     del self.cl_group, self.cl_prop
244 jonathan 365 end_dispatcher['clrange'] = "end_clrange"
245    
246     def start_cldata(self, name, qname, attrs):
247 jonathan 465 self.cl_prop.SetLineColor(
248     parse_color(attrs.get((None, 'stroke'), "None")))
249     self.cl_prop.SetLineWidth(
250 jonathan 390 int(attrs.get((None, 'stroke_width'), "0")))
251 jonathan 439 self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
252 jonathan 365 start_dispatcher['cldata'] = "start_cldata"
253    
254     def end_cldata(self, name, qname):
255     pass
256     end_dispatcher['cldata'] = "end_cldata"
257    
258 bh 267 def start_table(self, name, qname, attrs):
259 jonathan 493 #print "table title: %s" % attrs.get('title', None)
260     pass
261 bh 267 start_dispatcher['table'] = "start_table"
262    
263     def end_table(self, name, qname):
264     pass
265     end_dispatcher['table'] = "end_table"
266    
267     def start_labellayer(self, name, qname, attrs):
268     self.aLayer = self.aMap.LabelLayer()
269     start_dispatcher['labellayer'] = "start_labellayer"
270    
271     def start_label(self, name, qname, attrs):
272     x = float(attrs[(None, 'x')])
273     y = float(attrs[(None, 'y')])
274     text = attrs[(None, 'text')]
275     halign = attrs[(None, 'halign')]
276     valign = attrs[(None, 'valign')]
277     self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
278     start_dispatcher['label'] = "start_label"
279    
280     def characters(self, chars):
281     pass
282    
283    
284 bh 6 def load_session(filename):
285     """Load a Thuban session from the file object file"""
286     dir = os.path.dirname(filename)
287     file = open(filename)
288     handler = ProcessSession(dir)
289    
290 bh 267 parser = make_parser()
291     parser.setContentHandler(handler)
292     parser.setErrorHandler(ErrorHandler())
293     parser.setFeature(xml.sax.handler.feature_namespaces, 1)
294 jonathan 525
295     #
296     # Well, this isn't pretty, but it appears that if you
297     # use Python 2.2 without the site-package _xmlplus then
298     # the following will fail, and without them it will work.
299     # However, if you do have the site-package and you don't
300     # call these functions, the reader raises an exception
301     #
302     try:
303     parser.setFeature(xml.sax.handler.feature_validation, 0)
304     parser.setFeature(xml.sax.handler.feature_external_ges, 0)
305     parser.setFeature(xml.sax.handler.feature_external_pes, 0)
306     except SAXNotRecognizedException:
307     pass
308    
309 bh 267 parser.parse(file)
310    
311 bh 6 session = handler.theSession
312     # Newly loaded session aren't modified
313     session.UnsetModified()
314    
315     return session
316    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26