/[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 694 - (hide annotations)
Wed Apr 16 16:39:18 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: 11806 byte(s)
(XMLProcessor): New. Contains all the general XML reading methods that
        were part of ProcessSession.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26