/[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 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              s = attrs.get('value')          if method_name is not None:
95              s = str(s) # we can't handle unicode in proj              getattr(self, method_name)(name, qname, attrs)
96              self.ProjectionParams.append(s)  
97          elif name == 'layer':      def endElementNS(self, name, qname):
98              title = attrs.get('title', "")          """Call the method given for name in self.end_dispatcher
99              filename = attrs.get('filename', "")          """
100              filename = os.path.join(self.directory, filename)          if name[0] is None:
101              fill = parse_color(attrs.get('fill', "None"))              method_name = self.end_dispatcher.get(name[1])
102              stroke = parse_color(attrs.get('stroke', "#000000"))          else:
103              stroke_width = int(attrs.get("stroke_width", "1"))              # Dispatch with namespace
104              self.aLayer = Layer(title, filename, fill = fill, stroke = stroke,              method_name = self.end_dispatcher.get(name)
105                                  stroke_width = stroke_width)          if method_name is not None:
106          elif name == 'table':              getattr(self, method_name)(name, qname)
107              print "table title: %s" % attrs.get('title', None)  
108          elif name == 'labellayer':      def start_session(self, name, qname, attrs):
109              self.aLayer = self.aMap.LabelLayer()          self.theSession = Session(attrs.get((None, 'title'), None))
110          elif name == 'label':      start_dispatcher['session'] = "start_session"
111              x = float(attrs['x'])  
112              y = float(attrs['y'])      def end_session(self, name, qname):
113              text = attrs['text']          pass
114              halign = attrs['halign']      end_dispatcher['session'] = "end_session"
115              valign = attrs['valign']  
116              self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)      def start_map(self, name, qname, attrs):
117                    """Start a map."""
118            self.aMap = Map(attrs.get((None, 'title'), None))
119      if not oldPython and test_for_broken_SAX():      start_dispatcher['map'] = "start_map"
120          # works with python 2.0, but is not SAX compliant  
121          def characters(self, ch):      def end_map(self, name, qname):
122              self.my_characters(ch)          self.theSession.AddMap(self.aMap)
123      else:      end_dispatcher['map'] = "end_map"
124          # SAX compliant  
125          def characters(self, ch, start, length):      def start_projection(self, name, qname, attrs):
126              self.my_characters(ch[start:start+length])          self.ProjectionParams = [ ]
127        start_dispatcher['projection'] = "start_projection"
128      def my_characters(self, ch):  
129          self.chars = self.chars + ch      def end_projection(self, name, qname):
130            self.aMap.SetProjection(Projection(self.ProjectionParams))
131      def endElement(self, name):      end_dispatcher['projection'] = "end_projection"
132          # If it's not a parameter element, ignore it  
133          if name == 'session':      def start_parameter(self, name, qname, attrs):
134              #print "end of session"          s = attrs.get((None, 'value'))
135              pass          s = str(s) # we can't handle unicode in proj
136          if name == 'map':          self.ProjectionParams.append(s)
137              self.theSession.AddMap(self.aMap)      start_dispatcher['parameter'] = "start_parameter"
138          if name == 'projection':  
139              self.aMap.SetProjection(Projection(self.ProjectionParams))      def start_layer(self, name, qname, attrs, layer_class = Layer):
140          if name == 'layer':          """Start a layer
141              self.aMap.AddLayer(self.aLayer)  
142          if name == 'table':          Instantiate a layer of class layer_class from the attributes in
143              #print "end of table"          attrs which may be a dictionary as well as the normal SAX attrs
144              pass          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 159  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.105  
changed lines
  Added in v.413

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26