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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26