File: xmlwriter.py

package info (click to toggle)
thuban 1.2.2-14
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 9,176 kB
  • sloc: python: 30,410; ansic: 6,181; xml: 4,234; cpp: 1,595; makefile: 145
file content (132 lines) | stat: -rw-r--r-- 4,173 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Copyright (c) 2003, 2005 by Intevation GmbH
# Authors:
# Jonathan Coles <jonathan@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

"""
Functions to save an XML file
"""

__version__ = "$Revision: 2642 $"

import os
from types import UnicodeType

from Thuban import unicode_from_internal

#
# one level of indention
#
TAB = "    "

def escape(data):
    """Escape &, \", ', <, and > in a string of data.
    """
    data = data.replace("&", "&amp;")
    data = data.replace("<", "&lt;")
    data = data.replace(">", "&gt;")
    data = data.replace('"', "&quot;")
    data = data.replace("'", "&apos;")
    return data

class XMLWriter:
    """Abstract XMLWriter.

    Should be overridden to provide specific object saving functionality.
    """

    def __init__(self):
        self.filename = None
        pass

    def write(self, file_or_filename):
        """Write the session to a file.

        The argument may be either a file object or a filename. If it's
        a filename, the file will be opened for writing. Files of
        shapefiles will be stored as filenames relative to the directory
        the file is stored in (as given by os.path.dirname(filename)) if
        they have a common parent directory other than the root
        directory.

        If the argument is a file object (which is determined by the
        presence of a write method) all filenames will be absolute
        filenames.
        """

        # keep track of how many levels of indentation to write
        self.indent_level = 0 
        # track whether an element is currently open. see open_element().
        self.element_open = 0

        if hasattr(file_or_filename, "write"):
            # it's a file object
            self.file = file_or_filename
            self.dir = ""
        else:
            self.filename = file_or_filename
            self.dir = os.path.dirname(self.filename)
            self.file = open(self.filename, 'w')

    def close(self):
        assert self.indent_level == 0
        if self.filename is not None:
            self.file.close()

    def write_header(self, doctype, system):
        """Write the XML header"""
        self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        self.file.write('<!DOCTYPE %s SYSTEM "%s">\n' % (doctype, system))

    def open_element(self, element, attrs = {}):

        #
        # we note when an element is opened so that if two open_element()
        # calls are made successively we can end the currently open
        # tag and will later write a proper close tag. otherwise,
        # if a close_element() call is made directly after an open_element()
        # call we will close the tag with a />
        #
        if self.element_open == 1:
            self.file.write(">\n")

        self.element_open = 1

        # Helper function to write an element open tag with attributes
        self.file.write("%s<%s" % (TAB*self.indent_level, element))
        self.__write_attribs(attrs)

        self.indent_level += 1

    def close_element(self, element):
        self.indent_level -= 1
        assert self.indent_level >= 0

        # see open_element() for an explanation
        if self.element_open == 1:
            self.element_open = 0
            self.file.write("/>\n")
        else:
            self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))

    def write_element(self, element, attrs = {}):
        """write an element that won't need a closing tag"""
        self.open_element(element, attrs)
        self.close_element(element)

    def __write_attribs(self, attrs):
        for name, value in attrs.items():
            self.file.write(' %s="%s"' % (self.encode(name), 
                                          self.encode(value)))

    def encode(self, s):
        """Return an XML-escaped and UTF-8 encoded copy of the string s.

        The parameter must be a string in Thuban's internal string
        representation or a unicode object.
        """
        if not isinstance(s, unicode):
            s = unicode_from_internal(s)
        return escape(s).encode("utf8")