/[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 706 - (hide annotations)
Wed Apr 23 08:44:21 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/load.py
File MIME type: text/x-python
File size: 12328 byte(s)
(XMLReader): Renamed from XMLProcessor to
        promote symmetry. There now exists XMLReader and XMLWriter.
(XMLReader.read): New. Call to read the given file descriptor or
        filename.
(XMLReader.close): New. Make sure the file is closed.
(XMLReader.GetFileName): New. Return just the file name that is being read from.
(XMLReader.GetDirectory): New. Return just the directory of the file
        that is being read.
(XMLReader.AddDispatchers): New. Take a dictionary which contains
        the names of functions to call as the XML tree is parsed.
(XMLReader.startElementNS): Updated to use new dispatcher dictionary.
(XMLReader.endElementNS): Updated to use new dispatcher dictionary.
(SessionLoader): Removed class variables start_dispatcher and
        end_dispatcher since this functionality is now part of a class
        instance. Fixes RTbug #1808.
(SessionLoader.__init__): Add dispatcher functions.
(load_xmlfile): Code was moved into the XMLReader.read().
(load_session): Use modified SessionLoader.

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 jonathan 526 from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
21 bh 267
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 610 result = Color.Transparent
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 jonathan 706 class XMLReader(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 jonathan 706 def __init__(self):
78 bh 6 self.chars = ''
79 jonathan 706 self.__parser = None
80     self.__directory = ""
81     self.__dispatchers = {}
82 bh 6
83 jonathan 706 def read(self, file_or_filename):
84    
85     if hasattr(file_or_filename, "write"):
86     # it's a file object
87     self.__directory = ""
88     self.__file = file_or_filename
89     else:
90     filename = file_or_filename
91     self.__directory = os.path.dirname(filename)
92     self.__file = open(filename)
93    
94     if self.__parser is None:
95     self.__parser = make_parser()
96     self.__parser.setContentHandler(self)
97     self.__parser.setErrorHandler(ErrorHandler())
98     self.__parser.setFeature(xml.sax.handler.feature_namespaces, 1)
99    
100     #
101     # Well, this isn't pretty, but it appears that if you
102     # use Python 2.2 without the site-package _xmlplus then
103     # the following will fail, and without them it will work.
104     # However, if you do have the site-package and you don't
105     # call these functions, the reader raises an exception
106     #
107     # The reason we set these to 0 in the first place is
108     # because there is an unresolved issue with external
109     # entities causing an exception in the reader
110     #
111     try:
112     self.__parser.setFeature(xml.sax.handler.feature_validation,0)
113     self.__parser.setFeature(xml.sax.handler.feature_external_ges,0)
114     self.__parser.setFeature(xml.sax.handler.feature_external_pes,0)
115     except SAXNotRecognizedException:
116     pass
117    
118     self.__parser.parse(self.__file)
119    
120     self.close()
121    
122     def close(self):
123     self.__file.close()
124    
125     def GetFileName(self):
126     if hasattr(self.__file, "name"):
127     return self.__file.name
128    
129     return ""
130    
131     def GetDirectory(self):
132     return self.__directory
133    
134    
135     def AddDispatchers(self, dict):
136     self.__dispatchers.update(dict)
137    
138     #for key, (start, end) in dict.iteritems():
139     #if start is not None: self.start_dispatcher[key] = start
140     #if end is not None: self.end_dispatcher[key] = end
141    
142 bh 267 def startElementNS(self, name, qname, attrs):
143     """Call the method given for name in self.start_dispatcher
144     """
145     if name[0] is None:
146 jonathan 706 method_name = self.__dispatchers.get(name[1])
147     #method_name = self.start_dispatcher.get(name[1])
148 bh 267 else:
149     # Dispatch with namespace
150 jonathan 706 method_name = self.__dispatchers.get(name)
151     if method_name is not None \
152     and method_name[0] is not None:
153     getattr(self, method_name[0])(name, qname, attrs)
154 bh 6
155 bh 267 def endElementNS(self, name, qname):
156     """Call the method given for name in self.end_dispatcher
157     """
158     if name[0] is None:
159 jonathan 706 method_name = self.__dispatchers.get(name[1])
160     #method_name = self.end_dispatcher.get(name[1])
161 bh 267 else:
162     # Dispatch with namespace
163 jonathan 706 method_name = self.__dispatchers.get(name)
164     if method_name is not None \
165     and method_name[1] is not None:
166     getattr(self, method_name[1])(name, qname)
167 bh 6
168 jonathan 706 class SessionLoader(XMLReader):
169 jonathan 694
170 jonathan 706 def __init__(self):
171 jonathan 694 """Inititialize the Sax handler."""
172 jonathan 706 XMLReader.__init__(self)
173 jonathan 694
174     self.theSession = None
175     self.aMap = None
176     self.aLayer = None
177    
178 jonathan 706 XMLReader.AddDispatchers(self,
179     {'session' : ("start_session", "end_session"),
180     'map' : ("start_map", "end_map"),
181     'projection' : ("start_projection", "end_projection"),
182     'parameter' : ("start_parameter", None),
183     'layer' : ("start_layer", "end_layer"),
184     'classification': ("start_classification", "end_classification"),
185     'clnull' : ("start_clnull", "end_clnull"),
186     'clpoint' : ("start_clpoint", "end_clpoint"),
187     'clrange' : ("start_clrange", "end_clrange"),
188     'cldata' : ("start_cldata", "end_cldata"),
189     'table' : ("start_table", "end_table"),
190     'labellayer' : ("start_labellayer", None),
191     'label' : ("start_label", None)})
192    
193 bh 267 def start_session(self, name, qname, attrs):
194     self.theSession = Session(attrs.get((None, 'title'), None))
195 bh 6
196 bh 267 def end_session(self, name, qname):
197     pass
198 bh 6
199 bh 267 def start_map(self, name, qname, attrs):
200     """Start a map."""
201     self.aMap = Map(attrs.get((None, 'title'), None))
202    
203     def end_map(self, name, qname):
204     self.theSession.AddMap(self.aMap)
205    
206     def start_projection(self, name, qname, attrs):
207     self.ProjectionParams = [ ]
208    
209     def end_projection(self, name, qname):
210     self.aMap.SetProjection(Projection(self.ProjectionParams))
211    
212     def start_parameter(self, name, qname, attrs):
213     s = attrs.get((None, 'value'))
214     s = str(s) # we can't handle unicode in proj
215     self.ProjectionParams.append(s)
216    
217     def start_layer(self, name, qname, attrs, layer_class = Layer):
218     """Start a layer
219    
220     Instantiate a layer of class layer_class from the attributes in
221     attrs which may be a dictionary as well as the normal SAX attrs
222     object and bind it to self.aLayer.
223     """
224     title = attrs.get((None, 'title'), "")
225     filename = attrs.get((None, 'filename'), "")
226 jonathan 694 filename = os.path.join(self.GetDirectory(), filename)
227 bh 267 fill = parse_color(attrs.get((None, 'fill'), "None"))
228     stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
229     stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
230     self.aLayer = layer_class(title, filename, fill = fill,
231 jonathan 465 stroke = stroke, lineWidth = stroke_width)
232 bh 267
233     def end_layer(self, name, qname):
234     self.aMap.AddLayer(self.aLayer)
235    
236 jonathan 365 def start_classification(self, name, qname, attrs):
237 jonathan 465 field = attrs.get((None, 'field'), None)
238    
239     fieldType = attrs.get((None, 'field_type'), None)
240     dbFieldType = self.aLayer.GetFieldType(field)
241    
242     if fieldType != dbFieldType:
243     raise ValueError(_("xml field type differs from database!"))
244    
245     # setup conversion routines depending on the kind of data
246     # we will be seeing later on
247     if fieldType == FIELDTYPE_STRING:
248     self.conv = str
249     elif fieldType == FIELDTYPE_INT:
250     self.conv = lambda p: int(float(p))
251     elif fieldType == FIELDTYPE_DOUBLE:
252     self.conv = float
253    
254     self.aLayer.GetClassification().SetField(field)
255    
256 jonathan 365
257     def end_classification(self, name, qname):
258     pass
259    
260     def start_clnull(self, name, qname, attrs):
261 jonathan 439 self.cl_group = ClassGroupDefault()
262     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
263     self.cl_prop = ClassGroupProperties()
264 jonathan 365
265     def end_clnull(self, name, qname):
266 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
267     self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
268     del self.cl_group, self.cl_prop
269 jonathan 365
270     def start_clpoint(self, name, qname, attrs):
271     attrib_value = attrs.get((None, 'value'), "0")
272    
273 jonathan 465 #try:
274     #value = Str2Num(attrib_value)
275     #except:
276     #value = attrib_value
277 jonathan 365
278 jonathan 465 value = self.conv(attrib_value)
279    
280 jonathan 439 self.cl_group = ClassGroupSingleton(value)
281     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
282     self.cl_prop = ClassGroupProperties()
283 jonathan 413
284 jonathan 365
285     def end_clpoint(self, name, qname):
286 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
287 jonathan 614 self.aLayer.GetClassification().AppendGroup(self.cl_group)
288 jonathan 439 del self.cl_group, self.cl_prop
289 jonathan 365
290     def start_clrange(self, name, qname, attrs):
291    
292     try:
293 jonathan 465 min = self.conv(attrs.get((None, 'min'), "0"))
294     max = self.conv(attrs.get((None, 'max'), "0"))
295     #min = Str2Num(attrs.get((None, 'min'), "0"))
296     #max = Str2Num(attrs.get((None, 'max'), "0"))
297 jonathan 365 except ValueError:
298 jan 374 raise ValueError(_("Classification range is not a number!"))
299 jonathan 365
300 jonathan 439 self.cl_group = ClassGroupRange(min, max)
301     self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
302     self.cl_prop = ClassGroupProperties()
303 jonathan 413
304 jonathan 365
305     def end_clrange(self, name, qname):
306 jonathan 439 self.cl_group.SetProperties(self.cl_prop)
307 jonathan 614 self.aLayer.GetClassification().AppendGroup(self.cl_group)
308 jonathan 439 del self.cl_group, self.cl_prop
309 jonathan 365
310     def start_cldata(self, name, qname, attrs):
311 jonathan 465 self.cl_prop.SetLineColor(
312     parse_color(attrs.get((None, 'stroke'), "None")))
313     self.cl_prop.SetLineWidth(
314 jonathan 390 int(attrs.get((None, 'stroke_width'), "0")))
315 jonathan 439 self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
316 jonathan 365
317     def end_cldata(self, name, qname):
318     pass
319    
320 bh 267 def start_table(self, name, qname, attrs):
321 jonathan 493 #print "table title: %s" % attrs.get('title', None)
322     pass
323 bh 267
324     def end_table(self, name, qname):
325     pass
326    
327     def start_labellayer(self, name, qname, attrs):
328     self.aLayer = self.aMap.LabelLayer()
329    
330     def start_label(self, name, qname, attrs):
331     x = float(attrs[(None, 'x')])
332     y = float(attrs[(None, 'y')])
333     text = attrs[(None, 'text')]
334     halign = attrs[(None, 'halign')]
335     valign = attrs[(None, 'valign')]
336     self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
337    
338     def characters(self, chars):
339     pass
340    
341    
342 jonathan 694 def load_session(filename):
343     """Load a Thuban session from the file object file"""
344    
345 jonathan 706 handler = SessionLoader()
346     handler.read(filename)
347 jonathan 694
348 bh 6 session = handler.theSession
349     # Newly loaded session aren't modified
350     session.UnsetModified()
351    
352     return session
353    

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26