/[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 75 by bh, Mon Feb 4 19:22:22 2002 UTC revision 413 by jonathan, Wed Feb 19 16:52:04 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      ClassDataDefault, ClassDataPoint, ClassDataRange, ClassDataMap
   
 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  
32    
33    
34  def parse_color(color):  def parse_color(color):
35      """      """Return the color object for the string color.
36      Return the color object for the string color. Color may be either  
37      '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
38        HTML color notation
39      """      """
40      color = string.strip(color)      color = string.strip(color)
41      if color == "None":      if color == "None":
42          result = None          result = Color.None
43      elif color[0] == '#':      elif color[0] == '#':
44          if len(color) == 7:          if len(color) == 7:
45              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 47  def parse_color(color):
47              b = string.atoi(color[5:7], 16) / 255.0              b = string.atoi(color[5:7], 16) / 255.0
48              result = Color(r, g, b)              result = Color(r, g, b)
49          else:          else:
50              raise ValueError("Invalid hexadecimal color specification %s"              raise ValueError(_("Invalid hexadecimal color specification %s")
51                               % color)                               % color)
52      else:      else:
53          raise ValueError("Invalid color specification %s" % color)          raise ValueError(_("Invalid color specification %s") % color)
54      return result      return result
55    
56    
57  class ProcessSession(HandlerBase):  class ProcessSession(xml.sax.handler.ContentHandler):
58    
59        # Dictionary mapping element names (or (URI, element name) pairs for
60        # documents using namespaces) to method names. The methods should
61        # accept the same parameters as the startElement (or startElementNS)
62        # methods. The start_dispatcher is used by the default startElement
63        # and startElementNS methods to call a method for the open tag of an
64        # element.
65        start_dispatcher = {}
66    
67        # end_dispatcher works just like start_dispatcher but it's used by
68        # endElement and endElementNS. The method whose names it maps to
69        # should accept the same parameters as endElement and endElementNS.
70        end_dispatcher = {}
71    
72    
73      def __init__(self, directory):      def __init__(self, directory):
74          """Inititialize the Sax handler.          """Inititialize the Sax handler.
75    
76          directory is the directory containing the session file. It's          The directory parameter should be the directory containing the
77          needed to interpret embedded relative filenames          session file. It's needed to interpret embedded relative
78            filenames.
79          """          """
80          self.directory = directory          self.directory = directory
81          self.chars = ''          self.chars = ''
# Line 93  class ProcessSession(HandlerBase): Line 83  class ProcessSession(HandlerBase):
83          self.aMap = None          self.aMap = None
84          self.aLayer = None          self.aLayer = None
85    
86      def startElement(self, name, attrs):      def startElementNS(self, name, qname, attrs):
87          if name == 'session':          """Call the method given for name in self.start_dispatcher
88              self.theSession = Session(attrs.get('title', None))          """
89          elif name == 'map':          if name[0] is None:
90              self.aMap = Map(attrs.get('title', None))              method_name = self.start_dispatcher.get(name[1])
91          elif name == 'projection':          else:
92              self.ProjectionParams = [ ]              # Dispatch with namespace
93          elif name == 'parameter':              method_name = self.start_dispatcher.get(name)
94              self.ProjectionParams.append(attrs.get('value', None))          if method_name is not None:
95          elif name == 'layer':              getattr(self, method_name)(name, qname, attrs)
96              title = attrs.get('title', "")  
97              filename = attrs.get('filename', "")      def endElementNS(self, name, qname):
98              filename = os.path.join(self.directory, filename)          """Call the method given for name in self.end_dispatcher
99              fill = parse_color(attrs.get('fill', "None"))          """
100              stroke = parse_color(attrs.get('stroke', "#000000"))          if name[0] is None:
101              stroke_width = int(attrs.get("stroke_width", "1"))              method_name = self.end_dispatcher.get(name[1])
102              self.aLayer = Layer(title, filename, fill = fill, stroke = stroke,          else:
103                                  stroke_width = stroke_width)              # Dispatch with namespace
104          elif name == 'table':              method_name = self.end_dispatcher.get(name)
105              print "table title: %s" % attrs.get('title', None)          if method_name is not None:
106          elif name == 'labellayer':              getattr(self, method_name)(name, qname)
107              self.aLayer = self.aMap.LabelLayer()  
108          elif name == 'label':      def start_session(self, name, qname, attrs):
109              x = float(attrs['x'])          self.theSession = Session(attrs.get((None, 'title'), None))
110              y = float(attrs['y'])      start_dispatcher['session'] = "start_session"
111              text = attrs['text']  
112              halign = attrs['halign']      def end_session(self, name, qname):
113              valign = attrs['valign']          pass
114              self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)      end_dispatcher['session'] = "end_session"
115            
116        def start_map(self, name, qname, attrs):
117      if not oldPython and test_for_broken_SAX():          """Start a map."""
118          # works with python 2.0, but is not SAX compliant          self.aMap = Map(attrs.get((None, 'title'), None))
119          def characters(self, ch):      start_dispatcher['map'] = "start_map"
120              self.my_characters(ch)  
121      else:      def end_map(self, name, qname):
122          # SAX compliant          self.theSession.AddMap(self.aMap)
123          def characters(self, ch, start, length):      end_dispatcher['map'] = "end_map"
124              self.my_characters(ch[start:start+length])  
125        def start_projection(self, name, qname, attrs):
126      def my_characters(self, ch):          self.ProjectionParams = [ ]
127          self.chars = self.chars + ch      start_dispatcher['projection'] = "start_projection"
128    
129      def endElement(self, name):      def end_projection(self, name, qname):
130          # If it's not a parameter element, ignore it          self.aMap.SetProjection(Projection(self.ProjectionParams))
131          if name == 'session':      end_dispatcher['projection'] = "end_projection"
132              #print "end of session"  
133              pass      def start_parameter(self, name, qname, attrs):
134          if name == 'map':          s = attrs.get((None, 'value'))
135              self.theSession.AddMap(self.aMap)          s = str(s) # we can't handle unicode in proj
136          if name == 'projection':          self.ProjectionParams.append(s)
137              self.aMap.SetProjection(Projection(self.ProjectionParams))      start_dispatcher['parameter'] = "start_parameter"
138          if name == 'layer':  
139              self.aMap.AddLayer(self.aLayer)      def start_layer(self, name, qname, attrs, layer_class = Layer):
140          if name == 'table':          """Start a layer
141              #print "end of table"  
142              pass          Instantiate a layer of class layer_class from the attributes in
143            attrs which may be a dictionary as well as the normal SAX attrs
144            object and bind it to self.aLayer.
145            """
146            title = attrs.get((None, 'title'), "")
147            filename = attrs.get((None, 'filename'), "")
148            filename = os.path.join(self.directory, filename)
149            fill = parse_color(attrs.get((None, 'fill'), "None"))
150            stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
151            stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
152            self.aLayer = layer_class(title, filename, fill = fill,
153                                      stroke = stroke, stroke_width = stroke_width)
154        start_dispatcher['layer'] = "start_layer"
155    
156        def end_layer(self, name, qname):
157            self.aMap.AddLayer(self.aLayer)
158        end_dispatcher['layer'] = "end_layer"
159    
160        def start_classification(self, name, qname, attrs):
161            self.aLayer.GetClassification().SetField(
162                attrs.get((None, 'field'), None))
163        start_dispatcher['classification'] = "start_classification"
164    
165        def end_classification(self, name, qname):
166            pass
167        end_dispatcher['classification'] = "end_classification"
168    
169        def start_clnull(self, name, qname, attrs):
170            self.cl_data = ClassDataDefault()
171            self.cl_data.SetLabel(attrs.get((None, 'label'), ""))
172        start_dispatcher['clnull'] = "start_clnull"
173    
174        def end_clnull(self, name, qname):
175            self.aLayer.GetClassification().SetDefaultData(self.cl_data)
176            del self.cl_data
177        end_dispatcher['clnull'] = "end_clnull"
178    
179        def start_clpoint(self, name, qname, attrs):
180            attrib_value = attrs.get((None, 'value'), "0")
181    
182            try:
183                value  = Str2Num(attrib_value)
184            except:
185                value  = attrib_value
186    
187            self.cl_data = ClassDataPoint(value)
188            self.cl_data.SetLabel(attrs.get((None, 'label'), ""))
189    
190        start_dispatcher['clpoint'] = "start_clpoint"
191    
192        def end_clpoint(self, name, qname):
193            self.aLayer.GetClassification().AddClassData(self.cl_data)
194            del self.cl_data
195        end_dispatcher['clpoint'] = "end_clpoint"
196    
197        def start_clrange(self, name, qname, attrs):
198    
199            try:
200                min = Str2Num(attrs.get((None, 'min'), "0"))
201                max = Str2Num(attrs.get((None, 'max'), "0"))
202            except ValueError:
203                raise ValueError(_("Classification range is not a number!"))
204    
205            self.cl_data = ClassDataRange(min, max)
206            self.cl_data.SetLabel(attrs.get((None, 'label'), ""))
207    
208        start_dispatcher['clrange'] = "start_clrange"
209    
210        def end_clrange(self, name, qname):
211            self.aLayer.GetClassification().AddClassData(self.cl_data)
212            del self.cl_data
213        end_dispatcher['clrange'] = "end_clrange"
214    
215        def start_cldata(self, name, qname, attrs):
216            self.cl_data.SetStroke(parse_color(attrs.get((None, 'stroke'), "None")))
217            self.cl_data.SetStrokeWidth(
218                int(attrs.get((None, 'stroke_width'), "0")))
219            self.cl_data.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
220        start_dispatcher['cldata'] = "start_cldata"
221    
222        def end_cldata(self, name, qname):
223            pass
224        end_dispatcher['cldata'] = "end_cldata"
225    
226        def start_table(self, name, qname, attrs):
227            print "table title: %s" % attrs.get('title', None)
228        start_dispatcher['table'] = "start_table"
229    
230        def end_table(self, name, qname):
231            pass
232        end_dispatcher['table'] = "end_table"
233    
234        def start_labellayer(self, name, qname, attrs):
235            self.aLayer = self.aMap.LabelLayer()
236        start_dispatcher['labellayer'] = "start_labellayer"
237    
238        def start_label(self, name, qname, attrs):
239            x = float(attrs[(None, 'x')])
240            y = float(attrs[(None, 'y')])
241            text = attrs[(None, 'text')]
242            halign = attrs[(None, 'halign')]
243            valign = attrs[(None, 'valign')]
244            self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
245        start_dispatcher['label'] = "start_label"
246    
247        def characters(self, chars):
248            pass
249    
250    
251  def load_session(filename):  def load_session(filename):
252      """Load a Thuban session from the file object file"""      """Load a Thuban session from the file object file"""
# Line 157  def load_session(filename): Line 254  def load_session(filename):
254      file = open(filename)      file = open(filename)
255      handler = ProcessSession(dir)      handler = ProcessSession(dir)
256    
257      if oldPython:      parser = make_parser()
258          parser = make_parser()      parser.setContentHandler(handler)
259          parser.setDocumentHandler(handler)      parser.setErrorHandler(ErrorHandler())
260          parser.setErrorHandler(saxutils.ErrorPrinter())      parser.setFeature(xml.sax.handler.feature_namespaces, 1)
261          parser.parseFile(file)      parser.parse(file)
262          parser.close()  
     else:  
         xml.sax.parse(file,handler)  
263      session = handler.theSession      session = handler.theSession
264      # Newly loaded session aren't modified      # Newly loaded session aren't modified
265      session.UnsetModified()      session.UnsetModified()
266    
267      return session      return session
268    
 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.75  
changed lines
  Added in v.413

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26