blob: fe13bdebcf4c7d0bed794b221b9ff757b551e9cb [file] [log] [blame]
Fred Drakea12adfe2000-09-18 17:40:22 +00001"""\
2A library of useful helper classes to the SAX classes, for the
Fred Drake45cd9de2000-06-29 19:34:54 +00003convenience of application and driver writers.
Fred Drake45cd9de2000-06-29 19:34:54 +00004"""
5
Fred Drake45cd9de2000-06-29 19:34:54 +00006import handler
Lars Gustäbelfc643c32000-09-24 10:53:31 +00007import xmlreader
Fred Drakea12adfe2000-09-18 17:40:22 +00008
9def escape(data, entities={}):
Fred Drake45cd9de2000-06-29 19:34:54 +000010 """Escape &, <, and > in a string of data.
Fred Drakea12adfe2000-09-18 17:40:22 +000011
Fred Drake45cd9de2000-06-29 19:34:54 +000012 You can escape other strings of data by passing a dictionary as
13 the optional entities parameter. The keys and values must all be
14 strings; each key will be replaced with its corresponding value.
15 """
Fred Drakea12adfe2000-09-18 17:40:22 +000016 data = data.replace("&", "&amp;")
17 data = data.replace("<", "&lt;")
18 data = data.replace(">", "&gt;")
Fred Drake45cd9de2000-06-29 19:34:54 +000019 for chars, entity in entities.items():
Fred Drakea12adfe2000-09-18 17:40:22 +000020 data = data.replace(chars, entity)
Fred Drake45cd9de2000-06-29 19:34:54 +000021 return data
22
Fred Drakea12adfe2000-09-18 17:40:22 +000023
Fred Drake45cd9de2000-06-29 19:34:54 +000024class XMLGenerator(handler.ContentHandler):
25
Lars Gustäbelc5cec512000-09-21 08:25:28 +000026 def __init__(self, out=None, encoding="iso-8859-1"):
Fred Drakea12adfe2000-09-18 17:40:22 +000027 if out is None:
28 import sys
29 out = sys.stdout
Fred Drake45cd9de2000-06-29 19:34:54 +000030 handler.ContentHandler.__init__(self)
31 self._out = out
Lars Gustäbelc5cec512000-09-21 08:25:28 +000032 self._ns_contexts = [{}] # contains uri -> prefix dicts
33 self._current_context = self._ns_contexts[-1]
Lars Gustäbelfc643c32000-09-24 10:53:31 +000034 self._undeclared_ns_maps = []
Lars Gustäbelc5cec512000-09-21 08:25:28 +000035 self._encoding = encoding
Fred Drake45cd9de2000-06-29 19:34:54 +000036
37 # ContentHandler methods
Fred Drakea12adfe2000-09-18 17:40:22 +000038
Fred Drake45cd9de2000-06-29 19:34:54 +000039 def startDocument(self):
Lars Gustäbelc5cec512000-09-21 08:25:28 +000040 self._out.write('<?xml version="1.0" encoding="%s"?>\n' %
41 self._encoding)
Fred Drake45cd9de2000-06-29 19:34:54 +000042
43 def startPrefixMapping(self, prefix, uri):
Lars Gustäbelc5cec512000-09-21 08:25:28 +000044 self._ns_contexts.append(self._current_context.copy())
45 self._current_context[uri] = prefix
Lars Gustäbelfc643c32000-09-24 10:53:31 +000046 self._undeclared_ns_maps.append((prefix, uri))
Fred Drake45cd9de2000-06-29 19:34:54 +000047
48 def endPrefixMapping(self, prefix):
Lars Gustäbelfc643c32000-09-24 10:53:31 +000049 self._current_context = self._ns_contexts[-1]
50 del self._ns_contexts[-1]
Fred Drake45cd9de2000-06-29 19:34:54 +000051
52 def startElement(self, name, attrs):
Fred Drake45cd9de2000-06-29 19:34:54 +000053 self._out.write('<' + name)
54 for (name, value) in attrs.items():
55 self._out.write(' %s="%s"' % (name, escape(value)))
56 self._out.write('>')
Lars Gustäbelc5cec512000-09-21 08:25:28 +000057
Fred Drake45cd9de2000-06-29 19:34:54 +000058 def endElement(self, name):
Fred Drake45cd9de2000-06-29 19:34:54 +000059 self._out.write('</%s>' % name)
60
Lars Gustäbelc5cec512000-09-21 08:25:28 +000061 def startElementNS(self, name, qname, attrs):
62 name = self._current_context[name[0]] + ":" + name[1]
63 self._out.write('<' + name)
Lars Gustäbelfc643c32000-09-24 10:53:31 +000064
65 for pair in self._undeclared_ns_maps:
66 self._out.write(' xmlns:%s="%s"' % pair)
67 self._undeclared_ns_maps = []
68
Lars Gustäbelc5cec512000-09-21 08:25:28 +000069 for (name, value) in attrs.items():
70 name = self._current_context[name[0]] + ":" + name[1]
71 self._out.write(' %s="%s"' % (name, escape(value)))
72 self._out.write('>')
73
74 def endElementNS(self, name, qname):
75 name = self._current_context[name[0]] + ":" + name[1]
76 self._out.write('</%s>' % name)
77
Fred Drake45cd9de2000-06-29 19:34:54 +000078 def characters(self, content):
79 self._out.write(escape(content))
80
81 def ignorableWhitespace(self, content):
82 self._out.write(content)
Fred Drakea12adfe2000-09-18 17:40:22 +000083
Fred Drake45cd9de2000-06-29 19:34:54 +000084 def processingInstruction(self, target, data):
85 self._out.write('<?%s %s?>' % (target, data))
86
Fred Drakea12adfe2000-09-18 17:40:22 +000087
Lars Gustäbelfc643c32000-09-24 10:53:31 +000088class XMLFilterBase(xmlreader.XMLReader):
Fred Drake45cd9de2000-06-29 19:34:54 +000089 """This class is designed to sit between an XMLReader and the
90 client application's event handlers. By default, it does nothing
91 but pass requests up to the reader and events on to the handlers
92 unmodified, but subclasses can override specific methods to modify
93 the event stream or the configuration requests as they pass
94 through."""
95
96 # ErrorHandler methods
97
98 def error(self, exception):
99 self._err_handler.error(exception)
100
101 def fatalError(self, exception):
102 self._err_handler.fatalError(exception)
103
104 def warning(self, exception):
105 self._err_handler.warning(exception)
106
107 # ContentHandler methods
Fred Drakea12adfe2000-09-18 17:40:22 +0000108
Fred Drake45cd9de2000-06-29 19:34:54 +0000109 def setDocumentLocator(self, locator):
110 self._cont_handler.setDocumentLocator(locator)
Fred Drakea12adfe2000-09-18 17:40:22 +0000111
Fred Drake45cd9de2000-06-29 19:34:54 +0000112 def startDocument(self):
113 self._cont_handler.startDocument()
114
115 def endDocument(self):
116 self._cont_handler.endDocument()
117
118 def startPrefixMapping(self, prefix, uri):
119 self._cont_handler.startPrefixMapping(prefix, uri)
120
121 def endPrefixMapping(self, prefix):
122 self._cont_handler.endPrefixMapping(prefix)
123
124 def startElement(self, name, attrs):
125 self._cont_handler.startElement(name, attrs)
126
Lars Gustäbelc5cec512000-09-21 08:25:28 +0000127 def endElement(self, name):
128 self._cont_handler.endElement(name)
129
130 def startElementNS(self, name, qname, attrs):
131 self._cont_handler.startElement(name, attrs)
132
133 def endElementNS(self, name, qname):
134 self._cont_handler.endElementNS(name, qname)
Fred Drake45cd9de2000-06-29 19:34:54 +0000135
136 def characters(self, content):
137 self._cont_handler.characters(content)
138
Lars Gustäbelfc643c32000-09-24 10:53:31 +0000139 def ignorableWhitespace(self, chars):
140 self._cont_handler.ignorableWhitespace(chars)
Fred Drake45cd9de2000-06-29 19:34:54 +0000141
142 def processingInstruction(self, target, data):
143 self._cont_handler.processingInstruction(target, data)
144
145 def skippedEntity(self, name):
146 self._cont_handler.skippedEntity(name)
147
148 # DTDHandler methods
149
150 def notationDecl(self, name, publicId, systemId):
151 self._dtd_handler.notationDecl(name, publicId, systemId)
152
153 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
154 self._dtd_handler.unparsedEntityDecl(name, publicId, systemId, ndata)
155
156 # EntityResolver methods
157
158 def resolveEntity(self, publicId, systemId):
159 self._ent_handler.resolveEntity(publicId, systemId)
160
161 # XMLReader methods
162
163 def parse(self, source):
164 self._parent.setContentHandler(self)
165 self._parent.setErrorHandler(self)
166 self._parent.setEntityResolver(self)
167 self._parent.setDTDHandler(self)
168 self._parent.parse(source)
169
170 def setLocale(self, locale):
171 self._parent.setLocale(locale)
Fred Drakea12adfe2000-09-18 17:40:22 +0000172
Fred Drake45cd9de2000-06-29 19:34:54 +0000173 def getFeature(self, name):
174 return self._parent.getFeature(name)
175
176 def setFeature(self, name, state):
177 self._parent.setFeature(name, state)
178
179 def getProperty(self, name):
180 return self._parent.getProperty(name)
181
182 def setProperty(self, name, value):
183 self._parent.setProperty(name, value)