home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / webclean / !!!python!!! / BeOpen-Python-2.0.exe / EXPATREADER.PY < prev    next >
Encoding:
Python Source  |  2000-10-14  |  7.6 KB  |  221 lines

  1. """
  2. SAX driver for the Pyexpat C module.  This driver works with
  3. pyexpat.__version__ == '2.22'.
  4. """
  5.  
  6. version = "0.20"
  7.  
  8. from xml.sax._exceptions import *
  9. try:
  10.     from xml.parsers import expat
  11. except ImportError:
  12.     raise SAXReaderNotAvailable("expat not supported",None) 
  13. from xml.sax import xmlreader, saxutils, handler
  14.  
  15. AttributesImpl = xmlreader.AttributesImpl
  16. AttributesNSImpl = xmlreader.AttributesNSImpl
  17.  
  18. import string
  19.  
  20. # --- ExpatParser
  21.  
  22. class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator):
  23.     "SAX driver for the Pyexpat C module."
  24.  
  25.     def __init__(self, namespaceHandling=0, bufsize=2**16-20):
  26.         xmlreader.IncrementalParser.__init__(self, bufsize)
  27.         self._source = xmlreader.InputSource()
  28.         self._parser = None
  29.         self._namespaces = namespaceHandling
  30.         self._parsing = 0
  31.         self._entity_stack = []
  32.  
  33.     # XMLReader methods
  34.  
  35.     def parse(self, source):
  36.         "Parse an XML document from a URL or an InputSource."
  37.         source = saxutils.prepare_input_source(source)
  38.  
  39.         self._source = source
  40.         self.reset()
  41.         self._cont_handler.setDocumentLocator(self)
  42.         xmlreader.IncrementalParser.parse(self, source)            
  43.  
  44.     def prepareParser(self, source):
  45.         if source.getSystemId() != None:
  46.             self._parser.SetBase(source.getSystemId())
  47.         
  48.     def getFeature(self, name):
  49.         if name == handler.feature_namespaces:
  50.             return self._namespaces
  51.         raise SAXNotRecognizedException("Feature '%s' not recognized" % name)
  52.  
  53.     def setFeature(self, name, state):
  54.         if self._parsing:
  55.             raise SAXNotSupportedException("Cannot set features while parsing")
  56.         if name == handler.feature_namespaces:
  57.             self._namespaces = state
  58.         else:
  59.             raise SAXNotRecognizedException("Feature '%s' not recognized" %
  60.                                             name)
  61.  
  62.     def getProperty(self, name):
  63.         raise SAXNotRecognizedException("Property '%s' not recognized" % name)
  64.  
  65.     def setProperty(self, name, value):
  66.         raise SAXNotRecognizedException("Property '%s' not recognized" % name)
  67.  
  68.     # IncrementalParser methods
  69.  
  70.     def feed(self, data, isFinal = 0):
  71.         if not self._parsing:
  72.             self.reset()
  73.             self._parsing = 1
  74.             self._cont_handler.startDocument()
  75.  
  76.         try:
  77.             # The isFinal parameter is internal to the expat reader.
  78.             # If it is set to true, expat will check validity of the entire
  79.             # document. When feeding chunks, they are not normally final -
  80.             # except when invoked from close.
  81.             self._parser.Parse(data, isFinal)
  82.         except expat.error:
  83.             error_code = self._parser.ErrorCode
  84.             exc = SAXParseException(expat.ErrorString(error_code), None, self)
  85.             self._err_handler.fatalError(exc)
  86.  
  87.     def close(self):
  88.         if self._entity_stack:
  89.             # If we are completing an external entity, do nothing here
  90.             return
  91.         self.feed("", isFinal = 1)
  92.         self._cont_handler.endDocument()
  93.         self._parsing = 0
  94.         
  95.     def reset(self):
  96.         if self._namespaces:
  97.             self._parser = expat.ParserCreate(None, " ")
  98.             self._parser.StartElementHandler = self.start_element_ns
  99.             self._parser.EndElementHandler = self.end_element_ns
  100.         else:
  101.             self._parser = expat.ParserCreate()
  102.             self._parser.StartElementHandler = self.start_element
  103.             self._parser.EndElementHandler = self.end_element
  104.  
  105.         self._parser.ProcessingInstructionHandler = \
  106.                                     self._cont_handler.processingInstruction
  107.         self._parser.CharacterDataHandler = self._cont_handler.characters
  108.         self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl
  109.         self._parser.NotationDeclHandler = self.notation_decl
  110.         self._parser.StartNamespaceDeclHandler = self.start_namespace_decl
  111.         self._parser.EndNamespaceDeclHandler = self.end_namespace_decl
  112. #         self._parser.CommentHandler = 
  113. #         self._parser.StartCdataSectionHandler = 
  114. #         self._parser.EndCdataSectionHandler = 
  115. #         self._parser.DefaultHandler = 
  116. #         self._parser.DefaultHandlerExpand = 
  117. #         self._parser.NotStandaloneHandler = 
  118.         self._parser.ExternalEntityRefHandler = self.external_entity_ref
  119.  
  120.         self._parsing = 0
  121.         self._entity_stack = []
  122.         
  123.     # Locator methods
  124.  
  125.     def getColumnNumber(self):
  126.         return self._parser.ErrorColumnNumber
  127.  
  128.     def getLineNumber(self):
  129.         return self._parser.ErrorLineNumber
  130.  
  131.     def getPublicId(self):
  132.         return self._source.getPublicId()
  133.  
  134.     def getSystemId(self):
  135.         return self._source.getSystemId()
  136.     
  137.     # event handlers
  138.     def start_element(self, name, attrs):
  139.         self._cont_handler.startElement(name, AttributesImpl(attrs))
  140.  
  141.     def end_element(self, name):
  142.         self._cont_handler.endElement(name)
  143.  
  144.     def start_element_ns(self, name, attrs):
  145.         pair = string.split(name)
  146.         if len(pair) == 1:
  147.             pair = (None, name)
  148.  
  149.         newattrs = {}
  150.         for (aname, value) in attrs.items():
  151.             apair = string.split(aname)
  152.             if len(apair) == 1:
  153.                 apair = (None, aname)
  154.             else:
  155.                 apair = tuple(apair)
  156.  
  157.             newattrs[apair] = value
  158.  
  159.         self._cont_handler.startElementNS(pair, None, 
  160.                                           AttributesNSImpl(newattrs, {}))
  161.  
  162.     def end_element_ns(self, name):
  163.         pair = string.split(name)
  164.         if len(pair) == 1:
  165.             pair = (None, name)
  166.             
  167.         self._cont_handler.endElementNS(pair, None)
  168.  
  169.     # this is not used (call directly to ContentHandler)
  170.     def processing_instruction(self, target, data):
  171.         self._cont_handler.processingInstruction(target, data)
  172.  
  173.     # this is not used (call directly to ContentHandler)
  174.     def character_data(self, data):
  175.         self._cont_handler.characters(data)
  176.  
  177.     def start_namespace_decl(self, prefix, uri):
  178.         self._cont_handler.startPrefixMapping(prefix, uri)
  179.  
  180.     def end_namespace_decl(self, prefix):
  181.         self._cont_handler.endPrefixMapping(prefix)
  182.         
  183.     def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name):
  184.         self._dtd_handler.unparsedEntityDecl(name, pubid, sysid, notation_name)
  185.  
  186.     def notation_decl(self, name, base, sysid, pubid):
  187.         self._dtd_handler.notationDecl(name, pubid, sysid)
  188.  
  189.     def external_entity_ref(self, context, base, sysid, pubid):
  190.         source = self._ent_handler.resolveEntity(pubid, sysid)
  191.         source = saxutils.prepare_input_source(source,
  192.                                                self._source.getSystemId() or
  193.                                                "")
  194.         
  195.         self._entity_stack.append((self._parser, self._source))
  196.         self._parser = self._parser.ExternalEntityParserCreate(context)
  197.         self._source = source
  198.  
  199.         try:
  200.             xmlreader.IncrementalParser.parse(self, source)
  201.         except:
  202.             return 0  # FIXME: save error info here?
  203.  
  204.         (self._parser, self._source) = self._entity_stack[-1]
  205.         del self._entity_stack[-1]
  206.         return 1
  207.         
  208. # ---
  209.         
  210. def create_parser(*args, **kwargs):
  211.     return apply(ExpatParser, args, kwargs)
  212.         
  213. # ---
  214.  
  215. if __name__ == "__main__":
  216.     import xml.sax
  217.     p = create_parser()
  218.     p.setContentHandler(xml.sax.XMLGenerator())
  219.     p.setErrorHandler(xml.sax.ErrorHandler())
  220.     p.parse("../../../hamlet.xml")
  221.