1*7c568831SAndroid Build Coastguard Worker# -*- coding: iso-8859-1 -*- 2*7c568831SAndroid Build Coastguard Worker""" A SAX2 driver for libxml2, on top of it's XmlReader API 3*7c568831SAndroid Build Coastguard Worker 4*7c568831SAndroid Build Coastguard WorkerUSAGE 5*7c568831SAndroid Build Coastguard Worker # put this file (drv_libxml2.py) in PYTHONPATH 6*7c568831SAndroid Build Coastguard Worker import xml.sax 7*7c568831SAndroid Build Coastguard Worker reader = xml.sax.make_parser(["drv_libxml2"]) 8*7c568831SAndroid Build Coastguard Worker # ...and the rest is standard python sax. 9*7c568831SAndroid Build Coastguard Worker 10*7c568831SAndroid Build Coastguard WorkerCAVEATS 11*7c568831SAndroid Build Coastguard Worker - Lexical handlers are supported, except for start/endEntity 12*7c568831SAndroid Build Coastguard Worker (waiting for XmlReader.ResolveEntity) and start/endDTD 13*7c568831SAndroid Build Coastguard Worker - Error callbacks are not exactly synchronous, they tend 14*7c568831SAndroid Build Coastguard Worker to be invoked before the corresponding content callback, 15*7c568831SAndroid Build Coastguard Worker because the underlying reader interface parses 16*7c568831SAndroid Build Coastguard Worker data by chunks of 512 bytes 17*7c568831SAndroid Build Coastguard Worker 18*7c568831SAndroid Build Coastguard WorkerTODO 19*7c568831SAndroid Build Coastguard Worker - search for TODO 20*7c568831SAndroid Build Coastguard Worker - some ErrorHandler events (warning) 21*7c568831SAndroid Build Coastguard Worker - some ContentHandler events (setDocumentLocator, skippedEntity) 22*7c568831SAndroid Build Coastguard Worker - EntityResolver (using libxml2.?) 23*7c568831SAndroid Build Coastguard Worker - DTDHandler (if/when libxml2 exposes such node types) 24*7c568831SAndroid Build Coastguard Worker - DeclHandler (if/when libxml2 exposes such node types) 25*7c568831SAndroid Build Coastguard Worker - property_xml_string? 26*7c568831SAndroid Build Coastguard Worker - feature_string_interning? 27*7c568831SAndroid Build Coastguard Worker - Incremental parser 28*7c568831SAndroid Build Coastguard Worker - additional performance tuning: 29*7c568831SAndroid Build Coastguard Worker - one might cache callbacks to avoid some name lookups 30*7c568831SAndroid Build Coastguard Worker - one might implement a smarter way to pass attributes to startElement 31*7c568831SAndroid Build Coastguard Worker (some kind of lazy evaluation?) 32*7c568831SAndroid Build Coastguard Worker - there might be room for improvement in start/endPrefixMapping 33*7c568831SAndroid Build Coastguard Worker - other? 34*7c568831SAndroid Build Coastguard Worker 35*7c568831SAndroid Build Coastguard Worker""" 36*7c568831SAndroid Build Coastguard Worker 37*7c568831SAndroid Build Coastguard Worker__author__ = "St�phane Bidoul <[email protected]>" 38*7c568831SAndroid Build Coastguard Worker__version__ = "0.3" 39*7c568831SAndroid Build Coastguard Worker 40*7c568831SAndroid Build Coastguard Workerimport sys 41*7c568831SAndroid Build Coastguard Workerimport codecs 42*7c568831SAndroid Build Coastguard Worker 43*7c568831SAndroid Build Coastguard Workerif sys.version_info[0] < 3: 44*7c568831SAndroid Build Coastguard Worker __author__ = codecs.unicode_escape_decode(__author__)[0] 45*7c568831SAndroid Build Coastguard Worker 46*7c568831SAndroid Build Coastguard Worker StringTypes = (str, unicode) 47*7c568831SAndroid Build Coastguard Worker # libxml2 returns strings as UTF8 48*7c568831SAndroid Build Coastguard Worker _decoder = codecs.lookup("utf8")[1] 49*7c568831SAndroid Build Coastguard Worker def _d(s): 50*7c568831SAndroid Build Coastguard Worker if s is None: 51*7c568831SAndroid Build Coastguard Worker return s 52*7c568831SAndroid Build Coastguard Worker else: 53*7c568831SAndroid Build Coastguard Worker return _decoder(s)[0] 54*7c568831SAndroid Build Coastguard Workerelse: 55*7c568831SAndroid Build Coastguard Worker StringTypes = str 56*7c568831SAndroid Build Coastguard Worker # s is Unicode `str` already 57*7c568831SAndroid Build Coastguard Worker def _d(s): 58*7c568831SAndroid Build Coastguard Worker return s 59*7c568831SAndroid Build Coastguard Worker 60*7c568831SAndroid Build Coastguard Workerfrom xml.sax._exceptions import * 61*7c568831SAndroid Build Coastguard Workerfrom xml.sax import xmlreader, saxutils 62*7c568831SAndroid Build Coastguard Workerfrom xml.sax.handler import \ 63*7c568831SAndroid Build Coastguard Worker feature_namespaces, \ 64*7c568831SAndroid Build Coastguard Worker feature_namespace_prefixes, \ 65*7c568831SAndroid Build Coastguard Worker feature_string_interning, \ 66*7c568831SAndroid Build Coastguard Worker feature_validation, \ 67*7c568831SAndroid Build Coastguard Worker feature_external_ges, \ 68*7c568831SAndroid Build Coastguard Worker feature_external_pes, \ 69*7c568831SAndroid Build Coastguard Worker property_lexical_handler, \ 70*7c568831SAndroid Build Coastguard Worker property_declaration_handler, \ 71*7c568831SAndroid Build Coastguard Worker property_dom_node, \ 72*7c568831SAndroid Build Coastguard Worker property_xml_string 73*7c568831SAndroid Build Coastguard Worker 74*7c568831SAndroid Build Coastguard Workertry: 75*7c568831SAndroid Build Coastguard Worker import libxml2 76*7c568831SAndroid Build Coastguard Workerexcept ImportError: 77*7c568831SAndroid Build Coastguard Worker raise SAXReaderNotAvailable("libxml2 not available: " \ 78*7c568831SAndroid Build Coastguard Worker "import error was: %s" % sys.exc_info()[1]) 79*7c568831SAndroid Build Coastguard Worker 80*7c568831SAndroid Build Coastguard Workerclass Locator(xmlreader.Locator): 81*7c568831SAndroid Build Coastguard Worker """SAX Locator adapter for libxml2.xmlTextReaderLocator""" 82*7c568831SAndroid Build Coastguard Worker 83*7c568831SAndroid Build Coastguard Worker def __init__(self,locator): 84*7c568831SAndroid Build Coastguard Worker self.__locator = locator 85*7c568831SAndroid Build Coastguard Worker 86*7c568831SAndroid Build Coastguard Worker def getColumnNumber(self): 87*7c568831SAndroid Build Coastguard Worker "Return the column number where the current event ends." 88*7c568831SAndroid Build Coastguard Worker return -1 89*7c568831SAndroid Build Coastguard Worker 90*7c568831SAndroid Build Coastguard Worker def getLineNumber(self): 91*7c568831SAndroid Build Coastguard Worker "Return the line number where the current event ends." 92*7c568831SAndroid Build Coastguard Worker return self.__locator.LineNumber() 93*7c568831SAndroid Build Coastguard Worker 94*7c568831SAndroid Build Coastguard Worker def getPublicId(self): 95*7c568831SAndroid Build Coastguard Worker "Return the public identifier for the current event." 96*7c568831SAndroid Build Coastguard Worker return None 97*7c568831SAndroid Build Coastguard Worker 98*7c568831SAndroid Build Coastguard Worker def getSystemId(self): 99*7c568831SAndroid Build Coastguard Worker "Return the system identifier for the current event." 100*7c568831SAndroid Build Coastguard Worker return self.__locator.BaseURI() 101*7c568831SAndroid Build Coastguard Worker 102*7c568831SAndroid Build Coastguard Workerclass LibXml2Reader(xmlreader.XMLReader): 103*7c568831SAndroid Build Coastguard Worker 104*7c568831SAndroid Build Coastguard Worker def __init__(self): 105*7c568831SAndroid Build Coastguard Worker xmlreader.XMLReader.__init__(self) 106*7c568831SAndroid Build Coastguard Worker # features 107*7c568831SAndroid Build Coastguard Worker self.__ns = 0 108*7c568831SAndroid Build Coastguard Worker self.__nspfx = 0 109*7c568831SAndroid Build Coastguard Worker self.__validate = 0 110*7c568831SAndroid Build Coastguard Worker self.__extparams = 1 111*7c568831SAndroid Build Coastguard Worker # parsing flag 112*7c568831SAndroid Build Coastguard Worker self.__parsing = 0 113*7c568831SAndroid Build Coastguard Worker # additional handlers 114*7c568831SAndroid Build Coastguard Worker self.__lex_handler = None 115*7c568831SAndroid Build Coastguard Worker self.__decl_handler = None 116*7c568831SAndroid Build Coastguard Worker # error messages accumulator 117*7c568831SAndroid Build Coastguard Worker self.__errors = None 118*7c568831SAndroid Build Coastguard Worker 119*7c568831SAndroid Build Coastguard Worker def _errorHandler(self,arg,msg,severity,locator): 120*7c568831SAndroid Build Coastguard Worker if self.__errors is None: 121*7c568831SAndroid Build Coastguard Worker self.__errors = [] 122*7c568831SAndroid Build Coastguard Worker self.__errors.append((severity, 123*7c568831SAndroid Build Coastguard Worker SAXParseException(msg,None, 124*7c568831SAndroid Build Coastguard Worker Locator(locator)))) 125*7c568831SAndroid Build Coastguard Worker 126*7c568831SAndroid Build Coastguard Worker def _reportErrors(self,fatal): 127*7c568831SAndroid Build Coastguard Worker for severity,exception in self.__errors: 128*7c568831SAndroid Build Coastguard Worker if severity in (libxml2.PARSER_SEVERITY_VALIDITY_WARNING, 129*7c568831SAndroid Build Coastguard Worker libxml2.PARSER_SEVERITY_WARNING): 130*7c568831SAndroid Build Coastguard Worker self._err_handler.warning(exception) 131*7c568831SAndroid Build Coastguard Worker else: 132*7c568831SAndroid Build Coastguard Worker # when fatal is set, the parse will stop; 133*7c568831SAndroid Build Coastguard Worker # we consider that the last error reported 134*7c568831SAndroid Build Coastguard Worker # is the fatal one. 135*7c568831SAndroid Build Coastguard Worker if fatal and exception is self.__errors[-1][1]: 136*7c568831SAndroid Build Coastguard Worker self._err_handler.fatalError(exception) 137*7c568831SAndroid Build Coastguard Worker else: 138*7c568831SAndroid Build Coastguard Worker self._err_handler.error(exception) 139*7c568831SAndroid Build Coastguard Worker self.__errors = None 140*7c568831SAndroid Build Coastguard Worker 141*7c568831SAndroid Build Coastguard Worker def parse(self, source): 142*7c568831SAndroid Build Coastguard Worker self.__parsing = 1 143*7c568831SAndroid Build Coastguard Worker try: 144*7c568831SAndroid Build Coastguard Worker # prepare source and create reader 145*7c568831SAndroid Build Coastguard Worker if isinstance(source, StringTypes): 146*7c568831SAndroid Build Coastguard Worker reader = libxml2.newTextReaderFilename(source) 147*7c568831SAndroid Build Coastguard Worker else: 148*7c568831SAndroid Build Coastguard Worker source = saxutils.prepare_input_source(source) 149*7c568831SAndroid Build Coastguard Worker stream = source.getCharacterStream() 150*7c568831SAndroid Build Coastguard Worker if stream is None: 151*7c568831SAndroid Build Coastguard Worker stream = source.getByteStream() 152*7c568831SAndroid Build Coastguard Worker input = libxml2.inputBuffer(stream) 153*7c568831SAndroid Build Coastguard Worker reader = input.newTextReader(source.getSystemId()) 154*7c568831SAndroid Build Coastguard Worker reader.SetErrorHandler(self._errorHandler,None) 155*7c568831SAndroid Build Coastguard Worker # configure reader 156*7c568831SAndroid Build Coastguard Worker if self.__extparams: 157*7c568831SAndroid Build Coastguard Worker reader.SetParserProp(libxml2.PARSER_LOADDTD,1) 158*7c568831SAndroid Build Coastguard Worker reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1) 159*7c568831SAndroid Build Coastguard Worker reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1) 160*7c568831SAndroid Build Coastguard Worker reader.SetParserProp(libxml2.PARSER_VALIDATE,self.__validate) 161*7c568831SAndroid Build Coastguard Worker else: 162*7c568831SAndroid Build Coastguard Worker reader.SetParserProp(libxml2.PARSER_LOADDTD, 0) 163*7c568831SAndroid Build Coastguard Worker # we reuse attribute maps (for a slight performance gain) 164*7c568831SAndroid Build Coastguard Worker if self.__ns: 165*7c568831SAndroid Build Coastguard Worker attributesNSImpl = xmlreader.AttributesNSImpl({},{}) 166*7c568831SAndroid Build Coastguard Worker else: 167*7c568831SAndroid Build Coastguard Worker attributesImpl = xmlreader.AttributesImpl({}) 168*7c568831SAndroid Build Coastguard Worker # prefixes to pop (for endPrefixMapping) 169*7c568831SAndroid Build Coastguard Worker prefixes = [] 170*7c568831SAndroid Build Coastguard Worker # start loop 171*7c568831SAndroid Build Coastguard Worker self._cont_handler.startDocument() 172*7c568831SAndroid Build Coastguard Worker while 1: 173*7c568831SAndroid Build Coastguard Worker r = reader.Read() 174*7c568831SAndroid Build Coastguard Worker # check for errors 175*7c568831SAndroid Build Coastguard Worker if r == 1: 176*7c568831SAndroid Build Coastguard Worker if not self.__errors is None: 177*7c568831SAndroid Build Coastguard Worker self._reportErrors(0) 178*7c568831SAndroid Build Coastguard Worker elif r == 0: 179*7c568831SAndroid Build Coastguard Worker if not self.__errors is None: 180*7c568831SAndroid Build Coastguard Worker self._reportErrors(0) 181*7c568831SAndroid Build Coastguard Worker break # end of parse 182*7c568831SAndroid Build Coastguard Worker else: 183*7c568831SAndroid Build Coastguard Worker if not self.__errors is None: 184*7c568831SAndroid Build Coastguard Worker self._reportErrors(1) 185*7c568831SAndroid Build Coastguard Worker else: 186*7c568831SAndroid Build Coastguard Worker self._err_handler.fatalError(\ 187*7c568831SAndroid Build Coastguard Worker SAXException("Read failed (no details available)")) 188*7c568831SAndroid Build Coastguard Worker break # fatal parse error 189*7c568831SAndroid Build Coastguard Worker # get node type 190*7c568831SAndroid Build Coastguard Worker nodeType = reader.NodeType() 191*7c568831SAndroid Build Coastguard Worker # Element 192*7c568831SAndroid Build Coastguard Worker if nodeType == 1: 193*7c568831SAndroid Build Coastguard Worker if self.__ns: 194*7c568831SAndroid Build Coastguard Worker eltName = (_d(reader.NamespaceUri()),\ 195*7c568831SAndroid Build Coastguard Worker _d(reader.LocalName())) 196*7c568831SAndroid Build Coastguard Worker eltQName = _d(reader.Name()) 197*7c568831SAndroid Build Coastguard Worker attributesNSImpl._attrs = attrs = {} 198*7c568831SAndroid Build Coastguard Worker attributesNSImpl._qnames = qnames = {} 199*7c568831SAndroid Build Coastguard Worker newPrefixes = [] 200*7c568831SAndroid Build Coastguard Worker while reader.MoveToNextAttribute(): 201*7c568831SAndroid Build Coastguard Worker qname = _d(reader.Name()) 202*7c568831SAndroid Build Coastguard Worker value = _d(reader.Value()) 203*7c568831SAndroid Build Coastguard Worker if qname.startswith("xmlns"): 204*7c568831SAndroid Build Coastguard Worker if len(qname) > 5: 205*7c568831SAndroid Build Coastguard Worker newPrefix = qname[6:] 206*7c568831SAndroid Build Coastguard Worker else: 207*7c568831SAndroid Build Coastguard Worker newPrefix = None 208*7c568831SAndroid Build Coastguard Worker newPrefixes.append(newPrefix) 209*7c568831SAndroid Build Coastguard Worker self._cont_handler.startPrefixMapping(\ 210*7c568831SAndroid Build Coastguard Worker newPrefix,value) 211*7c568831SAndroid Build Coastguard Worker if not self.__nspfx: 212*7c568831SAndroid Build Coastguard Worker continue # don't report xmlns attribute 213*7c568831SAndroid Build Coastguard Worker attName = (_d(reader.NamespaceUri()), 214*7c568831SAndroid Build Coastguard Worker _d(reader.LocalName())) 215*7c568831SAndroid Build Coastguard Worker qnames[attName] = qname 216*7c568831SAndroid Build Coastguard Worker attrs[attName] = value 217*7c568831SAndroid Build Coastguard Worker reader.MoveToElement() 218*7c568831SAndroid Build Coastguard Worker self._cont_handler.startElementNS( \ 219*7c568831SAndroid Build Coastguard Worker eltName,eltQName,attributesNSImpl) 220*7c568831SAndroid Build Coastguard Worker if reader.IsEmptyElement(): 221*7c568831SAndroid Build Coastguard Worker self._cont_handler.endElementNS(eltName,eltQName) 222*7c568831SAndroid Build Coastguard Worker for newPrefix in newPrefixes: 223*7c568831SAndroid Build Coastguard Worker self._cont_handler.endPrefixMapping(newPrefix) 224*7c568831SAndroid Build Coastguard Worker else: 225*7c568831SAndroid Build Coastguard Worker prefixes.append(newPrefixes) 226*7c568831SAndroid Build Coastguard Worker else: 227*7c568831SAndroid Build Coastguard Worker eltName = _d(reader.Name()) 228*7c568831SAndroid Build Coastguard Worker attributesImpl._attrs = attrs = {} 229*7c568831SAndroid Build Coastguard Worker while reader.MoveToNextAttribute(): 230*7c568831SAndroid Build Coastguard Worker attName = _d(reader.Name()) 231*7c568831SAndroid Build Coastguard Worker attrs[attName] = _d(reader.Value()) 232*7c568831SAndroid Build Coastguard Worker reader.MoveToElement() 233*7c568831SAndroid Build Coastguard Worker self._cont_handler.startElement( \ 234*7c568831SAndroid Build Coastguard Worker eltName,attributesImpl) 235*7c568831SAndroid Build Coastguard Worker if reader.IsEmptyElement(): 236*7c568831SAndroid Build Coastguard Worker self._cont_handler.endElement(eltName) 237*7c568831SAndroid Build Coastguard Worker # EndElement 238*7c568831SAndroid Build Coastguard Worker elif nodeType == 15: 239*7c568831SAndroid Build Coastguard Worker if self.__ns: 240*7c568831SAndroid Build Coastguard Worker self._cont_handler.endElementNS( \ 241*7c568831SAndroid Build Coastguard Worker (_d(reader.NamespaceUri()),_d(reader.LocalName())), 242*7c568831SAndroid Build Coastguard Worker _d(reader.Name())) 243*7c568831SAndroid Build Coastguard Worker for prefix in prefixes.pop(): 244*7c568831SAndroid Build Coastguard Worker self._cont_handler.endPrefixMapping(prefix) 245*7c568831SAndroid Build Coastguard Worker else: 246*7c568831SAndroid Build Coastguard Worker self._cont_handler.endElement(_d(reader.Name())) 247*7c568831SAndroid Build Coastguard Worker # Text 248*7c568831SAndroid Build Coastguard Worker elif nodeType == 3: 249*7c568831SAndroid Build Coastguard Worker self._cont_handler.characters(_d(reader.Value())) 250*7c568831SAndroid Build Coastguard Worker # Whitespace 251*7c568831SAndroid Build Coastguard Worker elif nodeType == 13: 252*7c568831SAndroid Build Coastguard Worker self._cont_handler.ignorableWhitespace(_d(reader.Value())) 253*7c568831SAndroid Build Coastguard Worker # SignificantWhitespace 254*7c568831SAndroid Build Coastguard Worker elif nodeType == 14: 255*7c568831SAndroid Build Coastguard Worker self._cont_handler.characters(_d(reader.Value())) 256*7c568831SAndroid Build Coastguard Worker # CDATA 257*7c568831SAndroid Build Coastguard Worker elif nodeType == 4: 258*7c568831SAndroid Build Coastguard Worker if not self.__lex_handler is None: 259*7c568831SAndroid Build Coastguard Worker self.__lex_handler.startCDATA() 260*7c568831SAndroid Build Coastguard Worker self._cont_handler.characters(_d(reader.Value())) 261*7c568831SAndroid Build Coastguard Worker if not self.__lex_handler is None: 262*7c568831SAndroid Build Coastguard Worker self.__lex_handler.endCDATA() 263*7c568831SAndroid Build Coastguard Worker # EntityReference 264*7c568831SAndroid Build Coastguard Worker elif nodeType == 5: 265*7c568831SAndroid Build Coastguard Worker if not self.__lex_handler is None: 266*7c568831SAndroid Build Coastguard Worker self.startEntity(_d(reader.Name())) 267*7c568831SAndroid Build Coastguard Worker reader.ResolveEntity() 268*7c568831SAndroid Build Coastguard Worker # EndEntity 269*7c568831SAndroid Build Coastguard Worker elif nodeType == 16: 270*7c568831SAndroid Build Coastguard Worker if not self.__lex_handler is None: 271*7c568831SAndroid Build Coastguard Worker self.endEntity(_d(reader.Name())) 272*7c568831SAndroid Build Coastguard Worker # ProcessingInstruction 273*7c568831SAndroid Build Coastguard Worker elif nodeType == 7: 274*7c568831SAndroid Build Coastguard Worker self._cont_handler.processingInstruction( \ 275*7c568831SAndroid Build Coastguard Worker _d(reader.Name()),_d(reader.Value())) 276*7c568831SAndroid Build Coastguard Worker # Comment 277*7c568831SAndroid Build Coastguard Worker elif nodeType == 8: 278*7c568831SAndroid Build Coastguard Worker if not self.__lex_handler is None: 279*7c568831SAndroid Build Coastguard Worker self.__lex_handler.comment(_d(reader.Value())) 280*7c568831SAndroid Build Coastguard Worker # DocumentType 281*7c568831SAndroid Build Coastguard Worker elif nodeType == 10: 282*7c568831SAndroid Build Coastguard Worker #if not self.__lex_handler is None: 283*7c568831SAndroid Build Coastguard Worker # self.__lex_handler.startDTD() 284*7c568831SAndroid Build Coastguard Worker pass # TODO (how to detect endDTD? on first non-dtd event?) 285*7c568831SAndroid Build Coastguard Worker # XmlDeclaration 286*7c568831SAndroid Build Coastguard Worker elif nodeType == 17: 287*7c568831SAndroid Build Coastguard Worker pass # TODO 288*7c568831SAndroid Build Coastguard Worker # Entity 289*7c568831SAndroid Build Coastguard Worker elif nodeType == 6: 290*7c568831SAndroid Build Coastguard Worker pass # TODO (entity decl) 291*7c568831SAndroid Build Coastguard Worker # Notation (decl) 292*7c568831SAndroid Build Coastguard Worker elif nodeType == 12: 293*7c568831SAndroid Build Coastguard Worker pass # TODO 294*7c568831SAndroid Build Coastguard Worker # Attribute (never in this loop) 295*7c568831SAndroid Build Coastguard Worker #elif nodeType == 2: 296*7c568831SAndroid Build Coastguard Worker # pass 297*7c568831SAndroid Build Coastguard Worker # Document (not exposed) 298*7c568831SAndroid Build Coastguard Worker #elif nodeType == 9: 299*7c568831SAndroid Build Coastguard Worker # pass 300*7c568831SAndroid Build Coastguard Worker # DocumentFragment (never returned by XmlReader) 301*7c568831SAndroid Build Coastguard Worker #elif nodeType == 11: 302*7c568831SAndroid Build Coastguard Worker # pass 303*7c568831SAndroid Build Coastguard Worker # None 304*7c568831SAndroid Build Coastguard Worker #elif nodeType == 0: 305*7c568831SAndroid Build Coastguard Worker # pass 306*7c568831SAndroid Build Coastguard Worker # - 307*7c568831SAndroid Build Coastguard Worker else: 308*7c568831SAndroid Build Coastguard Worker raise SAXException("Unexpected node type %d" % nodeType) 309*7c568831SAndroid Build Coastguard Worker if r == 0: 310*7c568831SAndroid Build Coastguard Worker self._cont_handler.endDocument() 311*7c568831SAndroid Build Coastguard Worker reader.Close() 312*7c568831SAndroid Build Coastguard Worker finally: 313*7c568831SAndroid Build Coastguard Worker self.__parsing = 0 314*7c568831SAndroid Build Coastguard Worker 315*7c568831SAndroid Build Coastguard Worker def setDTDHandler(self, handler): 316*7c568831SAndroid Build Coastguard Worker # TODO (when supported, the inherited method works just fine) 317*7c568831SAndroid Build Coastguard Worker raise SAXNotSupportedException("DTDHandler not supported") 318*7c568831SAndroid Build Coastguard Worker 319*7c568831SAndroid Build Coastguard Worker def setEntityResolver(self, resolver): 320*7c568831SAndroid Build Coastguard Worker # TODO (when supported, the inherited method works just fine) 321*7c568831SAndroid Build Coastguard Worker raise SAXNotSupportedException("EntityResolver not supported") 322*7c568831SAndroid Build Coastguard Worker 323*7c568831SAndroid Build Coastguard Worker def getFeature(self, name): 324*7c568831SAndroid Build Coastguard Worker if name == feature_namespaces: 325*7c568831SAndroid Build Coastguard Worker return self.__ns 326*7c568831SAndroid Build Coastguard Worker elif name == feature_namespace_prefixes: 327*7c568831SAndroid Build Coastguard Worker return self.__nspfx 328*7c568831SAndroid Build Coastguard Worker elif name == feature_validation: 329*7c568831SAndroid Build Coastguard Worker return self.__validate 330*7c568831SAndroid Build Coastguard Worker elif name == feature_external_ges: 331*7c568831SAndroid Build Coastguard Worker return 1 # TODO (does that relate to PARSER_LOADDTD)? 332*7c568831SAndroid Build Coastguard Worker elif name == feature_external_pes: 333*7c568831SAndroid Build Coastguard Worker return self.__extparams 334*7c568831SAndroid Build Coastguard Worker else: 335*7c568831SAndroid Build Coastguard Worker raise SAXNotRecognizedException("Feature '%s' not recognized" % \ 336*7c568831SAndroid Build Coastguard Worker name) 337*7c568831SAndroid Build Coastguard Worker 338*7c568831SAndroid Build Coastguard Worker def setFeature(self, name, state): 339*7c568831SAndroid Build Coastguard Worker if self.__parsing: 340*7c568831SAndroid Build Coastguard Worker raise SAXNotSupportedException("Cannot set feature %s " \ 341*7c568831SAndroid Build Coastguard Worker "while parsing" % name) 342*7c568831SAndroid Build Coastguard Worker if name == feature_namespaces: 343*7c568831SAndroid Build Coastguard Worker self.__ns = state 344*7c568831SAndroid Build Coastguard Worker elif name == feature_namespace_prefixes: 345*7c568831SAndroid Build Coastguard Worker self.__nspfx = state 346*7c568831SAndroid Build Coastguard Worker elif name == feature_validation: 347*7c568831SAndroid Build Coastguard Worker self.__validate = state 348*7c568831SAndroid Build Coastguard Worker elif name == feature_external_ges: 349*7c568831SAndroid Build Coastguard Worker if state == 0: 350*7c568831SAndroid Build Coastguard Worker # TODO (does that relate to PARSER_LOADDTD)? 351*7c568831SAndroid Build Coastguard Worker raise SAXNotSupportedException("Feature '%s' not supported" % \ 352*7c568831SAndroid Build Coastguard Worker name) 353*7c568831SAndroid Build Coastguard Worker elif name == feature_external_pes: 354*7c568831SAndroid Build Coastguard Worker self.__extparams = state 355*7c568831SAndroid Build Coastguard Worker else: 356*7c568831SAndroid Build Coastguard Worker raise SAXNotRecognizedException("Feature '%s' not recognized" % \ 357*7c568831SAndroid Build Coastguard Worker name) 358*7c568831SAndroid Build Coastguard Worker 359*7c568831SAndroid Build Coastguard Worker def getProperty(self, name): 360*7c568831SAndroid Build Coastguard Worker if name == property_lexical_handler: 361*7c568831SAndroid Build Coastguard Worker return self.__lex_handler 362*7c568831SAndroid Build Coastguard Worker elif name == property_declaration_handler: 363*7c568831SAndroid Build Coastguard Worker return self.__decl_handler 364*7c568831SAndroid Build Coastguard Worker else: 365*7c568831SAndroid Build Coastguard Worker raise SAXNotRecognizedException("Property '%s' not recognized" % \ 366*7c568831SAndroid Build Coastguard Worker name) 367*7c568831SAndroid Build Coastguard Worker 368*7c568831SAndroid Build Coastguard Worker def setProperty(self, name, value): 369*7c568831SAndroid Build Coastguard Worker if name == property_lexical_handler: 370*7c568831SAndroid Build Coastguard Worker self.__lex_handler = value 371*7c568831SAndroid Build Coastguard Worker elif name == property_declaration_handler: 372*7c568831SAndroid Build Coastguard Worker # TODO: remove if/when libxml2 supports dtd events 373*7c568831SAndroid Build Coastguard Worker raise SAXNotSupportedException("Property '%s' not supported" % \ 374*7c568831SAndroid Build Coastguard Worker name) 375*7c568831SAndroid Build Coastguard Worker self.__decl_handler = value 376*7c568831SAndroid Build Coastguard Worker else: 377*7c568831SAndroid Build Coastguard Worker raise SAXNotRecognizedException("Property '%s' not recognized" % \ 378*7c568831SAndroid Build Coastguard Worker name) 379*7c568831SAndroid Build Coastguard Worker 380*7c568831SAndroid Build Coastguard Workerdef create_parser(): 381*7c568831SAndroid Build Coastguard Worker return LibXml2Reader() 382*7c568831SAndroid Build Coastguard Worker 383