/[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 374 by jan, Mon Jan 27 14:20:02 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
 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 = {}
166        start_dispatcher['clnull'] = "start_clnull"
167    
168        def end_clnull(self, name, qname):
169            self.aLayer.classification.setNull(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 = {}
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 = {}
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['stroke'] = parse_color(
208                                     attrs.get((None, 'stroke'), "None"))
209            self.cl_data['stroke_width'] = int(
210                                     attrs.get((None, 'stroke_width'), "0"))
211            self.cl_data['fill'] = parse_color(
212                                     attrs.get((None, 'fill'), "None"))
213        start_dispatcher['cldata'] = "start_cldata"
214    
215        def end_cldata(self, name, qname):
216            pass
217        end_dispatcher['cldata'] = "end_cldata"
218    
219        def start_table(self, name, qname, attrs):
220            print "table title: %s" % attrs.get('title', None)
221        start_dispatcher['table'] = "start_table"
222    
223        def end_table(self, name, qname):
224            pass
225        end_dispatcher['table'] = "end_table"
226    
227        def start_labellayer(self, name, qname, attrs):
228            self.aLayer = self.aMap.LabelLayer()
229        start_dispatcher['labellayer'] = "start_labellayer"
230    
231        def start_label(self, name, qname, attrs):
232            x = float(attrs[(None, 'x')])
233            y = float(attrs[(None, 'y')])
234            text = attrs[(None, 'text')]
235            halign = attrs[(None, 'halign')]
236            valign = attrs[(None, 'valign')]
237            self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
238        start_dispatcher['label'] = "start_label"
239    
240        def characters(self, chars):
241            pass
242    
243    
244  def load_session(filename):  def load_session(filename):
245      """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 247  def load_session(filename):
247      file = open(filename)      file = open(filename)
248      handler = ProcessSession(dir)      handler = ProcessSession(dir)
249    
250      if oldPython:      parser = make_parser()
251          parser = make_parser()      parser.setContentHandler(handler)
252          parser.setDocumentHandler(handler)      parser.setErrorHandler(ErrorHandler())
253          parser.setErrorHandler(saxutils.ErrorPrinter())      parser.setFeature(xml.sax.handler.feature_namespaces, 1)
254          parser.parseFile(file)      parser.parse(file)
255          parser.close()  
     else:  
         xml.sax.parse(file,handler)  
256      session = handler.theSession      session = handler.theSession
257      # Newly loaded session aren't modified      # Newly loaded session aren't modified
258      session.UnsetModified()      session.UnsetModified()
259    
260      return session      return session
261    
 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.374

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26