/[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 105 by jan, Fri Apr 19 15:36:57 2002 UTC revision 439 by jonathan, Thu Feb 27 15:54:05 2003 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001, 2002 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              s = attrs.get('value')          if method_name is not None:
96              s = str(s) # we can't handle unicode in proj              getattr(self, method_name)(name, qname, attrs)
97              self.ProjectionParams.append(s)  
98          elif name == 'layer':      def endElementNS(self, name, qname):
99              title = attrs.get('title', "")          """Call the method given for name in self.end_dispatcher
100              filename = attrs.get('filename', "")          """
101              filename = os.path.join(self.directory, filename)          if name[0] is None:
102              fill = parse_color(attrs.get('fill', "None"))              method_name = self.end_dispatcher.get(name[1])
103              stroke = parse_color(attrs.get('stroke', "#000000"))          else:
104              stroke_width = int(attrs.get("stroke_width", "1"))              # Dispatch with namespace
105              self.aLayer = Layer(title, filename, fill = fill, stroke = stroke,              method_name = self.end_dispatcher.get(name)
106                                  stroke_width = stroke_width)          if method_name is not None:
107          elif name == 'table':              getattr(self, method_name)(name, qname)
108              print "table title: %s" % attrs.get('title', None)  
109          elif name == 'labellayer':      def start_session(self, name, qname, attrs):
110              self.aLayer = self.aMap.LabelLayer()          self.theSession = Session(attrs.get((None, 'title'), None))
111          elif name == 'label':      start_dispatcher['session'] = "start_session"
112              x = float(attrs['x'])  
113              y = float(attrs['y'])      def end_session(self, name, qname):
114              text = attrs['text']          pass
115              halign = attrs['halign']      end_dispatcher['session'] = "end_session"
116              valign = attrs['valign']  
117              self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)      def start_map(self, name, qname, attrs):
118                    """Start a map."""
119            self.aMap = Map(attrs.get((None, 'title'), None))
120      if not oldPython and test_for_broken_SAX():      start_dispatcher['map'] = "start_map"
121          # works with python 2.0, but is not SAX compliant  
122          def characters(self, ch):      def end_map(self, name, qname):
123              self.my_characters(ch)          self.theSession.AddMap(self.aMap)
124      else:      end_dispatcher['map'] = "end_map"
125          # SAX compliant  
126          def characters(self, ch, start, length):      def start_projection(self, name, qname, attrs):
127              self.my_characters(ch[start:start+length])          self.ProjectionParams = [ ]
128        start_dispatcher['projection'] = "start_projection"
129      def my_characters(self, ch):  
130          self.chars = self.chars + ch      def end_projection(self, name, qname):
131            self.aMap.SetProjection(Projection(self.ProjectionParams))
132      def endElement(self, name):      end_dispatcher['projection'] = "end_projection"
133          # If it's not a parameter element, ignore it  
134          if name == 'session':      def start_parameter(self, name, qname, attrs):
135              #print "end of session"          s = attrs.get((None, 'value'))
136              pass          s = str(s) # we can't handle unicode in proj
137          if name == 'map':          self.ProjectionParams.append(s)
138              self.theSession.AddMap(self.aMap)      start_dispatcher['parameter'] = "start_parameter"
139          if name == 'projection':  
140              self.aMap.SetProjection(Projection(self.ProjectionParams))      def start_layer(self, name, qname, attrs, layer_class = Layer):
141          if name == 'layer':          """Start a layer
142              self.aMap.AddLayer(self.aLayer)  
143          if name == 'table':          Instantiate a layer of class layer_class from the attributes in
144              #print "end of table"          attrs which may be a dictionary as well as the normal SAX attrs
145              pass          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, stroke_width = 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            self.aLayer.GetClassification().SetField(
163                attrs.get((None, 'field'), None))
164        start_dispatcher['classification'] = "start_classification"
165    
166        def end_classification(self, name, qname):
167            pass
168        end_dispatcher['classification'] = "end_classification"
169    
170        def start_clnull(self, name, qname, attrs):
171            self.cl_group = ClassGroupDefault()
172            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
173            self.cl_prop = ClassGroupProperties()
174        start_dispatcher['clnull'] = "start_clnull"
175    
176        def end_clnull(self, name, qname):
177            self.cl_group.SetProperties(self.cl_prop)
178            self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
179            del self.cl_group, self.cl_prop
180        end_dispatcher['clnull'] = "end_clnull"
181    
182        def start_clpoint(self, name, qname, attrs):
183            attrib_value = attrs.get((None, 'value'), "0")
184    
185            try:
186                value  = Str2Num(attrib_value)
187            except:
188                value  = attrib_value
189    
190            self.cl_group = ClassGroupSingleton(value)
191            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
192            self.cl_prop = ClassGroupProperties()
193    
194        start_dispatcher['clpoint'] = "start_clpoint"
195    
196        def end_clpoint(self, name, qname):
197            self.cl_group.SetProperties(self.cl_prop)
198            self.aLayer.GetClassification().AddGroup(self.cl_group)
199            del self.cl_group, self.cl_prop
200        end_dispatcher['clpoint'] = "end_clpoint"
201    
202        def start_clrange(self, name, qname, attrs):
203    
204            try:
205                min = Str2Num(attrs.get((None, 'min'), "0"))
206                max = Str2Num(attrs.get((None, 'max'), "0"))
207            except ValueError:
208                raise ValueError(_("Classification range is not a number!"))
209    
210            self.cl_group = ClassGroupRange(min, max)
211            self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
212            self.cl_prop = ClassGroupProperties()
213    
214        start_dispatcher['clrange'] = "start_clrange"
215    
216        def end_clrange(self, name, qname):
217            self.cl_group.SetProperties(self.cl_prop)
218            self.aLayer.GetClassification().AddGroup(self.cl_group)
219            del self.cl_group, self.cl_prop
220        end_dispatcher['clrange'] = "end_clrange"
221    
222        def start_cldata(self, name, qname, attrs):
223            self.cl_prop.SetStroke(parse_color(attrs.get((None, 'stroke'), "None")))
224            self.cl_prop.SetStrokeWidth(
225                int(attrs.get((None, 'stroke_width'), "0")))
226            self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
227        start_dispatcher['cldata'] = "start_cldata"
228    
229        def end_cldata(self, name, qname):
230            pass
231        end_dispatcher['cldata'] = "end_cldata"
232    
233        def start_table(self, name, qname, attrs):
234            print "table title: %s" % attrs.get('title', None)
235        start_dispatcher['table'] = "start_table"
236    
237        def end_table(self, name, qname):
238            pass
239        end_dispatcher['table'] = "end_table"
240    
241        def start_labellayer(self, name, qname, attrs):
242            self.aLayer = self.aMap.LabelLayer()
243        start_dispatcher['labellayer'] = "start_labellayer"
244    
245        def start_label(self, name, qname, attrs):
246            x = float(attrs[(None, 'x')])
247            y = float(attrs[(None, 'y')])
248            text = attrs[(None, 'text')]
249            halign = attrs[(None, 'halign')]
250            valign = attrs[(None, 'valign')]
251            self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
252        start_dispatcher['label'] = "start_label"
253    
254        def characters(self, chars):
255            pass
256    
257    
258  def load_session(filename):  def load_session(filename):
259      """Load a Thuban session from the file object file"""      """Load a Thuban session from the file object file"""
# Line 159  def load_session(filename): Line 261  def load_session(filename):
261      file = open(filename)      file = open(filename)
262      handler = ProcessSession(dir)      handler = ProcessSession(dir)
263    
264      if oldPython:      parser = make_parser()
265          parser = make_parser()      parser.setContentHandler(handler)
266          parser.setDocumentHandler(handler)      parser.setErrorHandler(ErrorHandler())
267          parser.setErrorHandler(saxutils.ErrorPrinter())      parser.setFeature(xml.sax.handler.feature_namespaces, 1)
268          parser.parseFile(file)      parser.parse(file)
269          parser.close()  
     else:  
         xml.sax.parse(file,handler)  
270      session = handler.theSession      session = handler.theSession
271      # Newly loaded session aren't modified      # Newly loaded session aren't modified
272      session.UnsetModified()      session.UnsetModified()
273    
274      return session      return session
275    
 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.105  
changed lines
  Added in v.439

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26