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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26