1*cda5da8dSAndroid Build Coastguard Worker""" 2*cda5da8dSAndroid Build Coastguard WorkerSAX driver for the pyexpat C module. This driver works with 3*cda5da8dSAndroid Build Coastguard Workerpyexpat.__version__ == '2.22'. 4*cda5da8dSAndroid Build Coastguard Worker""" 5*cda5da8dSAndroid Build Coastguard Worker 6*cda5da8dSAndroid Build Coastguard Workerversion = "0.20" 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax._exceptions import * 9*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax.handler import feature_validation, feature_namespaces 10*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax.handler import feature_namespace_prefixes 11*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax.handler import feature_external_ges, feature_external_pes 12*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax.handler import feature_string_interning 13*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax.handler import property_xml_string, property_interning_dict 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard Worker# xml.parsers.expat does not raise ImportError in Jython 16*cda5da8dSAndroid Build Coastguard Workerimport sys 17*cda5da8dSAndroid Build Coastguard Workerif sys.platform[:4] == "java": 18*cda5da8dSAndroid Build Coastguard Worker raise SAXReaderNotAvailable("expat not available in Java", None) 19*cda5da8dSAndroid Build Coastguard Workerdel sys 20*cda5da8dSAndroid Build Coastguard Worker 21*cda5da8dSAndroid Build Coastguard Workertry: 22*cda5da8dSAndroid Build Coastguard Worker from xml.parsers import expat 23*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 24*cda5da8dSAndroid Build Coastguard Worker raise SAXReaderNotAvailable("expat not supported", None) 25*cda5da8dSAndroid Build Coastguard Workerelse: 26*cda5da8dSAndroid Build Coastguard Worker if not hasattr(expat, "ParserCreate"): 27*cda5da8dSAndroid Build Coastguard Worker raise SAXReaderNotAvailable("expat not supported", None) 28*cda5da8dSAndroid Build Coastguard Workerfrom xml.sax import xmlreader, saxutils, handler 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard WorkerAttributesImpl = xmlreader.AttributesImpl 31*cda5da8dSAndroid Build Coastguard WorkerAttributesNSImpl = xmlreader.AttributesNSImpl 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker# If we're using a sufficiently recent version of Python, we can use 34*cda5da8dSAndroid Build Coastguard Worker# weak references to avoid cycles between the parser and content 35*cda5da8dSAndroid Build Coastguard Worker# handler, otherwise we'll just have to pretend. 36*cda5da8dSAndroid Build Coastguard Workertry: 37*cda5da8dSAndroid Build Coastguard Worker import _weakref 38*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 39*cda5da8dSAndroid Build Coastguard Worker def _mkproxy(o): 40*cda5da8dSAndroid Build Coastguard Worker return o 41*cda5da8dSAndroid Build Coastguard Workerelse: 42*cda5da8dSAndroid Build Coastguard Worker import weakref 43*cda5da8dSAndroid Build Coastguard Worker _mkproxy = weakref.proxy 44*cda5da8dSAndroid Build Coastguard Worker del weakref, _weakref 45*cda5da8dSAndroid Build Coastguard Worker 46*cda5da8dSAndroid Build Coastguard Workerclass _ClosedParser: 47*cda5da8dSAndroid Build Coastguard Worker pass 48*cda5da8dSAndroid Build Coastguard Worker 49*cda5da8dSAndroid Build Coastguard Worker# --- ExpatLocator 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Workerclass ExpatLocator(xmlreader.Locator): 52*cda5da8dSAndroid Build Coastguard Worker """Locator for use with the ExpatParser class. 53*cda5da8dSAndroid Build Coastguard Worker 54*cda5da8dSAndroid Build Coastguard Worker This uses a weak reference to the parser object to avoid creating 55*cda5da8dSAndroid Build Coastguard Worker a circular reference between the parser and the content handler. 56*cda5da8dSAndroid Build Coastguard Worker """ 57*cda5da8dSAndroid Build Coastguard Worker def __init__(self, parser): 58*cda5da8dSAndroid Build Coastguard Worker self._ref = _mkproxy(parser) 59*cda5da8dSAndroid Build Coastguard Worker 60*cda5da8dSAndroid Build Coastguard Worker def getColumnNumber(self): 61*cda5da8dSAndroid Build Coastguard Worker parser = self._ref 62*cda5da8dSAndroid Build Coastguard Worker if parser._parser is None: 63*cda5da8dSAndroid Build Coastguard Worker return None 64*cda5da8dSAndroid Build Coastguard Worker return parser._parser.ErrorColumnNumber 65*cda5da8dSAndroid Build Coastguard Worker 66*cda5da8dSAndroid Build Coastguard Worker def getLineNumber(self): 67*cda5da8dSAndroid Build Coastguard Worker parser = self._ref 68*cda5da8dSAndroid Build Coastguard Worker if parser._parser is None: 69*cda5da8dSAndroid Build Coastguard Worker return 1 70*cda5da8dSAndroid Build Coastguard Worker return parser._parser.ErrorLineNumber 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Worker def getPublicId(self): 73*cda5da8dSAndroid Build Coastguard Worker parser = self._ref 74*cda5da8dSAndroid Build Coastguard Worker if parser is None: 75*cda5da8dSAndroid Build Coastguard Worker return None 76*cda5da8dSAndroid Build Coastguard Worker return parser._source.getPublicId() 77*cda5da8dSAndroid Build Coastguard Worker 78*cda5da8dSAndroid Build Coastguard Worker def getSystemId(self): 79*cda5da8dSAndroid Build Coastguard Worker parser = self._ref 80*cda5da8dSAndroid Build Coastguard Worker if parser is None: 81*cda5da8dSAndroid Build Coastguard Worker return None 82*cda5da8dSAndroid Build Coastguard Worker return parser._source.getSystemId() 83*cda5da8dSAndroid Build Coastguard Worker 84*cda5da8dSAndroid Build Coastguard Worker 85*cda5da8dSAndroid Build Coastguard Worker# --- ExpatParser 86*cda5da8dSAndroid Build Coastguard Worker 87*cda5da8dSAndroid Build Coastguard Workerclass ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator): 88*cda5da8dSAndroid Build Coastguard Worker """SAX driver for the pyexpat C module.""" 89*cda5da8dSAndroid Build Coastguard Worker 90*cda5da8dSAndroid Build Coastguard Worker def __init__(self, namespaceHandling=0, bufsize=2**16-20): 91*cda5da8dSAndroid Build Coastguard Worker xmlreader.IncrementalParser.__init__(self, bufsize) 92*cda5da8dSAndroid Build Coastguard Worker self._source = xmlreader.InputSource() 93*cda5da8dSAndroid Build Coastguard Worker self._parser = None 94*cda5da8dSAndroid Build Coastguard Worker self._namespaces = namespaceHandling 95*cda5da8dSAndroid Build Coastguard Worker self._lex_handler_prop = None 96*cda5da8dSAndroid Build Coastguard Worker self._parsing = False 97*cda5da8dSAndroid Build Coastguard Worker self._entity_stack = [] 98*cda5da8dSAndroid Build Coastguard Worker self._external_ges = 0 99*cda5da8dSAndroid Build Coastguard Worker self._interning = None 100*cda5da8dSAndroid Build Coastguard Worker 101*cda5da8dSAndroid Build Coastguard Worker # XMLReader methods 102*cda5da8dSAndroid Build Coastguard Worker 103*cda5da8dSAndroid Build Coastguard Worker def parse(self, source): 104*cda5da8dSAndroid Build Coastguard Worker "Parse an XML document from a URL or an InputSource." 105*cda5da8dSAndroid Build Coastguard Worker source = saxutils.prepare_input_source(source) 106*cda5da8dSAndroid Build Coastguard Worker 107*cda5da8dSAndroid Build Coastguard Worker self._source = source 108*cda5da8dSAndroid Build Coastguard Worker try: 109*cda5da8dSAndroid Build Coastguard Worker self.reset() 110*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.setDocumentLocator(ExpatLocator(self)) 111*cda5da8dSAndroid Build Coastguard Worker xmlreader.IncrementalParser.parse(self, source) 112*cda5da8dSAndroid Build Coastguard Worker except: 113*cda5da8dSAndroid Build Coastguard Worker # bpo-30264: Close the source on error to not leak resources: 114*cda5da8dSAndroid Build Coastguard Worker # xml.sax.parse() doesn't give access to the underlying parser 115*cda5da8dSAndroid Build Coastguard Worker # to the caller 116*cda5da8dSAndroid Build Coastguard Worker self._close_source() 117*cda5da8dSAndroid Build Coastguard Worker raise 118*cda5da8dSAndroid Build Coastguard Worker 119*cda5da8dSAndroid Build Coastguard Worker def prepareParser(self, source): 120*cda5da8dSAndroid Build Coastguard Worker if source.getSystemId() is not None: 121*cda5da8dSAndroid Build Coastguard Worker self._parser.SetBase(source.getSystemId()) 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker # Redefined setContentHandler to allow changing handlers during parsing 124*cda5da8dSAndroid Build Coastguard Worker 125*cda5da8dSAndroid Build Coastguard Worker def setContentHandler(self, handler): 126*cda5da8dSAndroid Build Coastguard Worker xmlreader.IncrementalParser.setContentHandler(self, handler) 127*cda5da8dSAndroid Build Coastguard Worker if self._parsing: 128*cda5da8dSAndroid Build Coastguard Worker self._reset_cont_handler() 129*cda5da8dSAndroid Build Coastguard Worker 130*cda5da8dSAndroid Build Coastguard Worker def getFeature(self, name): 131*cda5da8dSAndroid Build Coastguard Worker if name == feature_namespaces: 132*cda5da8dSAndroid Build Coastguard Worker return self._namespaces 133*cda5da8dSAndroid Build Coastguard Worker elif name == feature_string_interning: 134*cda5da8dSAndroid Build Coastguard Worker return self._interning is not None 135*cda5da8dSAndroid Build Coastguard Worker elif name in (feature_validation, feature_external_pes, 136*cda5da8dSAndroid Build Coastguard Worker feature_namespace_prefixes): 137*cda5da8dSAndroid Build Coastguard Worker return 0 138*cda5da8dSAndroid Build Coastguard Worker elif name == feature_external_ges: 139*cda5da8dSAndroid Build Coastguard Worker return self._external_ges 140*cda5da8dSAndroid Build Coastguard Worker raise SAXNotRecognizedException("Feature '%s' not recognized" % name) 141*cda5da8dSAndroid Build Coastguard Worker 142*cda5da8dSAndroid Build Coastguard Worker def setFeature(self, name, state): 143*cda5da8dSAndroid Build Coastguard Worker if self._parsing: 144*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException("Cannot set features while parsing") 145*cda5da8dSAndroid Build Coastguard Worker 146*cda5da8dSAndroid Build Coastguard Worker if name == feature_namespaces: 147*cda5da8dSAndroid Build Coastguard Worker self._namespaces = state 148*cda5da8dSAndroid Build Coastguard Worker elif name == feature_external_ges: 149*cda5da8dSAndroid Build Coastguard Worker self._external_ges = state 150*cda5da8dSAndroid Build Coastguard Worker elif name == feature_string_interning: 151*cda5da8dSAndroid Build Coastguard Worker if state: 152*cda5da8dSAndroid Build Coastguard Worker if self._interning is None: 153*cda5da8dSAndroid Build Coastguard Worker self._interning = {} 154*cda5da8dSAndroid Build Coastguard Worker else: 155*cda5da8dSAndroid Build Coastguard Worker self._interning = None 156*cda5da8dSAndroid Build Coastguard Worker elif name == feature_validation: 157*cda5da8dSAndroid Build Coastguard Worker if state: 158*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException( 159*cda5da8dSAndroid Build Coastguard Worker "expat does not support validation") 160*cda5da8dSAndroid Build Coastguard Worker elif name == feature_external_pes: 161*cda5da8dSAndroid Build Coastguard Worker if state: 162*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException( 163*cda5da8dSAndroid Build Coastguard Worker "expat does not read external parameter entities") 164*cda5da8dSAndroid Build Coastguard Worker elif name == feature_namespace_prefixes: 165*cda5da8dSAndroid Build Coastguard Worker if state: 166*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException( 167*cda5da8dSAndroid Build Coastguard Worker "expat does not report namespace prefixes") 168*cda5da8dSAndroid Build Coastguard Worker else: 169*cda5da8dSAndroid Build Coastguard Worker raise SAXNotRecognizedException( 170*cda5da8dSAndroid Build Coastguard Worker "Feature '%s' not recognized" % name) 171*cda5da8dSAndroid Build Coastguard Worker 172*cda5da8dSAndroid Build Coastguard Worker def getProperty(self, name): 173*cda5da8dSAndroid Build Coastguard Worker if name == handler.property_lexical_handler: 174*cda5da8dSAndroid Build Coastguard Worker return self._lex_handler_prop 175*cda5da8dSAndroid Build Coastguard Worker elif name == property_interning_dict: 176*cda5da8dSAndroid Build Coastguard Worker return self._interning 177*cda5da8dSAndroid Build Coastguard Worker elif name == property_xml_string: 178*cda5da8dSAndroid Build Coastguard Worker if self._parser: 179*cda5da8dSAndroid Build Coastguard Worker if hasattr(self._parser, "GetInputContext"): 180*cda5da8dSAndroid Build Coastguard Worker return self._parser.GetInputContext() 181*cda5da8dSAndroid Build Coastguard Worker else: 182*cda5da8dSAndroid Build Coastguard Worker raise SAXNotRecognizedException( 183*cda5da8dSAndroid Build Coastguard Worker "This version of expat does not support getting" 184*cda5da8dSAndroid Build Coastguard Worker " the XML string") 185*cda5da8dSAndroid Build Coastguard Worker else: 186*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException( 187*cda5da8dSAndroid Build Coastguard Worker "XML string cannot be returned when not parsing") 188*cda5da8dSAndroid Build Coastguard Worker raise SAXNotRecognizedException("Property '%s' not recognized" % name) 189*cda5da8dSAndroid Build Coastguard Worker 190*cda5da8dSAndroid Build Coastguard Worker def setProperty(self, name, value): 191*cda5da8dSAndroid Build Coastguard Worker if name == handler.property_lexical_handler: 192*cda5da8dSAndroid Build Coastguard Worker self._lex_handler_prop = value 193*cda5da8dSAndroid Build Coastguard Worker if self._parsing: 194*cda5da8dSAndroid Build Coastguard Worker self._reset_lex_handler_prop() 195*cda5da8dSAndroid Build Coastguard Worker elif name == property_interning_dict: 196*cda5da8dSAndroid Build Coastguard Worker self._interning = value 197*cda5da8dSAndroid Build Coastguard Worker elif name == property_xml_string: 198*cda5da8dSAndroid Build Coastguard Worker raise SAXNotSupportedException("Property '%s' cannot be set" % 199*cda5da8dSAndroid Build Coastguard Worker name) 200*cda5da8dSAndroid Build Coastguard Worker else: 201*cda5da8dSAndroid Build Coastguard Worker raise SAXNotRecognizedException("Property '%s' not recognized" % 202*cda5da8dSAndroid Build Coastguard Worker name) 203*cda5da8dSAndroid Build Coastguard Worker 204*cda5da8dSAndroid Build Coastguard Worker # IncrementalParser methods 205*cda5da8dSAndroid Build Coastguard Worker 206*cda5da8dSAndroid Build Coastguard Worker def feed(self, data, isFinal=False): 207*cda5da8dSAndroid Build Coastguard Worker if not self._parsing: 208*cda5da8dSAndroid Build Coastguard Worker self.reset() 209*cda5da8dSAndroid Build Coastguard Worker self._parsing = True 210*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.startDocument() 211*cda5da8dSAndroid Build Coastguard Worker 212*cda5da8dSAndroid Build Coastguard Worker try: 213*cda5da8dSAndroid Build Coastguard Worker # The isFinal parameter is internal to the expat reader. 214*cda5da8dSAndroid Build Coastguard Worker # If it is set to true, expat will check validity of the entire 215*cda5da8dSAndroid Build Coastguard Worker # document. When feeding chunks, they are not normally final - 216*cda5da8dSAndroid Build Coastguard Worker # except when invoked from close. 217*cda5da8dSAndroid Build Coastguard Worker self._parser.Parse(data, isFinal) 218*cda5da8dSAndroid Build Coastguard Worker except expat.error as e: 219*cda5da8dSAndroid Build Coastguard Worker exc = SAXParseException(expat.ErrorString(e.code), e, self) 220*cda5da8dSAndroid Build Coastguard Worker # FIXME: when to invoke error()? 221*cda5da8dSAndroid Build Coastguard Worker self._err_handler.fatalError(exc) 222*cda5da8dSAndroid Build Coastguard Worker 223*cda5da8dSAndroid Build Coastguard Worker def _close_source(self): 224*cda5da8dSAndroid Build Coastguard Worker source = self._source 225*cda5da8dSAndroid Build Coastguard Worker try: 226*cda5da8dSAndroid Build Coastguard Worker file = source.getCharacterStream() 227*cda5da8dSAndroid Build Coastguard Worker if file is not None: 228*cda5da8dSAndroid Build Coastguard Worker file.close() 229*cda5da8dSAndroid Build Coastguard Worker finally: 230*cda5da8dSAndroid Build Coastguard Worker file = source.getByteStream() 231*cda5da8dSAndroid Build Coastguard Worker if file is not None: 232*cda5da8dSAndroid Build Coastguard Worker file.close() 233*cda5da8dSAndroid Build Coastguard Worker 234*cda5da8dSAndroid Build Coastguard Worker def close(self): 235*cda5da8dSAndroid Build Coastguard Worker if (self._entity_stack or self._parser is None or 236*cda5da8dSAndroid Build Coastguard Worker isinstance(self._parser, _ClosedParser)): 237*cda5da8dSAndroid Build Coastguard Worker # If we are completing an external entity, do nothing here 238*cda5da8dSAndroid Build Coastguard Worker return 239*cda5da8dSAndroid Build Coastguard Worker try: 240*cda5da8dSAndroid Build Coastguard Worker self.feed(b"", isFinal=True) 241*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.endDocument() 242*cda5da8dSAndroid Build Coastguard Worker self._parsing = False 243*cda5da8dSAndroid Build Coastguard Worker # break cycle created by expat handlers pointing to our methods 244*cda5da8dSAndroid Build Coastguard Worker self._parser = None 245*cda5da8dSAndroid Build Coastguard Worker finally: 246*cda5da8dSAndroid Build Coastguard Worker self._parsing = False 247*cda5da8dSAndroid Build Coastguard Worker if self._parser is not None: 248*cda5da8dSAndroid Build Coastguard Worker # Keep ErrorColumnNumber and ErrorLineNumber after closing. 249*cda5da8dSAndroid Build Coastguard Worker parser = _ClosedParser() 250*cda5da8dSAndroid Build Coastguard Worker parser.ErrorColumnNumber = self._parser.ErrorColumnNumber 251*cda5da8dSAndroid Build Coastguard Worker parser.ErrorLineNumber = self._parser.ErrorLineNumber 252*cda5da8dSAndroid Build Coastguard Worker self._parser = parser 253*cda5da8dSAndroid Build Coastguard Worker self._close_source() 254*cda5da8dSAndroid Build Coastguard Worker 255*cda5da8dSAndroid Build Coastguard Worker def _reset_cont_handler(self): 256*cda5da8dSAndroid Build Coastguard Worker self._parser.ProcessingInstructionHandler = \ 257*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.processingInstruction 258*cda5da8dSAndroid Build Coastguard Worker self._parser.CharacterDataHandler = self._cont_handler.characters 259*cda5da8dSAndroid Build Coastguard Worker 260*cda5da8dSAndroid Build Coastguard Worker def _reset_lex_handler_prop(self): 261*cda5da8dSAndroid Build Coastguard Worker lex = self._lex_handler_prop 262*cda5da8dSAndroid Build Coastguard Worker parser = self._parser 263*cda5da8dSAndroid Build Coastguard Worker if lex is None: 264*cda5da8dSAndroid Build Coastguard Worker parser.CommentHandler = None 265*cda5da8dSAndroid Build Coastguard Worker parser.StartCdataSectionHandler = None 266*cda5da8dSAndroid Build Coastguard Worker parser.EndCdataSectionHandler = None 267*cda5da8dSAndroid Build Coastguard Worker parser.StartDoctypeDeclHandler = None 268*cda5da8dSAndroid Build Coastguard Worker parser.EndDoctypeDeclHandler = None 269*cda5da8dSAndroid Build Coastguard Worker else: 270*cda5da8dSAndroid Build Coastguard Worker parser.CommentHandler = lex.comment 271*cda5da8dSAndroid Build Coastguard Worker parser.StartCdataSectionHandler = lex.startCDATA 272*cda5da8dSAndroid Build Coastguard Worker parser.EndCdataSectionHandler = lex.endCDATA 273*cda5da8dSAndroid Build Coastguard Worker parser.StartDoctypeDeclHandler = self.start_doctype_decl 274*cda5da8dSAndroid Build Coastguard Worker parser.EndDoctypeDeclHandler = lex.endDTD 275*cda5da8dSAndroid Build Coastguard Worker 276*cda5da8dSAndroid Build Coastguard Worker def reset(self): 277*cda5da8dSAndroid Build Coastguard Worker if self._namespaces: 278*cda5da8dSAndroid Build Coastguard Worker self._parser = expat.ParserCreate(self._source.getEncoding(), " ", 279*cda5da8dSAndroid Build Coastguard Worker intern=self._interning) 280*cda5da8dSAndroid Build Coastguard Worker self._parser.namespace_prefixes = 1 281*cda5da8dSAndroid Build Coastguard Worker self._parser.StartElementHandler = self.start_element_ns 282*cda5da8dSAndroid Build Coastguard Worker self._parser.EndElementHandler = self.end_element_ns 283*cda5da8dSAndroid Build Coastguard Worker else: 284*cda5da8dSAndroid Build Coastguard Worker self._parser = expat.ParserCreate(self._source.getEncoding(), 285*cda5da8dSAndroid Build Coastguard Worker intern = self._interning) 286*cda5da8dSAndroid Build Coastguard Worker self._parser.StartElementHandler = self.start_element 287*cda5da8dSAndroid Build Coastguard Worker self._parser.EndElementHandler = self.end_element 288*cda5da8dSAndroid Build Coastguard Worker 289*cda5da8dSAndroid Build Coastguard Worker self._reset_cont_handler() 290*cda5da8dSAndroid Build Coastguard Worker self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl 291*cda5da8dSAndroid Build Coastguard Worker self._parser.NotationDeclHandler = self.notation_decl 292*cda5da8dSAndroid Build Coastguard Worker self._parser.StartNamespaceDeclHandler = self.start_namespace_decl 293*cda5da8dSAndroid Build Coastguard Worker self._parser.EndNamespaceDeclHandler = self.end_namespace_decl 294*cda5da8dSAndroid Build Coastguard Worker 295*cda5da8dSAndroid Build Coastguard Worker self._decl_handler_prop = None 296*cda5da8dSAndroid Build Coastguard Worker if self._lex_handler_prop: 297*cda5da8dSAndroid Build Coastguard Worker self._reset_lex_handler_prop() 298*cda5da8dSAndroid Build Coastguard Worker# self._parser.DefaultHandler = 299*cda5da8dSAndroid Build Coastguard Worker# self._parser.DefaultHandlerExpand = 300*cda5da8dSAndroid Build Coastguard Worker# self._parser.NotStandaloneHandler = 301*cda5da8dSAndroid Build Coastguard Worker self._parser.ExternalEntityRefHandler = self.external_entity_ref 302*cda5da8dSAndroid Build Coastguard Worker try: 303*cda5da8dSAndroid Build Coastguard Worker self._parser.SkippedEntityHandler = self.skipped_entity_handler 304*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 305*cda5da8dSAndroid Build Coastguard Worker # This pyexpat does not support SkippedEntity 306*cda5da8dSAndroid Build Coastguard Worker pass 307*cda5da8dSAndroid Build Coastguard Worker self._parser.SetParamEntityParsing( 308*cda5da8dSAndroid Build Coastguard Worker expat.XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) 309*cda5da8dSAndroid Build Coastguard Worker 310*cda5da8dSAndroid Build Coastguard Worker self._parsing = False 311*cda5da8dSAndroid Build Coastguard Worker self._entity_stack = [] 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Worker # Locator methods 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Worker def getColumnNumber(self): 316*cda5da8dSAndroid Build Coastguard Worker if self._parser is None: 317*cda5da8dSAndroid Build Coastguard Worker return None 318*cda5da8dSAndroid Build Coastguard Worker return self._parser.ErrorColumnNumber 319*cda5da8dSAndroid Build Coastguard Worker 320*cda5da8dSAndroid Build Coastguard Worker def getLineNumber(self): 321*cda5da8dSAndroid Build Coastguard Worker if self._parser is None: 322*cda5da8dSAndroid Build Coastguard Worker return 1 323*cda5da8dSAndroid Build Coastguard Worker return self._parser.ErrorLineNumber 324*cda5da8dSAndroid Build Coastguard Worker 325*cda5da8dSAndroid Build Coastguard Worker def getPublicId(self): 326*cda5da8dSAndroid Build Coastguard Worker return self._source.getPublicId() 327*cda5da8dSAndroid Build Coastguard Worker 328*cda5da8dSAndroid Build Coastguard Worker def getSystemId(self): 329*cda5da8dSAndroid Build Coastguard Worker return self._source.getSystemId() 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Worker # event handlers 332*cda5da8dSAndroid Build Coastguard Worker def start_element(self, name, attrs): 333*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.startElement(name, AttributesImpl(attrs)) 334*cda5da8dSAndroid Build Coastguard Worker 335*cda5da8dSAndroid Build Coastguard Worker def end_element(self, name): 336*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.endElement(name) 337*cda5da8dSAndroid Build Coastguard Worker 338*cda5da8dSAndroid Build Coastguard Worker def start_element_ns(self, name, attrs): 339*cda5da8dSAndroid Build Coastguard Worker pair = name.split() 340*cda5da8dSAndroid Build Coastguard Worker if len(pair) == 1: 341*cda5da8dSAndroid Build Coastguard Worker # no namespace 342*cda5da8dSAndroid Build Coastguard Worker pair = (None, name) 343*cda5da8dSAndroid Build Coastguard Worker elif len(pair) == 3: 344*cda5da8dSAndroid Build Coastguard Worker pair = pair[0], pair[1] 345*cda5da8dSAndroid Build Coastguard Worker else: 346*cda5da8dSAndroid Build Coastguard Worker # default namespace 347*cda5da8dSAndroid Build Coastguard Worker pair = tuple(pair) 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Worker newattrs = {} 350*cda5da8dSAndroid Build Coastguard Worker qnames = {} 351*cda5da8dSAndroid Build Coastguard Worker for (aname, value) in attrs.items(): 352*cda5da8dSAndroid Build Coastguard Worker parts = aname.split() 353*cda5da8dSAndroid Build Coastguard Worker length = len(parts) 354*cda5da8dSAndroid Build Coastguard Worker if length == 1: 355*cda5da8dSAndroid Build Coastguard Worker # no namespace 356*cda5da8dSAndroid Build Coastguard Worker qname = aname 357*cda5da8dSAndroid Build Coastguard Worker apair = (None, aname) 358*cda5da8dSAndroid Build Coastguard Worker elif length == 3: 359*cda5da8dSAndroid Build Coastguard Worker qname = "%s:%s" % (parts[2], parts[1]) 360*cda5da8dSAndroid Build Coastguard Worker apair = parts[0], parts[1] 361*cda5da8dSAndroid Build Coastguard Worker else: 362*cda5da8dSAndroid Build Coastguard Worker # default namespace 363*cda5da8dSAndroid Build Coastguard Worker qname = parts[1] 364*cda5da8dSAndroid Build Coastguard Worker apair = tuple(parts) 365*cda5da8dSAndroid Build Coastguard Worker 366*cda5da8dSAndroid Build Coastguard Worker newattrs[apair] = value 367*cda5da8dSAndroid Build Coastguard Worker qnames[apair] = qname 368*cda5da8dSAndroid Build Coastguard Worker 369*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.startElementNS(pair, None, 370*cda5da8dSAndroid Build Coastguard Worker AttributesNSImpl(newattrs, qnames)) 371*cda5da8dSAndroid Build Coastguard Worker 372*cda5da8dSAndroid Build Coastguard Worker def end_element_ns(self, name): 373*cda5da8dSAndroid Build Coastguard Worker pair = name.split() 374*cda5da8dSAndroid Build Coastguard Worker if len(pair) == 1: 375*cda5da8dSAndroid Build Coastguard Worker pair = (None, name) 376*cda5da8dSAndroid Build Coastguard Worker elif len(pair) == 3: 377*cda5da8dSAndroid Build Coastguard Worker pair = pair[0], pair[1] 378*cda5da8dSAndroid Build Coastguard Worker else: 379*cda5da8dSAndroid Build Coastguard Worker pair = tuple(pair) 380*cda5da8dSAndroid Build Coastguard Worker 381*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.endElementNS(pair, None) 382*cda5da8dSAndroid Build Coastguard Worker 383*cda5da8dSAndroid Build Coastguard Worker # this is not used (call directly to ContentHandler) 384*cda5da8dSAndroid Build Coastguard Worker def processing_instruction(self, target, data): 385*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.processingInstruction(target, data) 386*cda5da8dSAndroid Build Coastguard Worker 387*cda5da8dSAndroid Build Coastguard Worker # this is not used (call directly to ContentHandler) 388*cda5da8dSAndroid Build Coastguard Worker def character_data(self, data): 389*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.characters(data) 390*cda5da8dSAndroid Build Coastguard Worker 391*cda5da8dSAndroid Build Coastguard Worker def start_namespace_decl(self, prefix, uri): 392*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.startPrefixMapping(prefix, uri) 393*cda5da8dSAndroid Build Coastguard Worker 394*cda5da8dSAndroid Build Coastguard Worker def end_namespace_decl(self, prefix): 395*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.endPrefixMapping(prefix) 396*cda5da8dSAndroid Build Coastguard Worker 397*cda5da8dSAndroid Build Coastguard Worker def start_doctype_decl(self, name, sysid, pubid, has_internal_subset): 398*cda5da8dSAndroid Build Coastguard Worker self._lex_handler_prop.startDTD(name, pubid, sysid) 399*cda5da8dSAndroid Build Coastguard Worker 400*cda5da8dSAndroid Build Coastguard Worker def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): 401*cda5da8dSAndroid Build Coastguard Worker self._dtd_handler.unparsedEntityDecl(name, pubid, sysid, notation_name) 402*cda5da8dSAndroid Build Coastguard Worker 403*cda5da8dSAndroid Build Coastguard Worker def notation_decl(self, name, base, sysid, pubid): 404*cda5da8dSAndroid Build Coastguard Worker self._dtd_handler.notationDecl(name, pubid, sysid) 405*cda5da8dSAndroid Build Coastguard Worker 406*cda5da8dSAndroid Build Coastguard Worker def external_entity_ref(self, context, base, sysid, pubid): 407*cda5da8dSAndroid Build Coastguard Worker if not self._external_ges: 408*cda5da8dSAndroid Build Coastguard Worker return 1 409*cda5da8dSAndroid Build Coastguard Worker 410*cda5da8dSAndroid Build Coastguard Worker source = self._ent_handler.resolveEntity(pubid, sysid) 411*cda5da8dSAndroid Build Coastguard Worker source = saxutils.prepare_input_source(source, 412*cda5da8dSAndroid Build Coastguard Worker self._source.getSystemId() or 413*cda5da8dSAndroid Build Coastguard Worker "") 414*cda5da8dSAndroid Build Coastguard Worker 415*cda5da8dSAndroid Build Coastguard Worker self._entity_stack.append((self._parser, self._source)) 416*cda5da8dSAndroid Build Coastguard Worker self._parser = self._parser.ExternalEntityParserCreate(context) 417*cda5da8dSAndroid Build Coastguard Worker self._source = source 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker try: 420*cda5da8dSAndroid Build Coastguard Worker xmlreader.IncrementalParser.parse(self, source) 421*cda5da8dSAndroid Build Coastguard Worker except: 422*cda5da8dSAndroid Build Coastguard Worker return 0 # FIXME: save error info here? 423*cda5da8dSAndroid Build Coastguard Worker 424*cda5da8dSAndroid Build Coastguard Worker (self._parser, self._source) = self._entity_stack[-1] 425*cda5da8dSAndroid Build Coastguard Worker del self._entity_stack[-1] 426*cda5da8dSAndroid Build Coastguard Worker return 1 427*cda5da8dSAndroid Build Coastguard Worker 428*cda5da8dSAndroid Build Coastguard Worker def skipped_entity_handler(self, name, is_pe): 429*cda5da8dSAndroid Build Coastguard Worker if is_pe: 430*cda5da8dSAndroid Build Coastguard Worker # The SAX spec requires to report skipped PEs with a '%' 431*cda5da8dSAndroid Build Coastguard Worker name = '%'+name 432*cda5da8dSAndroid Build Coastguard Worker self._cont_handler.skippedEntity(name) 433*cda5da8dSAndroid Build Coastguard Worker 434*cda5da8dSAndroid Build Coastguard Worker# --- 435*cda5da8dSAndroid Build Coastguard Worker 436*cda5da8dSAndroid Build Coastguard Workerdef create_parser(*args, **kwargs): 437*cda5da8dSAndroid Build Coastguard Worker return ExpatParser(*args, **kwargs) 438*cda5da8dSAndroid Build Coastguard Worker 439*cda5da8dSAndroid Build Coastguard Worker# --- 440*cda5da8dSAndroid Build Coastguard Worker 441*cda5da8dSAndroid Build Coastguard Workerif __name__ == "__main__": 442*cda5da8dSAndroid Build Coastguard Worker import xml.sax.saxutils 443*cda5da8dSAndroid Build Coastguard Worker p = create_parser() 444*cda5da8dSAndroid Build Coastguard Worker p.setContentHandler(xml.sax.saxutils.XMLGenerator()) 445*cda5da8dSAndroid Build Coastguard Worker p.setErrorHandler(xml.sax.ErrorHandler()) 446*cda5da8dSAndroid Build Coastguard Worker p.parse("http://www.ibiblio.org/xml/examples/shakespeare/hamlet.xml") 447