home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 2004 #2 / K-CD-2-2004.ISO / OpenOffice Sv / f_0397 / python-core-2.2.2 / lib / xml / sax / saxutils.py < prev    next >
Encoding:
Python Source  |  2003-07-18  |  7.9 KB  |  261 lines

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