""" SAX driver for the Java SAX parsers. Can only be used in Jython. $Id: drv_javasax.py,v 1.5 2003/01/26 09:08:51 loewis Exp $ """ # --- Initialization version = "0.10" revision = "$Revision: 1.5 $" import string from xml.sax import xmlreader, saxutils from xml.sax.handler import feature_namespaces, feature_namespace_prefixes from xml.sax import _exceptions # we only work in jython import sys if sys.platform[:4] != "java": raise _exceptions.SAXReaderNotAvailable("drv_javasax not available in CPython", None) del sys # get the necessary Java SAX classes try: from org.python.core import FilelikeInputStream from org.xml.sax.helpers import XMLReaderFactory from org.xml import sax as javasax except ImportError: raise _exceptions.SAXReaderNotAvailable("SAX is not on the classpath", None) # get some JAXP stuff try: from javax.xml.parsers import SAXParserFactory, ParserConfigurationException factory = SAXParserFactory.newInstance() jaxp = 1 except ImportError: jaxp = 0 from java.lang import String def _wrap_sax_exception(e): return _exceptions.SAXParseException(e.message, e.exception, SimpleLocator(e.columnNumber, e.lineNumber, e.publicId, e.systemId)) class JyErrorHandlerWrapper(javasax.ErrorHandler): def __init__(self, err_handler): self._err_handler = err_handler def error(self, exc): self._err_handler.error(_wrap_sax_exception(exc)) def fatalError(self, exc): self._err_handler.fatalError(_wrap_sax_exception(exc)) def warning(self, exc): self._err_handler.warning(_wrap_sax_exception(exc)) class JyInputSourceWrapper(javasax.InputSource): def __init__(self, source): if isinstance(source, str): javasax.InputSource.__init__(self, source) elif hasattr(source, "read"):#file like object f = source javasax.InputSource.__init__(self, FilelikeInputStream(f)) if hasattr(f, "name"): self.setSystemId(f.name) else:#xml.sax.xmlreader.InputSource object #Use byte stream constructor if possible so that Xerces won't attempt to open #the url at systemId unless it's really there if source.getByteStream(): javasax.InputSource.__init__(self, FilelikeInputStream(source.getByteStream())) else: javasax.InputSource.__init__(self) if source.getSystemId(): self.setSystemId(source.getSystemId()) self.setPublicId(source.getPublicId()) self.setEncoding(source.getEncoding()) class JyEntityResolverWrapper(javasax.EntityResolver): def __init__(self, entityResolver): self._resolver = entityResolver def resolveEntity(self, pubId, sysId): return JyInputSourceWrapper(self._resolver.resolveEntity(pubId, sysId)) class JyDTDHandlerWrapper(javasax.DTDHandler): def __init__(self, dtdHandler): self._handler = dtdHandler def notationDecl(self, name, publicId, systemId): self._handler.notationDecl(name, publicId, systemId) def unparsedEntityDecl(self, name, publicId, systemId, notationName): self._handler.unparsedEntityDecl(name, publicId, systemId, notationName) class SimpleLocator(xmlreader.Locator): def __init__(self, colNum, lineNum, pubId, sysId): self.colNum = colNum self.lineNum = lineNum self.pubId = pubId self.sysId = sysId def getColumnNumber(self): return self.colNum def getLineNumber(self): return self.lineNum def getPublicId(self): return self.pubId def getSystemId(self): return self.sysId # --- JavaSAXParser class JavaSAXParser(xmlreader.XMLReader, javasax.ContentHandler): "SAX driver for the Java SAX parsers." def __init__(self, jdriver = None): xmlreader.XMLReader.__init__(self) self._parser = create_java_parser(jdriver) self._parser.setFeature(feature_namespaces, 0) self._parser.setFeature(feature_namespace_prefixes, 0) self._parser.setContentHandler(self) self._nsattrs = AttributesNSImpl() self._attrs = AttributesImpl() self.setEntityResolver(self.getEntityResolver()) self.setErrorHandler(self.getErrorHandler()) self.setDTDHandler(self.getDTDHandler()) # XMLReader methods def parse(self, source): "Parse an XML document from a URL or an InputSource." self._parser.parse(JyInputSourceWrapper(source)) def getFeature(self, name): return self._parser.getFeature(name) def setFeature(self, name, state): self._parser.setFeature(name, state) def getProperty(self, name): return self._parser.getProperty(name) def setProperty(self, name, value): self._parser.setProperty(name, value) def setEntityResolver(self, resolver): self._parser.entityResolver = JyEntityResolverWrapper(resolver) xmlreader.XMLReader.setEntityResolver(self, resolver) def setErrorHandler(self, err_handler): self._parser.errorHandler = JyErrorHandlerWrapper(err_handler) xmlreader.XMLReader.setErrorHandler(self, err_handler) def setDTDHandler(self, dtd_handler): self._parser.setDTDHandler(JyDTDHandlerWrapper(dtd_handler)) xmlreader.XMLReader.setDTDHandler(self, dtd_handler) # ContentHandler methods def setDocumentLocator(self, locator): self._cont_handler.setDocumentLocator(locator) def startDocument(self): self._cont_handler.startDocument() self._namespaces = self._parser.getFeature(feature_namespaces) def startElement(self, uri, lname, qname, attrs): if self._namespaces: self._nsattrs._attrs = attrs self._cont_handler.startElementNS((uri or None, lname), qname, self._nsattrs) else: self._attrs._attrs = attrs self._cont_handler.startElement(qname, self._attrs) def startPrefixMapping(self, prefix, uri): self._cont_handler.startPrefixMapping(prefix, uri) def characters(self, char, start, len): self._cont_handler.characters(str(String(char, start, len))) def ignorableWhitespace(self, char, start, len): self._cont_handler.ignorableWhitespace(str(String(char, start, len))) def endElement(self, uri, lname, qname): if self._namespaces: self._cont_handler.endElementNS((uri or None, lname), qname) else: self._cont_handler.endElement(qname) def endPrefixMapping(self, prefix): self._cont_handler.endPrefixMapping(prefix) def endDocument(self): self._cont_handler.endDocument() def processingInstruction(self, target, data): self._cont_handler.processingInstruction(target, data) class AttributesImpl: def __init__(self, attrs = None): self._attrs = attrs def getLength(self): return self._attrs.getLength() def getType(self, name): return self._attrs.getType(name) def getValue(self, name): if name is None: name = '' value = self._attrs.getValue(name) if value == None: raise KeyError(name) return value def getNames(self): return [self._attrs.getQName(index) for index in range(len(self))] def getQNames(self): return [self._attrs.getQName(index) for index in range(len(self))] def getValueByQName(self, qname): idx = self._attrs.getIndex(qname) if idx == -1: raise KeyError, qname return self._attrs.getValue(idx) def getNameByQName(self, qname): idx = self._attrs.getIndex(qname) if idx == -1: raise KeyError, qname return qname def getQNameByName(self, name): idx = self._attrs.getIndex(name) if idx == -1: raise KeyError, name return name def __len__(self): return self._attrs.getLength() def __getitem__(self, name): return self.getValue(name) def keys(self): return self.getNames() def copy(self): return self.__class__(self._attrs) def items(self): return [(name, self[name]) for name in self.getNames()] def values(self): return map(self.getValue, self.getNames()) def get(self, name, alt=None): try: return self.getValue(name) except KeyError: return alt def has_key(self, name): try: self.getValue(name) return True except KeyError: return False # --- AttributesNSImpl class AttributesNSImpl(AttributesImpl): def __init__(self, attrs=None): AttributesImpl.__init__(self, attrs) def getType(self, name): return self._attrs.getType(name[0] or '', name[1]) def getValue(self, name): value = self._attrs.getValue(name[0] or '', name[1]) if value == None: raise KeyError(name) return value def getNames(self): names = [] for idx in range(len(self)): names.append((self._attrs.getURI(idx), self._attrs.getLocalName(idx))) return names def getNameByQName(self, qname): idx = self._attrs.getIndex(qname) if idx == -1: raise KeyError, qname return (self._attrs.getURI(idx), self._attrs.getLocalName(idx)) def getQNameByName(self, name): idx = self._attrs.getIndex(name[0] or '', name[1]) if idx == -1: raise KeyError, name return self._attrs.getQName(idx) def getQNames(self): return [self._attrs.getQName(idx) for idx in range(len(self))] # --- def create_java_parser(jdriver = None): try: if jdriver: return XMLReaderFactory.createXMLReader(jdriver) elif jaxp: return factory.newSAXParser().getXMLReader() else: return XMLReaderFactory.createXMLReader() except ParserConfigurationException, e: raise _exceptions.SAXReaderNotAvailable(e.getMessage()) except javasax.SAXException, e: raise _exceptions.SAXReaderNotAvailable(e.getMessage()) def create_parser(jdriver = None): return JavaSAXParser(jdriver)