diff options
Diffstat (limited to 'Lib/xmllib.py')
-rw-r--r-- | Lib/xmllib.py | 912 |
1 files changed, 456 insertions, 456 deletions
diff --git a/Lib/xmllib.py b/Lib/xmllib.py index 9f6e23e..6d7f1d1 100644 --- a/Lib/xmllib.py +++ b/Lib/xmllib.py @@ -12,10 +12,10 @@ _opS = '[ \t\r\n]*' _Name = '[a-zA-Z_:][-a-zA-Z0-9._:]*' interesting = re.compile('[&<]') incomplete = re.compile('&(' + _Name + '|#[0-9]*|#x[0-9a-fA-F]*)?|' - '<([a-zA-Z_:][^<>]*|' - '/([a-zA-Z_:][^<>]*)?|' - '![^<>]*|' - r'\?[^<>]*)?') + '<([a-zA-Z_:][^<>]*|' + '/([a-zA-Z_:][^<>]*)?|' + '![^<>]*|' + r'\?[^<>]*)?') ref = re.compile('&(' + _Name + '|#[0-9]+|#x[0-9a-fA-F]+);?') entityref = re.compile('&(?P<name>' + _Name + ')[^-a-zA-Z0-9._:]') @@ -57,497 +57,497 @@ class XMLParser: # Interface -- initialize and reset this instance def __init__(self, verbose=0): - self.verbose = verbose - self.reset() + self.verbose = verbose + self.reset() # Interface -- reset this instance. Loses all unprocessed data def reset(self): - self.rawdata = '' - self.stack = [] - self.nomoretags = 0 - self.literal = 0 - self.lineno = 1 - self.__at_start = 1 - self.__seen_doctype = None - self.__seen_starttag = 0 + self.rawdata = '' + self.stack = [] + self.nomoretags = 0 + self.literal = 0 + self.lineno = 1 + self.__at_start = 1 + self.__seen_doctype = None + self.__seen_starttag = 0 # For derived classes only -- enter literal mode (CDATA) till EOF def setnomoretags(self): - self.nomoretags = self.literal = 1 + self.nomoretags = self.literal = 1 # For derived classes only -- enter literal mode (CDATA) def setliteral(self, *args): - self.literal = 1 + self.literal = 1 # Interface -- feed some data to the parser. Call this as # often as you want, with as little or as much text as you # want (may include '\n'). (This just saves the text, all the # processing is done by goahead().) def feed(self, data): - self.rawdata = self.rawdata + data - self.goahead(0) + self.rawdata = self.rawdata + data + self.goahead(0) # Interface -- handle the remaining data def close(self): - self.goahead(1) + self.goahead(1) # Interface -- translate references def translate_references(self, data): - newdata = [] - i = 0 - while 1: - res = ref.search(data, i) - if res is None: - newdata.append(data[i:]) - return string.join(newdata, '') - if data[res.end(0) - 1] != ';': - self.syntax_error("`;' missing after entity/char reference") - newdata.append(data[i:res.start(0)]) - str = res.group(1) - if str[0] == '#': - if str[1] == 'x': - newdata.append(chr(string.atoi(str[2:], 16))) - else: - newdata.append(chr(string.atoi(str[1:]))) - else: - try: - newdata.append(self.entitydefs[str]) - except KeyError: - # can't do it, so keep the entity ref in - newdata.append('&' + str + ';') - i = res.end(0) + newdata = [] + i = 0 + while 1: + res = ref.search(data, i) + if res is None: + newdata.append(data[i:]) + return string.join(newdata, '') + if data[res.end(0) - 1] != ';': + self.syntax_error("`;' missing after entity/char reference") + newdata.append(data[i:res.start(0)]) + str = res.group(1) + if str[0] == '#': + if str[1] == 'x': + newdata.append(chr(string.atoi(str[2:], 16))) + else: + newdata.append(chr(string.atoi(str[1:]))) + else: + try: + newdata.append(self.entitydefs[str]) + except KeyError: + # can't do it, so keep the entity ref in + newdata.append('&' + str + ';') + i = res.end(0) # Internal -- handle data as far as reasonable. May leave state # and data to be processed by a subsequent call. If 'end' is # true, force handling all data as if followed by EOF marker. def goahead(self, end): - rawdata = self.rawdata - i = 0 - n = len(rawdata) - while i < n: - if i > 0: - self.__at_start = 0 - if self.nomoretags: - data = rawdata[i:n] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = n - break - res = interesting.search(rawdata, i) - if res: - j = res.start(0) - else: - j = n - if i < j: - self.__at_start = 0 - data = rawdata[i:j] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = j - if i == n: break - if rawdata[i] == '<': - if starttagopen.match(rawdata, i): - if self.literal: - data = rawdata[i] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = i+1 - continue - k = self.parse_starttag(i) - if k < 0: break - self.__seen_starttag = 1 - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') - i = k - continue - if endtagopen.match(rawdata, i): - k = self.parse_endtag(i) - if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') - i = k - self.literal = 0 - continue - if commentopen.match(rawdata, i): - if self.literal: - data = rawdata[i] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = i+1 - continue - k = self.parse_comment(i) - if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') - i = k - continue - if cdataopen.match(rawdata, i): - k = self.parse_cdata(i) - if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:i], '\n') - i = k - continue - res = procopen.match(rawdata, i) - if res: - k = self.parse_proc(i) - if k < 0: break - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') - i = k - continue - res = doctype.match(rawdata, i) - if res: - if self.literal: - data = rawdata[i] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = i+1 - continue - if self.__seen_doctype: - self.syntax_error('multiple DOCTYPE elements') - if self.__seen_starttag: - self.syntax_error('DOCTYPE not at beginning of document') - k = self.parse_doctype(res) - if k < 0: break - self.__seen_doctype = res.group('name') - self.lineno = self.lineno + string.count(rawdata[i:k], '\n') - i = k - continue - res = special.match(rawdata, i) - if res: - if self.literal: - data = rawdata[i] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = i+1 - continue - self.handle_special(res.group('special')) - self.lineno = self.lineno + string.count(res.group(0), '\n') - i = res.end(0) - continue - elif rawdata[i] == '&': - res = charref.match(rawdata, i) - if res is not None: - i = res.end(0) - if rawdata[i-1] != ';': - self.syntax_error("`;' missing in charref") - i = i-1 - self.handle_charref(res.group('char')[:-1]) - self.lineno = self.lineno + string.count(res.group(0), '\n') - continue - res = entityref.match(rawdata, i) - if res is not None: - i = res.end(0) - if rawdata[i-1] != ';': - self.syntax_error("`;' missing in entityref") - i = i-1 - self.handle_entityref(res.group('name')) - self.lineno = self.lineno + string.count(res.group(0), '\n') - continue - else: - raise RuntimeError, 'neither < nor & ??' - # We get here only if incomplete matches but - # nothing else - res = incomplete.match(rawdata, i) - if not res: - data = rawdata[i] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = i+1 - continue - j = res.end(0) - if j == n: - break # Really incomplete - self.syntax_error("bogus `<' or `&'") - data = res.group(0) - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = j - # end while - if end and i < n: - data = rawdata[i:n] - self.handle_data(data) - self.lineno = self.lineno + string.count(data, '\n') - i = n - self.rawdata = rawdata[i:] - if end: - if self.stack: - self.syntax_error('missing end tags') - while self.stack: - self.finish_endtag(self.stack[-1]) + rawdata = self.rawdata + i = 0 + n = len(rawdata) + while i < n: + if i > 0: + self.__at_start = 0 + if self.nomoretags: + data = rawdata[i:n] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = n + break + res = interesting.search(rawdata, i) + if res: + j = res.start(0) + else: + j = n + if i < j: + self.__at_start = 0 + data = rawdata[i:j] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = j + if i == n: break + if rawdata[i] == '<': + if starttagopen.match(rawdata, i): + if self.literal: + data = rawdata[i] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = i+1 + continue + k = self.parse_starttag(i) + if k < 0: break + self.__seen_starttag = 1 + self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + i = k + continue + if endtagopen.match(rawdata, i): + k = self.parse_endtag(i) + if k < 0: break + self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + i = k + self.literal = 0 + continue + if commentopen.match(rawdata, i): + if self.literal: + data = rawdata[i] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = i+1 + continue + k = self.parse_comment(i) + if k < 0: break + self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + i = k + continue + if cdataopen.match(rawdata, i): + k = self.parse_cdata(i) + if k < 0: break + self.lineno = self.lineno + string.count(rawdata[i:i], '\n') + i = k + continue + res = procopen.match(rawdata, i) + if res: + k = self.parse_proc(i) + if k < 0: break + self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + i = k + continue + res = doctype.match(rawdata, i) + if res: + if self.literal: + data = rawdata[i] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = i+1 + continue + if self.__seen_doctype: + self.syntax_error('multiple DOCTYPE elements') + if self.__seen_starttag: + self.syntax_error('DOCTYPE not at beginning of document') + k = self.parse_doctype(res) + if k < 0: break + self.__seen_doctype = res.group('name') + self.lineno = self.lineno + string.count(rawdata[i:k], '\n') + i = k + continue + res = special.match(rawdata, i) + if res: + if self.literal: + data = rawdata[i] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = i+1 + continue + self.handle_special(res.group('special')) + self.lineno = self.lineno + string.count(res.group(0), '\n') + i = res.end(0) + continue + elif rawdata[i] == '&': + res = charref.match(rawdata, i) + if res is not None: + i = res.end(0) + if rawdata[i-1] != ';': + self.syntax_error("`;' missing in charref") + i = i-1 + self.handle_charref(res.group('char')[:-1]) + self.lineno = self.lineno + string.count(res.group(0), '\n') + continue + res = entityref.match(rawdata, i) + if res is not None: + i = res.end(0) + if rawdata[i-1] != ';': + self.syntax_error("`;' missing in entityref") + i = i-1 + self.handle_entityref(res.group('name')) + self.lineno = self.lineno + string.count(res.group(0), '\n') + continue + else: + raise RuntimeError, 'neither < nor & ??' + # We get here only if incomplete matches but + # nothing else + res = incomplete.match(rawdata, i) + if not res: + data = rawdata[i] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = i+1 + continue + j = res.end(0) + if j == n: + break # Really incomplete + self.syntax_error("bogus `<' or `&'") + data = res.group(0) + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = j + # end while + if end and i < n: + data = rawdata[i:n] + self.handle_data(data) + self.lineno = self.lineno + string.count(data, '\n') + i = n + self.rawdata = rawdata[i:] + if end: + if self.stack: + self.syntax_error('missing end tags') + while self.stack: + self.finish_endtag(self.stack[-1]) # Internal -- parse comment, return length or -1 if not terminated def parse_comment(self, i): - rawdata = self.rawdata - if rawdata[i:i+4] <> '<!--': - raise RuntimeError, 'unexpected call to handle_comment' - res = commentclose.search(rawdata, i+4) - if not res: - return -1 - # doubledash search will succeed because it's a subset of commentclose - if doubledash.search(rawdata, i+4).start(0) < res.start(0): - self.syntax_error("`--' inside comment") - self.handle_comment(rawdata[i+4: res.start(0)]) - return res.end(0) + rawdata = self.rawdata + if rawdata[i:i+4] <> '<!--': + raise RuntimeError, 'unexpected call to handle_comment' + res = commentclose.search(rawdata, i+4) + if not res: + return -1 + # doubledash search will succeed because it's a subset of commentclose + if doubledash.search(rawdata, i+4).start(0) < res.start(0): + self.syntax_error("`--' inside comment") + self.handle_comment(rawdata[i+4: res.start(0)]) + return res.end(0) # Internal -- handle DOCTYPE tag, return length or -1 if not terminated def parse_doctype(self, res): - rawdata = self.rawdata - n = len(rawdata) - name = res.group('name') - j = k = res.end(0) - level = 0 - while k < n: - c = rawdata[k] - if c == '<': - level = level + 1 - elif c == '>': - if level == 0: - self.handle_doctype(name, rawdata[j:k]) - return k+1 - level = level - 1 - k = k+1 - return -1 + rawdata = self.rawdata + n = len(rawdata) + name = res.group('name') + j = k = res.end(0) + level = 0 + while k < n: + c = rawdata[k] + if c == '<': + level = level + 1 + elif c == '>': + if level == 0: + self.handle_doctype(name, rawdata[j:k]) + return k+1 + level = level - 1 + k = k+1 + return -1 # Internal -- handle CDATA tag, return length or -1 if not terminated def parse_cdata(self, i): - rawdata = self.rawdata - if rawdata[i:i+9] <> '<![CDATA[': - raise RuntimeError, 'unexpected call to handle_cdata' - res = cdataclose.search(rawdata, i+9) - if not res: - return -1 - self.handle_cdata(rawdata[i+9:res.start(0)]) - return res.end(0) + rawdata = self.rawdata + if rawdata[i:i+9] <> '<![CDATA[': + raise RuntimeError, 'unexpected call to handle_cdata' + res = cdataclose.search(rawdata, i+9) + if not res: + return -1 + self.handle_cdata(rawdata[i+9:res.start(0)]) + return res.end(0) __xml_attributes = {'version': '1.0', 'standalone': 'no', 'encoding': None} # Internal -- handle a processing instruction tag def parse_proc(self, i): - rawdata = self.rawdata - end = procclose.search(rawdata, i) - if not end: - return -1 - j = end.start(0) - res = tagfind.match(rawdata, i+2) - if not res: - raise RuntimeError, 'unexpected call to parse_proc' - k = res.end(0) - name = res.group(0) - if name == 'xml': - if self.__at_start: - attrdict, k = self.parse_attributes('xml', k, j, - self.__xml_attributes) - if k != j: - self.syntax_error('garbage at end of <?xml?>') - if attrdict['version'] != '1.0': - self.syntax_error('only XML version 1.0 supported') - self.handle_xml(attrdict.get('encoding', None), - attrdict['standalone']) - return end.end(0) - else: - self.syntax_error("<?xml?> tag not at start of document") - self.handle_proc(name, rawdata[k:j]) - return end.end(0) + rawdata = self.rawdata + end = procclose.search(rawdata, i) + if not end: + return -1 + j = end.start(0) + res = tagfind.match(rawdata, i+2) + if not res: + raise RuntimeError, 'unexpected call to parse_proc' + k = res.end(0) + name = res.group(0) + if name == 'xml': + if self.__at_start: + attrdict, k = self.parse_attributes('xml', k, j, + self.__xml_attributes) + if k != j: + self.syntax_error('garbage at end of <?xml?>') + if attrdict['version'] != '1.0': + self.syntax_error('only XML version 1.0 supported') + self.handle_xml(attrdict.get('encoding', None), + attrdict['standalone']) + return end.end(0) + else: + self.syntax_error("<?xml?> tag not at start of document") + self.handle_proc(name, rawdata[k:j]) + return end.end(0) # Internal -- parse attributes between i and j def parse_attributes(self, tag, k, j, attributes = None): - rawdata = self.rawdata - # Now parse the data between k and j into a tag and attrs - attrdict = {} - try: - # convert attributes list to dictionary - d = {} - for a in attributes: - d[a] = None - attributes = d - except TypeError: - pass - while k < j: - res = attrfind.match(rawdata, k) - if not res: break - attrname, attrvalue = res.group('name', 'value') - if attrvalue is None: - self.syntax_error('no attribute value specified') - attrvalue = attrname - elif attrvalue[:1] == "'" == attrvalue[-1:] or \ - attrvalue[:1] == '"' == attrvalue[-1:]: - attrvalue = attrvalue[1:-1] - else: - self.syntax_error('attribute value not quoted') - if attributes is not None and not attributes.has_key(attrname): - self.syntax_error('unknown attribute %s of element %s' % - (attrname, tag)) - if attrdict.has_key(attrname): - self.syntax_error('attribute specified twice') - attrdict[attrname] = self.translate_references(attrvalue) - k = res.end(0) - if attributes is not None: - # fill in with default attributes - for key, val in attributes.items(): - if val is not None and not attrdict.has_key(key): - attrdict[key] = val - return attrdict, k + rawdata = self.rawdata + # Now parse the data between k and j into a tag and attrs + attrdict = {} + try: + # convert attributes list to dictionary + d = {} + for a in attributes: + d[a] = None + attributes = d + except TypeError: + pass + while k < j: + res = attrfind.match(rawdata, k) + if not res: break + attrname, attrvalue = res.group('name', 'value') + if attrvalue is None: + self.syntax_error('no attribute value specified') + attrvalue = attrname + elif attrvalue[:1] == "'" == attrvalue[-1:] or \ + attrvalue[:1] == '"' == attrvalue[-1:]: + attrvalue = attrvalue[1:-1] + else: + self.syntax_error('attribute value not quoted') + if attributes is not None and not attributes.has_key(attrname): + self.syntax_error('unknown attribute %s of element %s' % + (attrname, tag)) + if attrdict.has_key(attrname): + self.syntax_error('attribute specified twice') + attrdict[attrname] = self.translate_references(attrvalue) + k = res.end(0) + if attributes is not None: + # fill in with default attributes + for key, val in attributes.items(): + if val is not None and not attrdict.has_key(key): + attrdict[key] = val + return attrdict, k # Internal -- handle starttag, return length or -1 if not terminated def parse_starttag(self, i): - rawdata = self.rawdata - # i points to start of tag - end = endbracket.search(rawdata, i+1) - if not end: - return -1 - j = end.start(0) - res = tagfind.match(rawdata, i+1) - if not res: - raise RuntimeError, 'unexpected call to parse_starttag' - k = res.end(0) - tag = res.group(0) - if not self.__seen_starttag and self.__seen_doctype: - if tag != self.__seen_doctype: - self.syntax_error('starttag does not match DOCTYPE') - if hasattr(self, tag + '_attributes'): - attributes = getattr(self, tag + '_attributes') - else: - attributes = None - attrdict, k = self.parse_attributes(tag, k, j, attributes) - res = starttagend.match(rawdata, k) - if not res: - self.syntax_error('garbage in start tag') - self.finish_starttag(tag, attrdict) - if res and res.group('slash') == '/': - self.finish_endtag(tag) - return end.end(0) + rawdata = self.rawdata + # i points to start of tag + end = endbracket.search(rawdata, i+1) + if not end: + return -1 + j = end.start(0) + res = tagfind.match(rawdata, i+1) + if not res: + raise RuntimeError, 'unexpected call to parse_starttag' + k = res.end(0) + tag = res.group(0) + if not self.__seen_starttag and self.__seen_doctype: + if tag != self.__seen_doctype: + self.syntax_error('starttag does not match DOCTYPE') + if hasattr(self, tag + '_attributes'): + attributes = getattr(self, tag + '_attributes') + else: + attributes = None + attrdict, k = self.parse_attributes(tag, k, j, attributes) + res = starttagend.match(rawdata, k) + if not res: + self.syntax_error('garbage in start tag') + self.finish_starttag(tag, attrdict) + if res and res.group('slash') == '/': + self.finish_endtag(tag) + return end.end(0) # Internal -- parse endtag def parse_endtag(self, i): - rawdata = self.rawdata - end = endbracket.search(rawdata, i+1) - if not end: - return -1 - res = tagfind.match(rawdata, i+2) - if not res: - self.syntax_error('no name specified in end tag') - tag = '' - k = i+2 - else: - tag = res.group(0) - k = res.end(0) - if k != end.start(0): - # check that there is only white space at end of tag - res = space.match(rawdata, k) - if res is None or res.end(0) != end.start(0): - self.syntax_error('garbage in end tag') - self.finish_endtag(tag) - return end.end(0) + rawdata = self.rawdata + end = endbracket.search(rawdata, i+1) + if not end: + return -1 + res = tagfind.match(rawdata, i+2) + if not res: + self.syntax_error('no name specified in end tag') + tag = '' + k = i+2 + else: + tag = res.group(0) + k = res.end(0) + if k != end.start(0): + # check that there is only white space at end of tag + res = space.match(rawdata, k) + if res is None or res.end(0) != end.start(0): + self.syntax_error('garbage in end tag') + self.finish_endtag(tag) + return end.end(0) # Internal -- finish processing of start tag # Return -1 for unknown tag, 1 for balanced tag def finish_starttag(self, tag, attrs): - self.stack.append(tag) - try: - method = getattr(self, 'start_' + tag) - except AttributeError: - self.unknown_starttag(tag, attrs) - return -1 - else: - self.handle_starttag(tag, method, attrs) - return 1 + self.stack.append(tag) + try: + method = getattr(self, 'start_' + tag) + except AttributeError: + self.unknown_starttag(tag, attrs) + return -1 + else: + self.handle_starttag(tag, method, attrs) + return 1 # Internal -- finish processing of end tag def finish_endtag(self, tag): - if not tag: - self.syntax_error('name-less end tag') - found = len(self.stack) - 1 - if found < 0: - self.unknown_endtag(tag) - return - else: - if tag not in self.stack: - self.syntax_error('unopened end tag') - try: - method = getattr(self, 'end_' + tag) - except AttributeError: - self.unknown_endtag(tag) - return - found = len(self.stack) - for i in range(found): - if self.stack[i] == tag: - found = i - while len(self.stack) > found: - if found < len(self.stack) - 1: - self.syntax_error('missing close tag for %s' % self.stack[-1]) - tag = self.stack[-1] - try: - method = getattr(self, 'end_' + tag) - except AttributeError: - method = None - if method: - self.handle_endtag(tag, method) - else: - self.unknown_endtag(tag) - del self.stack[-1] + if not tag: + self.syntax_error('name-less end tag') + found = len(self.stack) - 1 + if found < 0: + self.unknown_endtag(tag) + return + else: + if tag not in self.stack: + self.syntax_error('unopened end tag') + try: + method = getattr(self, 'end_' + tag) + except AttributeError: + self.unknown_endtag(tag) + return + found = len(self.stack) + for i in range(found): + if self.stack[i] == tag: + found = i + while len(self.stack) > found: + if found < len(self.stack) - 1: + self.syntax_error('missing close tag for %s' % self.stack[-1]) + tag = self.stack[-1] + try: + method = getattr(self, 'end_' + tag) + except AttributeError: + method = None + if method: + self.handle_endtag(tag, method) + else: + self.unknown_endtag(tag) + del self.stack[-1] # Overridable -- handle xml processing instruction def handle_xml(self, encoding, standalone): - pass + pass # Overridable -- handle DOCTYPE def handle_doctype(self, tag, data): - pass + pass # Overridable -- handle start tag def handle_starttag(self, tag, method, attrs): - method(attrs) + method(attrs) # Overridable -- handle end tag def handle_endtag(self, tag, method): - method() + method() # Example -- handle character reference, no need to override def handle_charref(self, name): - try: - if name[0] == 'x': - n = string.atoi(name[1:], 16) - else: - n = string.atoi(name) - except string.atoi_error: - self.unknown_charref(name) - return - if not 0 <= n <= 255: - self.unknown_charref(name) - return - self.handle_data(chr(n)) + try: + if name[0] == 'x': + n = string.atoi(name[1:], 16) + else: + n = string.atoi(name) + except string.atoi_error: + self.unknown_charref(name) + return + if not 0 <= n <= 255: + self.unknown_charref(name) + return + self.handle_data(chr(n)) # Definition of entities -- derived classes may override entitydefs = {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': "'"} # Example -- handle entity reference, no need to override def handle_entityref(self, name): - table = self.entitydefs - if table.has_key(name): - self.handle_data(table[name]) - else: - self.unknown_entityref(name) - return + table = self.entitydefs + if table.has_key(name): + self.handle_data(table[name]) + else: + self.unknown_entityref(name) + return # Example -- handle data, should be overridden def handle_data(self, data): - pass + pass # Example -- handle cdata, could be overridden def handle_cdata(self, data): - pass + pass # Example -- handle comment, could be overridden def handle_comment(self, data): - pass + pass # Example -- handle processing instructions, could be overridden def handle_proc(self, name, data): - pass + pass # Example -- handle special instructions, could be overridden def handle_special(self, data): - pass + pass # Example -- handle relatively harmless syntax errors, could be overridden def syntax_error(self, message): - raise RuntimeError, 'Syntax error at line %d: %s' % (self.lineno, message) + raise RuntimeError, 'Syntax error at line %d: %s' % (self.lineno, message) # To be overridden -- handlers for unknown objects def unknown_starttag(self, tag, attrs): pass @@ -559,109 +559,109 @@ class XMLParser: class TestXMLParser(XMLParser): def __init__(self, verbose=0): - self.testdata = "" - XMLParser.__init__(self, verbose) + self.testdata = "" + XMLParser.__init__(self, verbose) def handle_xml(self, encoding, standalone): - self.flush() - print 'xml: encoding =',encoding,'standalone =',standalone + self.flush() + print 'xml: encoding =',encoding,'standalone =',standalone def handle_doctype(self, tag, data): - self.flush() - print 'DOCTYPE:',tag, `data` + self.flush() + print 'DOCTYPE:',tag, `data` def handle_data(self, data): - self.testdata = self.testdata + data - if len(`self.testdata`) >= 70: - self.flush() + self.testdata = self.testdata + data + if len(`self.testdata`) >= 70: + self.flush() def flush(self): - data = self.testdata - if data: - self.testdata = "" - print 'data:', `data` + data = self.testdata + if data: + self.testdata = "" + print 'data:', `data` def handle_cdata(self, data): - self.flush() - print 'cdata:', `data` + self.flush() + print 'cdata:', `data` def handle_proc(self, name, data): - self.flush() - print 'processing:',name,`data` + self.flush() + print 'processing:',name,`data` def handle_special(self, data): - self.flush() - print 'special:',`data` + self.flush() + print 'special:',`data` def handle_comment(self, data): - self.flush() - r = `data` - if len(r) > 68: - r = r[:32] + '...' + r[-32:] - print 'comment:', r + self.flush() + r = `data` + if len(r) > 68: + r = r[:32] + '...' + r[-32:] + print 'comment:', r def syntax_error(self, message): - print 'error at line %d:' % self.lineno, message + print 'error at line %d:' % self.lineno, message def unknown_starttag(self, tag, attrs): - self.flush() - if not attrs: - print 'start tag: <' + tag + '>' - else: - print 'start tag: <' + tag, - for name, value in attrs.items(): - print name + '=' + '"' + value + '"', - print '>' + self.flush() + if not attrs: + print 'start tag: <' + tag + '>' + else: + print 'start tag: <' + tag, + for name, value in attrs.items(): + print name + '=' + '"' + value + '"', + print '>' def unknown_endtag(self, tag): - self.flush() - print 'end tag: </' + tag + '>' + self.flush() + print 'end tag: </' + tag + '>' def unknown_entityref(self, ref): - self.flush() - print '*** unknown entity ref: &' + ref + ';' + self.flush() + print '*** unknown entity ref: &' + ref + ';' def unknown_charref(self, ref): - self.flush() - print '*** unknown char ref: &#' + ref + ';' + self.flush() + print '*** unknown char ref: &#' + ref + ';' def close(self): - XMLParser.close(self) - self.flush() + XMLParser.close(self) + self.flush() def test(args = None): import sys if not args: - args = sys.argv[1:] + args = sys.argv[1:] if args and args[0] == '-s': - args = args[1:] - klass = XMLParser + args = args[1:] + klass = XMLParser else: - klass = TestXMLParser + klass = TestXMLParser if args: - file = args[0] + file = args[0] else: - file = 'test.xml' + file = 'test.xml' if file == '-': - f = sys.stdin + f = sys.stdin else: - try: - f = open(file, 'r') - except IOError, msg: - print file, ":", msg - sys.exit(1) + try: + f = open(file, 'r') + except IOError, msg: + print file, ":", msg + sys.exit(1) data = f.read() if f is not sys.stdin: - f.close() + f.close() x = klass() for c in data: - x.feed(c) + x.feed(c) x.close() |