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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 374 by jan, Mon Jan 27 14:20:02 2003 UTC revision 784 by jonathan, Tue Apr 29 17:30:18 2003 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001, 2002 by Intevation GmbH  # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
5    # Jonathan Coles <[email protected]>
6  #  #
7  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
8  # Read the file COPYING coming with GRASS for details.  # Read the file COPYING coming with GRASS for details.
# Line 12  Parser for thuban session files. Line 13  Parser for thuban session files.
13    
14  __version__ = "$Revision$"  __version__ = "$Revision$"
15    
16  import sys, string, os  import string, os
17    
18  import xml.sax  import xml.sax
19  import xml.sax.handler  import xml.sax.handler
20  from xml.sax import make_parser, ErrorHandler  from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
21    
22  from Thuban import _  from Thuban import _
23    
24    from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
25         FIELDTYPE_STRING
26    
27  from Thuban.Model.session import Session  from Thuban.Model.session import Session
28  from Thuban.Model.map import Map  from Thuban.Model.map import Map
29  from Thuban.Model.layer import Layer  from Thuban.Model.layer import Layer
30  from Thuban.Model.color import Color  from Thuban.Model.color import Color
31  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
32  from Thuban.Model.classification import Classification  from Thuban.Model.classification import Classification, \
33        ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
34        ClassGroupProperties
35    
36    
37  def parse_color(color):  def parse_color(color):
# Line 35  def parse_color(color): Line 42  def parse_color(color):
42      """      """
43      color = string.strip(color)      color = string.strip(color)
44      if color == "None":      if color == "None":
45          result = None          result = Color.Transparent
46      elif color[0] == '#':      elif color[0] == '#':
47          if len(color) == 7:          if len(color) == 7:
48              r = string.atoi(color[1:3], 16) / 255.0              r = string.atoi(color[1:3], 16) / 255.0
# Line 50  def parse_color(color): Line 57  def parse_color(color):
57      return result      return result
58    
59    
60  class ProcessSession(xml.sax.handler.ContentHandler):  class XMLReader(xml.sax.handler.ContentHandler):
61    
62      # Dictionary mapping element names (or (URI, element name) pairs for      # Dictionary mapping element names (or (URI, element name) pairs for
63      # documents using namespaces) to method names. The methods should      # documents using namespaces) to method names. The methods should
# Line 66  class ProcessSession(xml.sax.handler.Con Line 73  class ProcessSession(xml.sax.handler.Con
73      end_dispatcher = {}      end_dispatcher = {}
74    
75    
76      def __init__(self, directory):      def __init__(self):
77          """Inititialize the Sax handler.          self.chars = ''
78            self.__directory = ""
79            self.__dispatchers = {}
80    
81        def read(self, file_or_filename):
82    
83          The directory parameter should be the directory containing the          if hasattr(file_or_filename, "read"):
84          session file. It's needed to interpret embedded relative              # it's a file object
85          filenames.              self.__directory = ""
86                self.__file = file_or_filename
87            else:
88                filename = file_or_filename
89                self.__directory = os.path.dirname(filename)
90                self.__file = open(filename)
91    
92            parser = make_parser()
93            parser.setContentHandler(self)
94            parser.setErrorHandler(ErrorHandler())
95            parser.setFeature(xml.sax.handler.feature_namespaces, 1)
96    
97            #
98            # Well, this isn't pretty, but it appears that if you
99            # use Python 2.2 without the site-package _xmlplus then
100            # the following will fail, and without them it will work.
101            # However, if you do have the site-package and you don't
102            # call these functions, the reader raises an exception
103            #
104            # The reason we set these to 0 in the first place is
105            # because there is an unresolved issue with external
106            # entities causing an exception in the reader
107            #
108            try:
109                parser.setFeature(xml.sax.handler.feature_validation,0)
110                parser.setFeature(xml.sax.handler.feature_external_ges,0)
111                parser.setFeature(xml.sax.handler.feature_external_pes,0)
112            except SAXNotRecognizedException:
113                pass
114    
115            parser.parse(self.__file)
116    
117            self.close()
118    
119        def close(self):
120            self.__file.close()
121            
122        def GetFilename(self):
123            if hasattr(self.__file, "name"):
124                return self.__file.name
125    
126            return ""
127    
128        def GetDirectory(self):
129            return self.__directory
130    
131    
132        def AddDispatchers(self, dict):
133            """Add the function names that should be used to process XML tags.
134    
135            dict -- a dictionary whose keys are XML tag strings and whose values
136                    are pairs of strings such that the first string is
137                    the name of the function that should be called when the
138                    XML tag opens and the second string is the name of the
139                    function that should be called when the XML tag closes.
140                    If a pair element is None, no function is called.
141          """          """
142          self.directory = directory  
143          self.chars = ''          self.__dispatchers.update(dict)
         self.theSession = None  
         self.aMap = None  
         self.aLayer = None  
144    
145      def startElementNS(self, name, qname, attrs):      def startElementNS(self, name, qname, attrs):
146          """Call the method given for name in self.start_dispatcher          """Call the method given for name in self.start_dispatcher
147          """          """
148          if name[0] is None:          if name[0] is None:
149              method_name = self.start_dispatcher.get(name[1])              method_name = self.__dispatchers.get(name[1])
150          else:          else:
151              # Dispatch with namespace              # Dispatch with namespace
152              method_name = self.start_dispatcher.get(name)              method_name = self.__dispatchers.get(name)
153          if method_name is not None:          if method_name is not None and method_name[0] is not None:
154              getattr(self, method_name)(name, qname, attrs)              getattr(self, method_name[0])(name, qname, attrs)
155    
156      def endElementNS(self, name, qname):      def endElementNS(self, name, qname):
157          """Call the method given for name in self.end_dispatcher          """Call the method given for name in self.end_dispatcher
158          """          """
159          if name[0] is None:          if name[0] is None:
160              method_name = self.end_dispatcher.get(name[1])              method_name = self.__dispatchers.get(name[1])
161          else:          else:
162              # Dispatch with namespace              # Dispatch with namespace
163              method_name = self.end_dispatcher.get(name)              method_name = self.__dispatchers.get(name)
164          if method_name is not None:          if method_name is not None and method_name[1] is not None:
165              getattr(self, method_name)(name, qname)              getattr(self, method_name[1])(name, qname)
166    
167    class SessionLoader(XMLReader):
168    
169        def __init__(self):
170            """Inititialize the Sax handler."""
171            XMLReader.__init__(self)
172    
173            self.theSession = None
174            self.aMap = None
175            self.aLayer = None
176    
177            XMLReader.AddDispatchers(self,
178                {'session'       : ("start_session",        "end_session"),
179                 'map'           : ("start_map",            "end_map"),
180                 'projection'    : ("start_projection",     "end_projection"),
181                 'parameter'     : ("start_parameter",      None),
182                 'layer'         : ("start_layer",          "end_layer"),
183                 'classification': ("start_classification", "end_classification"),
184                 'clnull'        : ("start_clnull",         "end_clnull"),
185                 'clpoint'       : ("start_clpoint",        "end_clpoint"),
186                 'clrange'       : ("start_clrange",        "end_clrange"),
187                 'cldata'        : ("start_cldata",         "end_cldata"),
188                 'table'         : ("start_table",          "end_table"),
189                 'labellayer'    : ("start_labellayer",     None),
190                 'label'         : ("start_label",          None)})
191    
192      def start_session(self, name, qname, attrs):      def start_session(self, name, qname, attrs):
193          self.theSession = Session(attrs.get((None, 'title'), None))          self.theSession = Session(attrs.get((None, 'title'), None))
     start_dispatcher['session'] = "start_session"  
194    
195      def end_session(self, name, qname):      def end_session(self, name, qname):
196          pass          pass
     end_dispatcher['session'] = "end_session"  
197    
198      def start_map(self, name, qname, attrs):      def start_map(self, name, qname, attrs):
199          """Start a map."""          """Start a map."""
200          self.aMap = Map(attrs.get((None, 'title'), None))          self.aMap = Map(attrs.get((None, 'title'), None))
201      start_dispatcher['map'] = "start_map"          self.__projReceiver = self.aMap
202    
203      def end_map(self, name, qname):      def end_map(self, name, qname):
204          self.theSession.AddMap(self.aMap)          self.theSession.AddMap(self.aMap)
205      end_dispatcher['map'] = "end_map"          self.__projReceiver = None
206    
207      def start_projection(self, name, qname, attrs):      def start_projection(self, name, qname, attrs):
208            self.ProjectionName = attrs.get((None, 'name'), None)
209          self.ProjectionParams = [ ]          self.ProjectionParams = [ ]
     start_dispatcher['projection'] = "start_projection"  
210    
211      def end_projection(self, name, qname):      def end_projection(self, name, qname):
212          self.aMap.SetProjection(Projection(self.ProjectionParams))          self.__projReceiver.SetProjection(
213      end_dispatcher['projection'] = "end_projection"              Projection(self.ProjectionParams, self.ProjectionName))
214    
215      def start_parameter(self, name, qname, attrs):      def start_parameter(self, name, qname, attrs):
216          s = attrs.get((None, 'value'))          s = attrs.get((None, 'value'))
217          s = str(s) # we can't handle unicode in proj          s = str(s) # we can't handle unicode in proj
218          self.ProjectionParams.append(s)          self.ProjectionParams.append(s)
     start_dispatcher['parameter'] = "start_parameter"  
219    
220      def start_layer(self, name, qname, attrs, layer_class = Layer):      def start_layer(self, name, qname, attrs, layer_class = Layer):
221          """Start a layer          """Start a layer
# Line 141  class ProcessSession(xml.sax.handler.Con Line 226  class ProcessSession(xml.sax.handler.Con
226          """          """
227          title = attrs.get((None, 'title'), "")          title = attrs.get((None, 'title'), "")
228          filename = attrs.get((None, 'filename'), "")          filename = attrs.get((None, 'filename'), "")
229          filename = os.path.join(self.directory, filename)          filename = os.path.join(self.GetDirectory(), filename)
230            visible  = attrs.get((None, 'visible'), "true")
231          fill = parse_color(attrs.get((None, 'fill'), "None"))          fill = parse_color(attrs.get((None, 'fill'), "None"))
232          stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))          stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
233          stroke_width = int(attrs.get((None, 'stroke_width'), "1"))          stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
234          self.aLayer = layer_class(title, filename, fill = fill,          self.aLayer = layer_class(title,
235                                    stroke = stroke, stroke_width = stroke_width)                                    self.theSession.OpenShapefile(filename),
236      start_dispatcher['layer'] = "start_layer"                                    fill = fill, stroke = stroke,
237                                      lineWidth = stroke_width,
238                                      visible = visible != "false")
239    
240            self.__projReceiver = self.aLayer
241    
242      def end_layer(self, name, qname):      def end_layer(self, name, qname):
243          self.aMap.AddLayer(self.aLayer)          self.aMap.AddLayer(self.aLayer)
244      end_dispatcher['layer'] = "end_layer"          self.__projReceiver = None
245    
246      def start_classification(self, name, qname, attrs):      def start_classification(self, name, qname, attrs):
247          self.aLayer.classification.setField(attrs.get((None, 'field'), None))          field = attrs.get((None, 'field'), None)
248      start_dispatcher['classification'] = "start_classification"  
249            fieldType = attrs.get((None, 'field_type'), None)
250            dbFieldType = self.aLayer.GetFieldType(field)
251    
252            if fieldType != dbFieldType:
253                raise ValueError(_("xml field type differs from database!"))
254    
255            # setup conversion routines depending on the kind of data
256            # we will be seeing later on
257            if fieldType == FIELDTYPE_STRING:
258                self.conv = str
259            elif fieldType == FIELDTYPE_INT:
260                self.conv = lambda p: int(float(p))
261            elif fieldType == FIELDTYPE_DOUBLE:
262                self.conv = float
263    
264            self.aLayer.GetClassification().SetField(field)
265    
266    
267      def end_classification(self, name, qname):      def end_classification(self, name, qname):
268          pass          pass
     end_dispatcher['classification'] = "end_classification"  
269    
270      def start_clnull(self, name, qname, attrs):      def start_clnull(self, name, qname, attrs):
271          self.cl_data = {}          self.cl_group = ClassGroupDefault()
272      start_dispatcher['clnull'] = "start_clnull"          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
273            self.cl_prop = ClassGroupProperties()
274    
275      def end_clnull(self, name, qname):      def end_clnull(self, name, qname):
276          self.aLayer.classification.setNull(self.cl_data)          self.cl_group.SetProperties(self.cl_prop)
277          del self.cl_data          self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
278      end_dispatcher['clnull'] = "end_clnull"          del self.cl_group, self.cl_prop
279    
280      def start_clpoint(self, name, qname, attrs):      def start_clpoint(self, name, qname, attrs):
281          attrib_value = attrs.get((None, 'value'), "0")          attrib_value = attrs.get((None, 'value'), "0")
282    
283          try:          value = self.conv(attrib_value)
284              self.cl_value  = int(attrib_value)  
285          except:          self.cl_group = ClassGroupSingleton(value)
286              self.cl_value  = attrib_value          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
287            self.cl_prop = ClassGroupProperties()
288    
         self.cl_data = {}  
     start_dispatcher['clpoint'] = "start_clpoint"  
289    
290      def end_clpoint(self, name, qname):      def end_clpoint(self, name, qname):
291          self.aLayer.classification.addPoint(self.cl_value, self.cl_data)          self.cl_group.SetProperties(self.cl_prop)
292          del self.cl_value, self.cl_data          self.aLayer.GetClassification().AppendGroup(self.cl_group)
293      end_dispatcher['clpoint'] = "end_clpoint"          del self.cl_group, self.cl_prop
294    
295      def start_clrange(self, name, qname, attrs):      def start_clrange(self, name, qname, attrs):
296    
297          try:          try:
298              self.cl_low = int(attrs.get((None, 'low'), "0"))              min = self.conv(attrs.get((None, 'min'), "0"))
299              self.cl_high = int(attrs.get((None, 'high'), "0"))              max = self.conv(attrs.get((None, 'max'), "0"))
300          except ValueError:          except ValueError:
301              raise ValueError(_("Classification range is not a number!"))              raise ValueError(_("Classification range is not a number!"))
302    
303          self.cl_data = {}          self.cl_group = ClassGroupRange(min, max)
304      start_dispatcher['clrange'] = "start_clrange"          self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
305            self.cl_prop = ClassGroupProperties()
306    
307    
308      def end_clrange(self, name, qname):      def end_clrange(self, name, qname):
309          self.aLayer.classification.addRange(          self.cl_group.SetProperties(self.cl_prop)
310              self.cl_low, self.cl_high, self.cl_data)          self.aLayer.GetClassification().AppendGroup(self.cl_group)
311          del self.cl_low, self.cl_high, self.cl_data          del self.cl_group, self.cl_prop
     end_dispatcher['clrange'] = "end_clrange"  
312    
313      def start_cldata(self, name, qname, attrs):      def start_cldata(self, name, qname, attrs):
314          self.cl_data['stroke'] = parse_color(          self.cl_prop.SetLineColor(
315                                   attrs.get((None, 'stroke'), "None"))              parse_color(attrs.get((None, 'stroke'), "None")))
316          self.cl_data['stroke_width'] = int(          self.cl_prop.SetLineWidth(
317                                   attrs.get((None, 'stroke_width'), "0"))              int(attrs.get((None, 'stroke_width'), "0")))
318          self.cl_data['fill'] = parse_color(          self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
                                  attrs.get((None, 'fill'), "None"))  
     start_dispatcher['cldata'] = "start_cldata"  
319    
320      def end_cldata(self, name, qname):      def end_cldata(self, name, qname):
321          pass          pass
     end_dispatcher['cldata'] = "end_cldata"  
322    
323      def start_table(self, name, qname, attrs):      def start_table(self, name, qname, attrs):
324          print "table title: %s" % attrs.get('title', None)          #print "table title: %s" % attrs.get('title', None)
325      start_dispatcher['table'] = "start_table"          pass
326    
327      def end_table(self, name, qname):      def end_table(self, name, qname):
328          pass          pass
     end_dispatcher['table'] = "end_table"  
329    
330      def start_labellayer(self, name, qname, attrs):      def start_labellayer(self, name, qname, attrs):
331          self.aLayer = self.aMap.LabelLayer()          self.aLayer = self.aMap.LabelLayer()
     start_dispatcher['labellayer'] = "start_labellayer"  
332    
333      def start_label(self, name, qname, attrs):      def start_label(self, name, qname, attrs):
334          x = float(attrs[(None, 'x')])          x = float(attrs[(None, 'x')])
# Line 235  class ProcessSession(xml.sax.handler.Con Line 337  class ProcessSession(xml.sax.handler.Con
337          halign = attrs[(None, 'halign')]          halign = attrs[(None, 'halign')]
338          valign = attrs[(None, 'valign')]          valign = attrs[(None, 'valign')]
339          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
     start_dispatcher['label'] = "start_label"  
340    
341      def characters(self, chars):      def characters(self, chars):
342          pass          pass
# Line 243  class ProcessSession(xml.sax.handler.Con Line 344  class ProcessSession(xml.sax.handler.Con
344    
345  def load_session(filename):  def load_session(filename):
346      """Load a Thuban session from the file object file"""      """Load a Thuban session from the file object file"""
347      dir = os.path.dirname(filename)  
348      file = open(filename)      handler = SessionLoader()
349      handler = ProcessSession(dir)      handler.read(filename)
   
     parser = make_parser()  
     parser.setContentHandler(handler)  
     parser.setErrorHandler(ErrorHandler())  
     parser.setFeature(xml.sax.handler.feature_namespaces, 1)  
     parser.parse(file)  
350    
351      session = handler.theSession      session = handler.theSession
352      # Newly loaded session aren't modified      # Newly loaded session aren't modified

Legend:
Removed from v.374  
changed lines
  Added in v.784

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26