/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/save.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/save.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 366 by jonathan, Mon Jan 27 11:48:17 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]>  # Bernhard Herzog <[email protected]>
# Line 15  __version__ = "$Revision$" Line 15  __version__ = "$Revision$"
15  import os  import os
16  import string  import string
17    
18  from Thuban.Lib.fileutil import relative_filename  import Thuban.Lib.fileutil
19    
20    from Thuban.Model.color import Color
21    
22    #
23    # one level of indention
24    #
25    TAB = "    "
26    
27    def relative_filename(dir, filename):
28        """Return a filename relative to dir for the absolute file name absname.
29    
30        This is almost the same as the function in fileutil, except that dir
31        can be an empty string in which case filename will be returned
32        unchanged.
33        """
34        if dir:
35            return Thuban.Lib.fileutil.relative_filename(dir, filename)
36        else:
37            return filename
38    
39  def escape(data):  def escape(data):
40      """Escape &, \", ', <, and > in a string of data.      """Escape &, \", ', <, and > in a string of data.
# Line 27  def escape(data): Line 46  def escape(data):
46      data = string.replace(data, "'", "&apos;")      data = string.replace(data, "'", "&apos;")
47      return data      return data
48    
49  def save_session(session, filename):  class Saver:
     """Save the session session to the file given by filename"""  
     dir = os.path.dirname(filename)  
     file = open(filename, 'w')  
     write = file.write  
     write('<?xml version="1.0" encoding="UTF-8"?>\n')  
     write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')  
     write('<session title="%s">\n' % escape(session.title))  
     for map in session.Maps():  
         write('\t<map title="%s">\n' % escape(map.title))  
         if map.projection and len(map.projection.params) > 0:  
             write('\t\t<projection>\n')  
             for param in map.projection.params:  
                 write('\t\t\t<parameter value="%s"/>\n' % escape(param))  
             write('\t\t</projection>\n')  
50    
51          for layer in map.Layers():      """Class to serialize a session into an XML file.
52              fill = layer.fill  
53              if fill is None:      Applications built on top of Thuban may derive from this class and
54                  fill = "None"      override or extend the methods to save additinal information. This
55              else:      additional information should take the form of additional attributes
56                  fill = fill.hex()      or elements whose names are prefixed with a namespace. To define a
57              stroke = layer.stroke      namespace derived classes should extend the write_session method to
58              if stroke is None:      pass the namespaces to the default implementation.
59                  stroke = "None"      """
60    
61    
62        def __init__(self, session):
63            self.session = session
64    
65        def write(self, file_or_filename):
66            """Write the session to a file.
67    
68            The argument may be either a file object or a filename. If it's
69            a filename, the file will be opened for writing. Files of
70            shapefiles will be stored as filenames relative to the directory
71            the file is stored in (as given by os.path.dirname(filename)) if
72            they have a common parent directory other than the root
73            directory.
74    
75            If the argument is a file object (which is determined by the
76            presence of a write method) all filenames will be absolut
77            filenames.
78            """
79    
80            self.indent_level = 0
81    
82            if hasattr(file_or_filename, "write"):
83                # it's a file object
84                self.file = file_or_filename
85                self.dir = ""
86            else:
87                filename = file_or_filename
88                self.dir = os.path.dirname(filename)
89                self.file = open(filename, 'w')
90            self.write_header()
91            self.write_session(self.session)
92    
93            if self.indent_level != 0:
94                raise ValueError("indent_level still positive!")
95    
96        def write_attribs(self, attrs):
97            for name, value in attrs.items():
98                if isinstance(value, Color):
99                    value = value.hex()
100              else:              else:
101                  stroke = stroke.hex()                  value = str(value)
102              write(('\t\t<layer title="%s" filename="%s"'              self.file.write(' %s="%s"' % (escape(name), escape(value)))
103                     ' fill="%s" stroke="%s"/>\n') %      
104                    (escape(layer.title),      def open_element(self, element, attrs = {}):
105                     escape(relative_filename(dir, layer.filename)),          # Helper function to write an element open tag with attributes
106                     fill, stroke))          self.file.write("%s<%s" % (TAB*self.indent_level, element))
107          labels = map.LabelLayer().Labels()          self.write_attribs(attrs)
108            self.file.write(">\n")
109    
110            self.indent_level += 1
111    
112        def close_element(self, element):
113            self.indent_level -= 1
114            if self.indent_level < 0:
115                raise ValueError("close_element called too many times!")
116            self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))
117    
118        def write_element(self, element, attrs = {}):
119            # Helper function to write an element open tag with attributes
120            self.file.write("%s<%s" % (TAB*self.indent_level, element))
121            self.write_attribs(attrs)
122            self.file.write("/>\n")
123    
124        def write_header(self):
125            """Write the XML header"""
126            self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
127            self.file.write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')
128    
129        def write_session(self, session, attrs = None, namespaces = ()):
130            """Write the session and its contents
131    
132            By default, write a session element with the title attribute and
133            call write_map for each map contained in the session.
134    
135            The optional argument attrs is for additional attributes and, if
136            given, should be a mapping from attribute names to attribute
137            values. The values should not be XML-escaped yet.
138    
139            The optional argument namespaces, if given, should be a sequence
140            of (name, URI) pairs. The namespaces are written as namespace
141            attributes into the session element. This is mainly useful for
142            derived classes that need to store additional information in a
143            thuban session file.
144            """
145            if attrs is None:
146                attrs = {}
147            attrs["title"] = session.title
148            for name, uri in namespaces:
149                attrs["xmlns:" + name] = uri
150            self.open_element("session", attrs)
151            for map in session.Maps():
152                self.write_map(map)
153            self.close_element("session")
154    
155        def write_map(self, map):
156            """Write the map and its contents.
157    
158            By default, write a map element element with the title
159            attribute, call write_projection to write the projection
160            element, call write_layer for each layer contained in the map
161            and finally call write_label_layer to write the label layer.
162            """
163            write = self.file.write
164            self.open_element('map title="%s"' % escape(map.title))
165            self.write_projection(map.projection)
166            for layer in map.Layers():
167                self.write_layer(layer)
168            self.write_label_layer(map.LabelLayer())
169            self.close_element('map')
170    
171        def write_projection(self, projection):
172            """Write the projection.
173            """
174            if projection and len(projection.params) > 0:
175                self.open_element("projection")
176                for param in projection.params:
177                    self.write_element('parameter value="%s"' % escape(param))
178                self.close_element("projection")
179    
180        def write_layer(self, layer, attrs = None):
181            """Write the layer.
182    
183            The optional argument attrs is for additional attributes and, if
184            given, should be a mapping from attribute names to attribute
185            values. The values should not be XML-escaped yet.
186            """
187            if attrs is None:
188                attrs = {}
189            attrs["title"] = layer.title
190            attrs["filename"] = relative_filename(self.dir, layer.filename)
191            attrs["stroke_width"] = str(layer.stroke_width)
192            fill = layer.fill
193            if fill is None:
194                attrs["fill"] = "None"
195            else:
196                attrs["fill"] = fill.hex()
197            stroke = layer.stroke
198            if stroke is None:
199                attrs["stroke"] = "None"
200            else:
201                attrs["stroke"] = stroke.hex()
202    
203            self.open_element("layer", attrs)
204            self.write_classification(layer)
205            self.close_element("layer")
206    
207        def write_classification(self, layer, attrs = None):
208            if attrs is None:
209                attrs = {}
210    
211            lc = layer.classification
212    
213            field = lc.field
214    
215            #
216            # there isn't a classification of anything
217            # so don't do anything
218            #
219            if field is None: return
220    
221            attrs["field"] = field
222            self.open_element("classification", attrs)
223    
224            if lc.NullData is not None:
225                self.open_element("clnull")
226                self.write_element("cldata", lc.NullData)
227                self.close_element("clnull")
228    
229            if lc.points != {}:
230                for value, data in lc.points.items():
231                    self.open_element('clpoint value="%s"' % (escape(str(value))))
232                    self.write_element("cldata", data)
233                    self.close_element('clpoint')
234              
235            if lc.ranges != []:
236                for p in lc.ranges:
237                    self.open_element('clrange min="%s" max="%s"'
238                        % (escape(str(p[0])), escape(str(p[1]))))
239                    self.write_element("cldata", p[2])
240                    self.close_element('clrange')
241    
242            self.close_element("classification")
243    
244        def write_label_layer(self, layer):
245            """Write the label layer.
246            """
247            labels = layer.Labels()
248          if labels:          if labels:
249              write('\t\t<labellayer>\n')              self.open_element('labellayer')
250              for label in labels:              for label in labels:
251                  write(('\t\t\t<label x="%g" y="%g" text="%s"'                  self.write_element(('label x="%g" y="%g" text="%s"'
252                         ' halign="%s" valign="%s"/>\n')                                      ' halign="%s" valign="%s"')
253                        % (label.x, label.y, label.text, label.halign,                                  % (label.x, label.y, label.text, label.halign,
254                           label.valign))                                     label.valign))
255              write('\t\t</labellayer>\n')              self.close_element('labellayer')
256          write('\t</map>\n')  
257      write('</session>\n')  
258    
259    def save_session(session, file, saver_class = None):
260        """Save the session session to a file.
261    
262        The file argument may either be a filename or an open file object.
263    
264        The optional argument saver_class is the class to use to serialize
265        the session. By default or if it's None, the saver class will be
266        Saver.
267    
268        If writing the session is successful call the session's
269        UnsetModified method
270        """
271        if saver_class is None:
272            saver_class = Saver
273        saver = saver_class(session)
274        saver.write(file)
275    
276      # after a successful save consider the session unmodified.      # after a successful save consider the session unmodified.
277      session.UnsetModified()      session.UnsetModified()

Legend:
Removed from v.6  
changed lines
  Added in v.366

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26