/[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 6 by bh, Tue Aug 28 15:41:52 2001 UTC revision 465 by jonathan, Wed Mar 5 18:18:06 2003 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001 by Intevation GmbH  # Copyright (C) 2001, 2002 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4    # 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 14  Parser for thuban session files.
14  __version__ = "$Revision$"  __version__ = "$Revision$"
15    
16  import sys, string, os  import sys, string, os
17    
18    import xml.sax
19    import xml.sax.handler
20    from xml.sax import make_parser, ErrorHandler
21    
22    from Thuban import _
23    from Thuban.common import *
24    
25  from Thuban.Model.session import Session  from Thuban.Model.session import Session
26  from Thuban.Model.map import Map  from Thuban.Model.map import Map
27  from Thuban.Model.layer import Layer  from Thuban.Model.layer import Layer
28  from Thuban.Model.color import Color  from Thuban.Model.color import Color
29  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
30    from Thuban.Model.classification import Classification, \
31  oldPython=0      ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
32        ClassGroupProperties
 if not sys.__dict__.has_key("version_info"):  
     # We can assume to have python 1.5.2 or lower here now  
     oldPython=1  
   
 if oldPython:  
     try:  
         from xml.sax.saxexts import make_parser  
         from xml.sax.saxlib import HandlerBase  
         from xml.sax import saxutils  
     except ImportError:  
         sys.stdout.write(("You need to have Python-XML installed or"  
                           " a modern Python!\n"  
                           "Check www.python.org/sigs/xml-sig/\n\n"))  
         raise  
 else:  
     # Do the python 2.0 standard xml thing and map it on the old names  
     import xml.sax  
     import xml.sax.handler  
     HandlerBase=xml.sax.handler.ContentHandler  
     from xml.sax import make_parser  
   
 class testSAXContentHandler(HandlerBase):  
 # SAX compliant  
     def characters(self, ch, start, length):  
         pass  
       
 def test_for_broken_SAX():  
     ch=testSAXContentHandler()  
     try:  
         xml.sax.parseString("""<?xml version="1.0"?>  
             <child1 name="paul">Text goes here</child1>  
         """,ch)  
     except TypeError:  
         return 1  
     return 0  
33    
34    
35  def parse_color(color):  def parse_color(color):
36      """      """Return the color object for the string color.
37      Return the color object for the string color. Color may be either  
38      'None' or of the form '#RRGGBB' in the usual HTML color notation      Color may be either 'None' or of the form '#RRGGBB' in the usual
39        HTML color notation
40      """      """
41      color = string.strip(color)      color = string.strip(color)
42      if color == "None":      if color == "None":
43          result = None          result = Color.None
44      elif color[0] == '#':      elif color[0] == '#':
45          if len(color) == 7:          if len(color) == 7:
46              r = string.atoi(color[1:3], 16) / 255.0              r = string.atoi(color[1:3], 16) / 255.0
# Line 72  def parse_color(color): Line 48  def parse_color(color):
48              b = string.atoi(color[5:7], 16) / 255.0              b = string.atoi(color[5:7], 16) / 255.0
49              result = Color(r, g, b)              result = Color(r, g, b)
50          else:          else:
51              raise ValueError("Invalid hexadecimal color specification %s"              raise ValueError(_("Invalid hexadecimal color specification %s")
52                               % color)                               % color)
53      else:      else:
54          raise ValueError("Invalid color specification %s" % color)          raise ValueError(_("Invalid color specification %s") % color)
55      return result      return result
56    
57    
58  class ProcessSession(HandlerBase):  class ProcessSession(xml.sax.handler.ContentHandler):
59    
60        # Dictionary mapping element names (or (URI, element name) pairs for
61        # documents using namespaces) to method names. The methods should
62        # accept the same parameters as the startElement (or startElementNS)
63        # methods. The start_dispatcher is used by the default startElement
64        # and startElementNS methods to call a method for the open tag of an
65        # element.
66        start_dispatcher = {}
67    
68        # end_dispatcher works just like start_dispatcher but it's used by
69        # endElement and endElementNS. The method whose names it maps to
70        # should accept the same parameters as endElement and endElementNS.
71        end_dispatcher = {}
72    
73    
74      def __init__(self, directory):      def __init__(self, directory):
75          """Inititialize the Sax handler.          """Inititialize the Sax handler.
76    
77          directory is the directory containing the session file. It's          The directory parameter should be the directory containing the
78          needed to interpret embedded relative filenames          session file. It's needed to interpret embedded relative
79            filenames.
80          """          """
81          self.directory = directory          self.directory = directory
82          self.chars = ''          self.chars = ''
# Line 93  class ProcessSession(HandlerBase): Line 84  class ProcessSession(HandlerBase):
84          self.aMap = None          self.aMap = None
85          self.aLayer = None          self.aLayer = None
86    
87      def startElement(self, name, attrs):      def startElementNS(self, name, qname, attrs):
88          if name == 'session':          """Call the method given for name in self.start_dispatcher
89              self.theSession = Session(attrs.get('title', None))          """
90          elif name == 'map':          if name[0] is None:
91              self.aMap = Map(attrs.get('title', None))              method_name = self.start_dispatcher.get(name[1])
92          elif name == 'projection':          else:
93              self.ProjectionParams = [ ]              # Dispatch with namespace
94          elif name == 'parameter':              method_name = self.start_dispatcher.get(name)
95              self.ProjectionParams.append(attrs.get('value', None))          if method_name is not None:
96          elif name == 'layer':              getattr(self, method_name)(name, qname, attrs)
97              title = attrs.get('title', "")  
98              filename = attrs.get('filename', "")      def endElementNS(self, name, qname):
99              filename = os.path.join(self.directory, filename)          """Call the method given for name in self.end_dispatcher
100              fill = parse_color(attrs.get('fill', "None"))          """
101              stroke = parse_color(attrs.get('stroke', "#000000"))          if name[0] is None:
102              self.aLayer = Layer(title, filename, fill = fill, stroke = stroke)              method_name = self.end_dispatcher.get(name[1])
103          elif name == 'table':          else:
104              print "table title: %s" % attrs.get('title', None)              # Dispatch with namespace
105          elif name == 'labellayer':              method_name = self.end_dispatcher.get(name)
106              self.aLayer = self.aMap.LabelLayer()          if method_name is not None:
107          elif name == 'label':              getattr(self, method_name)(name, qname)
108              x = float(attrs['x'])  
109              y = float(attrs['y'])      def start_session(self, name, qname, attrs):
110              text = attrs['text']          self.theSession = Session(attrs.get((None, 'title'), None))
111              halign = attrs['halign']      start_dispatcher['session'] = "start_session"
112              valign = attrs['valign']  
113              self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)      def end_session(self, name, qname):
114                    pass
115        end_dispatcher['session'] = "end_session"
116      if not oldPython and test_for_broken_SAX():  
117          # works with python 2.0, but is not SAX compliant      def start_map(self, name, qname, attrs):
118          def characters(self, ch):          """Start a map."""
119              self.my_characters(ch)          self.aMap = Map(attrs.get((None, 'title'), None))
120      else:      start_dispatcher['map'] = "start_map"
121          # SAX compliant  
122          def characters(self, ch, start, length):      def end_map(self, name, qname):
123              self.my_characters(ch[start:start+length])          self.theSession.AddMap(self.aMap)
124        end_dispatcher['map'] = "end_map"
125      def my_characters(self, ch):  
126          self.chars = self.chars + ch      def start_projection(self, name, qname, attrs):
127            self.ProjectionParams = [ ]
128      def endElement(self, name):      start_dispatcher['projection'] = "start_projection"
129          # If it's not a parameter element, ignore it  
130          if name == 'session':      def end_projection(self, name, qname):
131              #print "end of session"          self.aMap.SetProjection(Projection(self.ProjectionParams))
132              pass      end_dispatcher['projection'] = "end_projection"
133          if name == 'map':  
134              self.theSession.AddMap(self.aMap)      def start_parameter(self, name, qname, attrs):
135          if name == 'projection':          s = attrs.get((None, 'value'))
136              self.aMap.SetProjection(Projection(self.ProjectionParams))          s = str(s) # we can't handle unicode in proj
137          if name == 'layer':          self.ProjectionParams.append(s)
138              self.aMap.AddLayer(self.aLayer)      start_dispatcher['parameter'] = "start_parameter"
139          if name == 'table':  
140              #print "end of table"      def start_layer(self, name, qname, attrs, layer_class = Layer):
141              pass          """Start a layer
142    
143            Instantiate a layer of class layer_class from the attributes in
144            attrs which may be a dictionary as well as the normal SAX attrs
145            object and bind it to self.aLayer.
146            """
147            title = attrs.get((None, 'title'), "")
148            filename = attrs.get((None, 'filename'), "")
149            filename = os.path.join(self.directory, filename)
150            fill = parse_color(attrs.get((None, 'fill'), "None"))
151            stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
152            stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
153            self.aLayer = layer_class(title, filename, fill = fill,
154                                      stroke = stroke, lineWidth = stroke_width)
155        start_dispatcher['layer'] = "start_layer"
156    
157        def end_layer(self, name, qname):
158            self.aMap.AddLayer(self.aLayer)
159        end_dispatcher['layer'] = "end_layer"
160    
161        def start_classification(self, name, qname, attrs):
162            field = attrs.get((None, 'field'), None)
163    
164            fieldType = attrs.get((None, 'field_type'), None)
165            dbFieldType = self.aLayer.GetFieldType(field)
166    
167            if fieldType != dbFieldType:
168                raise ValueError(_("xml field type differs from database!"))
169    
170            # setup conversion routines depending on the kind of data
171            # we will be seeing later on
172            if fieldType == FIELDTYPE_STRING:
173                self.conv = str
174            elif fieldType == FIELDTYPE_INT:
175                self.conv = lambda p: int(float(p))
176            elif fieldType == FIELDTYPE_DOUBLE:
177                self.conv = float
178    
179            self.aLayer.GetClassification().SetField(field)
180    
181        start_dispatcher['classification'] = "start_classification"
182    
183        def end_classification(self, name, qname):
184            pass
185        end_dispatcher['classification'] = "end_classification"
186    
187        def start_clnull(self, name, qname, attrs):
188            self.cl_group = ClassGroupDefault()
189            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
190            self.cl_prop = ClassGroupProperties()
191        start_dispatcher['clnull'] = "start_clnull"
192    
193        def end_clnull(self, name, qname):
194            self.cl_group.SetProperties(self.cl_prop)
195            self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
196            del self.cl_group, self.cl_prop
197        end_dispatcher['clnull'] = "end_clnull"
198    
199        def start_clpoint(self, name, qname, attrs):
200            attrib_value = attrs.get((None, 'value'), "0")
201    
202            #try:
203                #value  = Str2Num(attrib_value)
204            #except:
205                #value  = attrib_value
206    
207            value = self.conv(attrib_value)
208    
209            self.cl_group = ClassGroupSingleton(value)
210            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
211            self.cl_prop = ClassGroupProperties()
212    
213        start_dispatcher['clpoint'] = "start_clpoint"
214    
215        def end_clpoint(self, name, qname):
216            self.cl_group.SetProperties(self.cl_prop)
217            self.aLayer.GetClassification().AddGroup(self.cl_group)
218            del self.cl_group, self.cl_prop
219        end_dispatcher['clpoint'] = "end_clpoint"
220    
221        def start_clrange(self, name, qname, attrs):
222    
223            try:
224                min = self.conv(attrs.get((None, 'min'), "0"))
225                max = self.conv(attrs.get((None, 'max'), "0"))
226                #min = Str2Num(attrs.get((None, 'min'), "0"))
227                #max = Str2Num(attrs.get((None, 'max'), "0"))
228            except ValueError:
229                raise ValueError(_("Classification range is not a number!"))
230    
231            self.cl_group = ClassGroupRange(min, max)
232            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
233            self.cl_prop = ClassGroupProperties()
234    
235        start_dispatcher['clrange'] = "start_clrange"
236    
237        def end_clrange(self, name, qname):
238            self.cl_group.SetProperties(self.cl_prop)
239            self.aLayer.GetClassification().AddGroup(self.cl_group)
240            del self.cl_group, self.cl_prop
241        end_dispatcher['clrange'] = "end_clrange"
242    
243        def start_cldata(self, name, qname, attrs):
244            self.cl_prop.SetLineColor(
245                parse_color(attrs.get((None, 'stroke'), "None")))
246            self.cl_prop.SetLineWidth(
247                int(attrs.get((None, 'stroke_width'), "0")))
248            self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
249        start_dispatcher['cldata'] = "start_cldata"
250    
251        def end_cldata(self, name, qname):
252            pass
253        end_dispatcher['cldata'] = "end_cldata"
254    
255        def start_table(self, name, qname, attrs):
256            print "table title: %s" % attrs.get('title', None)
257        start_dispatcher['table'] = "start_table"
258    
259        def end_table(self, name, qname):
260            pass
261        end_dispatcher['table'] = "end_table"
262    
263        def start_labellayer(self, name, qname, attrs):
264            self.aLayer = self.aMap.LabelLayer()
265        start_dispatcher['labellayer'] = "start_labellayer"
266    
267        def start_label(self, name, qname, attrs):
268            x = float(attrs[(None, 'x')])
269            y = float(attrs[(None, 'y')])
270            text = attrs[(None, 'text')]
271            halign = attrs[(None, 'halign')]
272            valign = attrs[(None, 'valign')]
273            self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
274        start_dispatcher['label'] = "start_label"
275    
276        def characters(self, chars):
277            pass
278    
279    
280  def load_session(filename):  def load_session(filename):
281      """Load a Thuban session from the file object file"""      """Load a Thuban session from the file object file"""
# Line 155  def load_session(filename): Line 283  def load_session(filename):
283      file = open(filename)      file = open(filename)
284      handler = ProcessSession(dir)      handler = ProcessSession(dir)
285    
286      if oldPython:      parser = make_parser()
287          parser = make_parser()      parser.setContentHandler(handler)
288          parser.setDocumentHandler(handler)      parser.setErrorHandler(ErrorHandler())
289          parser.setErrorHandler(saxutils.ErrorPrinter())      parser.setFeature(xml.sax.handler.feature_namespaces, 1)
290          parser.parseFile(file)      parser.parse(file)
291          parser.close()  
     else:  
         xml.sax.parse(file,handler)  
292      session = handler.theSession      session = handler.theSession
293      # Newly loaded session aren't modified      # Newly loaded session aren't modified
294      session.UnsetModified()      session.UnsetModified()
295    
296      return session      return session
297    
 if __name__ == "__main__":  
     # find out the command to run  
     if len(sys.argv) > 1:  
         print "usage: cat <file> | " + sys.argv[0]  
     else:  
         parseSession(sys.stdin)  

Legend:
Removed from v.6  
changed lines
  Added in v.465

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26