Package xml :: Package sax :: Module saxutils
[hide private]
[frames] | no frames]

Source Code for Module xml.sax.saxutils

  1  """\ 
  2  A library of useful helper classes to the SAX classes, for the 
  3  convenience of application and driver writers. 
  4  """ 
  5   
  6  import os, urlparse, urllib, types 
  7  import handler 
  8  import xmlreader 
  9   
 10  try: 
 11      _StringTypes = [types.StringType, types.UnicodeType] 
 12  except AttributeError: 
 13      _StringTypes = [types.StringType] 
 14   
 15  # See whether the xmlcharrefreplace error handler is 
 16  # supported 
 17  try: 
 18      from codecs import xmlcharrefreplace_errors 
 19      _error_handling = "xmlcharrefreplace" 
 20      del xmlcharrefreplace_errors 
 21  except ImportError: 
 22      _error_handling = "strict" 
 23   
24 -def __dict_replace(s, d):
25 """Replace substrings of a string using a dictionary.""" 26 for key, value in d.items(): 27 s = s.replace(key, value) 28 return s
29
30 -def escape(data, entities={}):
31 """Escape &, <, and > in a string of data. 32 33 You can escape other strings of data by passing a dictionary as 34 the optional entities parameter. The keys and values must all be 35 strings; each key will be replaced with its corresponding value. 36 """ 37 38 # must do ampersand first 39 data = data.replace("&", "&amp;") 40 data = data.replace(">", "&gt;") 41 data = data.replace("<", "&lt;") 42 if entities: 43 data = __dict_replace(data, entities) 44 return data
45
46 -def unescape(data, entities={}):
47 """Unescape &amp;, &lt;, and &gt; in a string of data. 48 49 You can unescape other strings of data by passing a dictionary as 50 the optional entities parameter. The keys and values must all be 51 strings; each key will be replaced with its corresponding value. 52 """ 53 data = data.replace("&lt;", "<") 54 data = data.replace("&gt;", ">") 55 if entities: 56 data = __dict_replace(data, entities) 57 # must do ampersand last 58 return data.replace("&amp;", "&")
59
60 -def quoteattr(data, entities={}):
61 """Escape and quote an attribute value. 62 63 Escape &, <, and > in a string of data, then quote it for use as 64 an attribute value. The \" character will be escaped as well, if 65 necessary. 66 67 You can escape other strings of data by passing a dictionary as 68 the optional entities parameter. The keys and values must all be 69 strings; each key will be replaced with its corresponding value. 70 """ 71 entities = entities.copy() 72 entities.update({'\n': '&#10;', '\r': '&#13;', '\t':'&#9;'}) 73 data = escape(data, entities) 74 if '"' in data: 75 if "'" in data: 76 data = '"%s"' % data.replace('"', "&quot;") 77 else: 78 data = "'%s'" % data 79 else: 80 data = '"%s"' % data 81 return data
82 83
84 -class XMLGenerator(handler.ContentHandler):
85
86 - def __init__(self, out=None, encoding="iso-8859-1"):
87 if out is None: 88 import sys 89 out = sys.stdout 90 handler.ContentHandler.__init__(self) 91 self._out = out 92 self._ns_contexts = [{}] # contains uri -> prefix dicts 93 self._current_context = self._ns_contexts[-1] 94 self._undeclared_ns_maps = [] 95 self._encoding = encoding
96
97 - def _write(self, text):
98 if isinstance(text, str): 99 self._out.write(text) 100 else: 101 self._out.write(text.encode(self._encoding, _error_handling))
102 103 # ContentHandler methods 104
105 - def startDocument(self):
106 self._write('<?xml version="1.0" encoding="%s"?>\n' % 107 self._encoding)
108
109 - def startPrefixMapping(self, prefix, uri):
110 self._ns_contexts.append(self._current_context.copy()) 111 self._current_context[uri] = prefix 112 self._undeclared_ns_maps.append((prefix, uri))
113
114 - def endPrefixMapping(self, prefix):
115 self._current_context = self._ns_contexts[-1] 116 del self._ns_contexts[-1]
117
118 - def startElement(self, name, attrs):
119 self._write('<' + name) 120 for (name, value) in attrs.items(): 121 self._write(' %s=%s' % (name, quoteattr(value))) 122 self._write('>')
123
124 - def endElement(self, name):
125 self._write('</%s>' % name)
126
127 - def startElementNS(self, name, qname, attrs):
128 if name[0] is None: 129 # if the name was not namespace-scoped, use the unqualified part 130 name = name[1] 131 else: 132 # else try to restore the original prefix from the namespace 133 name = self._current_context[name[0]] + ":" + name[1] 134 self._write('<' + name) 135 136 for pair in self._undeclared_ns_maps: 137 self._write(' xmlns:%s="%s"' % pair) 138 self._undeclared_ns_maps = [] 139 140 for (name, value) in attrs.items(): 141 name = self._current_context[name[0]] + ":" + name[1] 142 self._write(' %s=%s' % (name, quoteattr(value))) 143 self._write('>')
144
145 - def endElementNS(self, name, qname):
146 if name[0] is None: 147 name = name[1] 148 else: 149 name = self._current_context[name[0]] + ":" + name[1] 150 self._write('</%s>' % name)
151
152 - def characters(self, content):
153 self._write(escape(content))
154
155 - def ignorableWhitespace(self, content):
156 self._write(content)
157
158 - def processingInstruction(self, target, data):
159 self._write('<?%s %s?>' % (target, data))
160 161
162 -class XMLFilterBase(xmlreader.XMLReader):
163 """This class is designed to sit between an XMLReader and the 164 client application's event handlers. By default, it does nothing 165 but pass requests up to the reader and events on to the handlers 166 unmodified, but subclasses can override specific methods to modify 167 the event stream or the configuration requests as they pass 168 through.""" 169
170 - def __init__(self, parent = None):
171 xmlreader.XMLReader.__init__(self) 172 self._parent = parent
173 174 # ErrorHandler methods 175
176 - def error(self, exception):
177 self._err_handler.error(exception)
178
179 - def fatalError(self, exception):
180 self._err_handler.fatalError(exception)
181
182 - def warning(self, exception):
183 self._err_handler.warning(exception)
184 185 # ContentHandler methods 186
187 - def setDocumentLocator(self, locator):
188 self._cont_handler.setDocumentLocator(locator)
189
190 - def startDocument(self):
191 self._cont_handler.startDocument()
192
193 - def endDocument(self):
194 self._cont_handler.endDocument()
195
196 - def startPrefixMapping(self, prefix, uri):
197 self._cont_handler.startPrefixMapping(prefix, uri)
198
199 - def endPrefixMapping(self, prefix):
200 self._cont_handler.endPrefixMapping(prefix)
201
202 - def startElement(self, name, attrs):
203 self._cont_handler.startElement(name, attrs)
204
205 - def endElement(self, name):
206 self._cont_handler.endElement(name)
207
208 - def startElementNS(self, name, qname, attrs):
209 self._cont_handler.startElementNS(name, qname, attrs)
210
211 - def endElementNS(self, name, qname):
212 self._cont_handler.endElementNS(name, qname)
213
214 - def characters(self, content):
215 self._cont_handler.characters(content)
216
217 - def ignorableWhitespace(self, chars):
218 self._cont_handler.ignorableWhitespace(chars)
219
220 - def processingInstruction(self, target, data):
221 self._cont_handler.processingInstruction(target, data)
222
223 - def skippedEntity(self, name):
224 self._cont_handler.skippedEntity(name)
225 226 # DTDHandler methods 227
228 - def notationDecl(self, name, publicId, systemId):
229 self._dtd_handler.notationDecl(name, publicId, systemId)
230
231 - def unparsedEntityDecl(self, name, publicId, systemId, ndata):
232 self._dtd_handler.unparsedEntityDecl(name, publicId, systemId, ndata)
233 234 # EntityResolver methods 235
236 - def resolveEntity(self, publicId, systemId):
237 return self._ent_handler.resolveEntity(publicId, systemId)
238 239 # XMLReader methods 240
241 - def parse(self, source):
242 self._parent.setContentHandler(self) 243 self._parent.setErrorHandler(self) 244 self._parent.setEntityResolver(self) 245 self._parent.setDTDHandler(self) 246 self._parent.parse(source)
247
248 - def setLocale(self, locale):
249 self._parent.setLocale(locale)
250
251 - def getFeature(self, name):
252 return self._parent.getFeature(name)
253
254 - def setFeature(self, name, state):
255 self._parent.setFeature(name, state)
256
257 - def getProperty(self, name):
258 return self._parent.getProperty(name)
259
260 - def setProperty(self, name, value):
261 self._parent.setProperty(name, value)
262 263 # XMLFilter methods 264
265 - def getParent(self):
266 return self._parent
267
268 - def setParent(self, parent):
269 self._parent = parent
270 271 # --- Utility functions 272
273 -def prepare_input_source(source, base = ""):
274 """This function takes an InputSource and an optional base URL and 275 returns a fully resolved InputSource object ready for reading.""" 276 277 if type(source) in _StringTypes: 278 source = xmlreader.InputSource(source) 279 elif hasattr(source, "read"): 280 f = source 281 source = xmlreader.InputSource() 282 source.setByteStream(f) 283 if hasattr(f, "name"): 284 source.setSystemId(f.name) 285 286 if source.getByteStream() is None: 287 sysid = source.getSystemId() 288 basehead = os.path.dirname(os.path.normpath(base)) 289 sysidfilename = os.path.join(basehead, sysid) 290 if os.path.isfile(sysidfilename): 291 source.setSystemId(sysidfilename) 292 f = open(sysidfilename, "rb") 293 else: 294 source.setSystemId(urlparse.urljoin(base, sysid)) 295 f = urllib.urlopen(source.getSystemId()) 296 297 source.setByteStream(f) 298 299 return source
300