home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Calibre / calibre-0.8.18.msi / file_262 / xmllib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-09-09  |  25.0 KB  |  940 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.7)
  3.  
  4. import re
  5. import string
  6. import warnings
  7. warnings.warn('The xmllib module is obsolete.  Use xml.sax instead.', DeprecationWarning, 2)
  8. del warnings
  9. version = '0.3'
  10.  
  11. class Error(RuntimeError):
  12.     pass
  13.  
  14. _S = '[ \t\r\n]+'
  15. _opS = '[ \t\r\n]*'
  16. _Name = '[a-zA-Z_:][-a-zA-Z0-9._:]*'
  17. _QStr = '(?:\'[^\']*\'|"[^"]*")'
  18. illegal = re.compile('[^\t\r\n -~\xa0-\xff]')
  19. interesting = re.compile('[]&<]')
  20. amp = re.compile('&')
  21. ref = re.compile('&(' + _Name + '|#[0-9]+|#x[0-9a-fA-F]+)[^-a-zA-Z0-9._:]')
  22. entityref = re.compile('&(?P<name>' + _Name + ')[^-a-zA-Z0-9._:]')
  23. charref = re.compile('&#(?P<char>[0-9]+[^0-9]|x[0-9a-fA-F]+[^0-9a-fA-F])')
  24. space = re.compile(_S + '$')
  25. newline = re.compile('\n')
  26. attrfind = re.compile(_S + '(?P<name>' + _Name + ')(' + _opS + '=' + _opS + '(?P<value>' + _QStr + '|[-a-zA-Z0-9.:+*%?!\\(\\)_#=~]+))?')
  27. starttagopen = re.compile('<' + _Name)
  28. starttagend = re.compile(_opS + '(?P<slash>/?)>')
  29. starttagmatch = re.compile('<(?P<tagname>' + _Name + ')(?P<attrs>(?:' + attrfind.pattern + ')*)' + starttagend.pattern)
  30. endtagopen = re.compile('</')
  31. endbracket = re.compile(_opS + '>')
  32. endbracketfind = re.compile('(?:[^>\'"]|' + _QStr + ')*>')
  33. tagfind = re.compile(_Name)
  34. cdataopen = re.compile('<!\\[CDATA\\[')
  35. cdataclose = re.compile('\\]\\]>')
  36. _SystemLiteral = '(?P<%s>' + _QStr + ')'
  37. _PublicLiteral = '(?P<%s>"[-\'\\(\\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*"|\'[-\\(\\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*\')'
  38. _ExternalId = '(?:SYSTEM|PUBLIC' + _S + _PublicLiteral % 'pubid' + ')' + _S + _SystemLiteral % 'syslit'
  39. doctype = re.compile('<!DOCTYPE' + _S + '(?P<name>' + _Name + ')(?:' + _S + _ExternalId + ')?' + _opS)
  40. xmldecl = re.compile('<\\?xml' + _S + 'version' + _opS + '=' + _opS + '(?P<version>' + _QStr + ')' + '(?:' + _S + 'encoding' + _opS + '=' + _opS + '(?P<encoding>\'[A-Za-z][-A-Za-z0-9._]*\'|"[A-Za-z][-A-Za-z0-9._]*"))?(?:' + _S + 'standalone' + _opS + '=' + _opS + '(?P<standalone>\'(?:yes|no)\'|"(?:yes|no)"))?' + _opS + '\\?>')
  41. procopen = re.compile('<\\?(?P<proc>' + _Name + ')' + _opS)
  42. procclose = re.compile(_opS + '\\?>')
  43. commentopen = re.compile('<!--')
  44. commentclose = re.compile('-->')
  45. doubledash = re.compile('--')
  46. attrtrans = string.maketrans(' \r\n\t', '    ')
  47. _NCName = '[a-zA-Z_][-a-zA-Z0-9._]*'
  48. ncname = re.compile(_NCName + '$')
  49. qname = re.compile('(?:(?P<prefix>' + _NCName + '):)?(?P<local>' + _NCName + ')$')
  50. xmlns = re.compile('xmlns(?::(?P<ncname>' + _NCName + '))?$')
  51.  
  52. class XMLParser:
  53.     attributes = { }
  54.     elements = { }
  55.     __accept_unquoted_attributes = 0
  56.     __accept_missing_endtag_name = 0
  57.     __map_case = 0
  58.     __accept_utf8 = 0
  59.     __translate_attribute_references = 1
  60.     
  61.     def __init__(self, **kw):
  62.         self._XMLParser__fixed = 0
  63.         if 'accept_unquoted_attributes' in kw:
  64.             self._XMLParser__accept_unquoted_attributes = kw['accept_unquoted_attributes']
  65.         if 'accept_missing_endtag_name' in kw:
  66.             self._XMLParser__accept_missing_endtag_name = kw['accept_missing_endtag_name']
  67.         if 'map_case' in kw:
  68.             self._XMLParser__map_case = kw['map_case']
  69.         if 'accept_utf8' in kw:
  70.             self._XMLParser__accept_utf8 = kw['accept_utf8']
  71.         if 'translate_attribute_references' in kw:
  72.             self._XMLParser__translate_attribute_references = kw['translate_attribute_references']
  73.         self.reset()
  74.  
  75.     
  76.     def __fixelements(self):
  77.         self._XMLParser__fixed = 1
  78.         self.elements = { }
  79.         self._XMLParser__fixdict(self.__dict__)
  80.         self._XMLParser__fixclass(self.__class__)
  81.  
  82.     
  83.     def __fixclass(self, kl):
  84.         self._XMLParser__fixdict(kl.__dict__)
  85.         for k in kl.__bases__:
  86.             self._XMLParser__fixclass(k)
  87.         
  88.  
  89.     
  90.     def __fixdict(self, dict):
  91.         for key in dict.keys():
  92.             if key[:6] == 'start_':
  93.                 tag = key[6:]
  94.                 (start, end) = self.elements.get(tag, (None, None))
  95.                 if start is None:
  96.                     self.elements[tag] = (getattr(self, key), end)
  97.                 
  98.             if key[:4] == 'end_':
  99.                 tag = key[4:]
  100.                 (start, end) = self.elements.get(tag, (None, None))
  101.                 if end is None:
  102.                     self.elements[tag] = (start, getattr(self, key))
  103.                 
  104.  
  105.     
  106.     def reset(self):
  107.         self.rawdata = ''
  108.         self.stack = []
  109.         self.nomoretags = 0
  110.         self.literal = 0
  111.         self.lineno = 1
  112.         self._XMLParser__at_start = 1
  113.         self._XMLParser__seen_doctype = None
  114.         self._XMLParser__seen_starttag = 0
  115.         self._XMLParser__use_namespaces = 0
  116.         self._XMLParser__namespaces = {
  117.             'xml': None }
  118.         if self.elements is XMLParser.elements:
  119.             self._XMLParser__fixelements()
  120.  
  121.     
  122.     def setnomoretags(self):
  123.         self.nomoretags = self.literal = 1
  124.  
  125.     
  126.     def setliteral(self, *args):
  127.         self.literal = 1
  128.  
  129.     
  130.     def feed(self, data):
  131.         self.rawdata = self.rawdata + data
  132.         self.goahead(0)
  133.  
  134.     
  135.     def close(self):
  136.         self.goahead(1)
  137.         if self._XMLParser__fixed:
  138.             self._XMLParser__fixed = 0
  139.             del self.elements
  140.  
  141.     
  142.     def translate_references(self, data, all = 1):
  143.         if not self._XMLParser__translate_attribute_references:
  144.             return data
  145.         i = None
  146.         while None:
  147.             res = amp.search(data, i)
  148.             if res is None:
  149.                 return data
  150.             s = None.start(0)
  151.             res = ref.match(data, s)
  152.             if res is None:
  153.                 self.syntax_error("bogus `&'")
  154.                 i = s + 1
  155.                 continue
  156.             i = res.end(0)
  157.             str = res.group(1)
  158.             rescan = 0
  159.             if str[0] == '#':
  160.                 if str[1] == 'x':
  161.                     str = chr(int(str[2:], 16))
  162.                 else:
  163.                     str = chr(int(str[1:]))
  164.                 if data[i - 1] != ';':
  165.                     self.syntax_error("`;' missing after char reference")
  166.                     i = i - 1
  167.                 
  168.             elif all:
  169.                 if str in self.entitydefs:
  170.                     str = self.entitydefs[str]
  171.                     rescan = 1
  172.                 elif data[i - 1] != ';':
  173.                     self.syntax_error("bogus `&'")
  174.                     i = s + 1
  175.                     continue
  176.                 else:
  177.                     self.syntax_error("reference to unknown entity `&%s;'" % str)
  178.                     str = '&' + str + ';'
  179.             elif data[i - 1] != ';':
  180.                 self.syntax_error("bogus `&'")
  181.                 i = s + 1
  182.                 continue
  183.             data = data[:s] + str + data[i:]
  184.             if rescan:
  185.                 i = s
  186.                 continue
  187.             i = s + len(str)
  188.             continue
  189.             return None
  190.  
  191.     
  192.     def getnamespace(self):
  193.         nsdict = { }
  194.         for t, d, nst in self.stack:
  195.             nsdict.update(d)
  196.         
  197.         return nsdict
  198.  
  199.     
  200.     def goahead(self, end):
  201.         rawdata = self.rawdata
  202.         i = 0
  203.         n = len(rawdata)
  204.         while i < n:
  205.             if i > 0:
  206.                 self._XMLParser__at_start = 0
  207.             if self.nomoretags:
  208.                 data = rawdata[i:n]
  209.                 self.handle_data(data)
  210.                 self.lineno = self.lineno + data.count('\n')
  211.                 i = n
  212.                 break
  213.             res = interesting.search(rawdata, i)
  214.             if res:
  215.                 j = res.start(0)
  216.             else:
  217.                 j = n
  218.             if i < j:
  219.                 data = rawdata[i:j]
  220.                 if self._XMLParser__at_start and space.match(data) is None:
  221.                     self.syntax_error('illegal data at start of file')
  222.                 self._XMLParser__at_start = 0
  223.                 if not (self.stack) and space.match(data) is None:
  224.                     self.syntax_error('data not in content')
  225.                 if not (self._XMLParser__accept_utf8) and illegal.search(data):
  226.                     self.syntax_error('illegal character in content')
  227.                 self.handle_data(data)
  228.                 self.lineno = self.lineno + data.count('\n')
  229.             i = j
  230.             if i == n:
  231.                 break
  232.             if rawdata[i] == '<':
  233.                 if starttagopen.match(rawdata, i):
  234.                     if self.literal:
  235.                         data = rawdata[i]
  236.                         self.handle_data(data)
  237.                         self.lineno = self.lineno + data.count('\n')
  238.                         i = i + 1
  239.                         continue
  240.                     k = self.parse_starttag(i)
  241.                     if k < 0:
  242.                         break
  243.                     self._XMLParser__seen_starttag = 1
  244.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  245.                     i = k
  246.                     continue
  247.                 if endtagopen.match(rawdata, i):
  248.                     k = self.parse_endtag(i)
  249.                     if k < 0:
  250.                         break
  251.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  252.                     i = k
  253.                     continue
  254.                 if commentopen.match(rawdata, i):
  255.                     if self.literal:
  256.                         data = rawdata[i]
  257.                         self.handle_data(data)
  258.                         self.lineno = self.lineno + data.count('\n')
  259.                         i = i + 1
  260.                         continue
  261.                     k = self.parse_comment(i)
  262.                     if k < 0:
  263.                         break
  264.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  265.                     i = k
  266.                     continue
  267.                 if cdataopen.match(rawdata, i):
  268.                     k = self.parse_cdata(i)
  269.                     if k < 0:
  270.                         break
  271.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  272.                     i = k
  273.                     continue
  274.                 res = xmldecl.match(rawdata, i)
  275.                 if res:
  276.                     if not self._XMLParser__at_start:
  277.                         self.syntax_error('<?xml?> declaration not at start of document')
  278.                     (version, encoding, standalone) = res.group('version', 'encoding', 'standalone')
  279.                     if version[1:-1] != '1.0':
  280.                         raise Error('only XML version 1.0 supported')
  281.                     if encoding:
  282.                         encoding = encoding[1:-1]
  283.                     if standalone:
  284.                         standalone = standalone[1:-1]
  285.                     self.handle_xml(encoding, standalone)
  286.                     i = res.end(0)
  287.                     continue
  288.                 res = procopen.match(rawdata, i)
  289.                 if res:
  290.                     k = self.parse_proc(i)
  291.                     if k < 0:
  292.                         break
  293.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  294.                     i = k
  295.                     continue
  296.                 res = doctype.match(rawdata, i)
  297.                 if res:
  298.                     if self.literal:
  299.                         data = rawdata[i]
  300.                         self.handle_data(data)
  301.                         self.lineno = self.lineno + data.count('\n')
  302.                         i = i + 1
  303.                         continue
  304.                     if self._XMLParser__seen_doctype:
  305.                         self.syntax_error('multiple DOCTYPE elements')
  306.                     if self._XMLParser__seen_starttag:
  307.                         self.syntax_error('DOCTYPE not at beginning of document')
  308.                     k = self.parse_doctype(res)
  309.                     if k < 0:
  310.                         break
  311.                     self._XMLParser__seen_doctype = res.group('name')
  312.                     if self._XMLParser__map_case:
  313.                         self._XMLParser__seen_doctype = self._XMLParser__seen_doctype.lower()
  314.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  315.                     i = k
  316.                     continue
  317.                 
  318.             elif rawdata[i] == '&':
  319.                 if self.literal:
  320.                     data = rawdata[i]
  321.                     self.handle_data(data)
  322.                     i = i + 1
  323.                     continue
  324.                 res = charref.match(rawdata, i)
  325.                 if res is not None:
  326.                     i = res.end(0)
  327.                     if rawdata[i - 1] != ';':
  328.                         self.syntax_error("`;' missing in charref")
  329.                         i = i - 1
  330.                     if not self.stack:
  331.                         self.syntax_error('data not in content')
  332.                     self.handle_charref(res.group('char')[:-1])
  333.                     self.lineno = self.lineno + res.group(0).count('\n')
  334.                     continue
  335.                 res = entityref.match(rawdata, i)
  336.                 if res is not None:
  337.                     i = res.end(0)
  338.                     if rawdata[i - 1] != ';':
  339.                         self.syntax_error("`;' missing in entityref")
  340.                         i = i - 1
  341.                     name = res.group('name')
  342.                     if self._XMLParser__map_case:
  343.                         name = name.lower()
  344.                     if name in self.entitydefs:
  345.                         self.rawdata = rawdata = rawdata[:res.start(0)] + self.entitydefs[name] + rawdata[i:]
  346.                         n = len(rawdata)
  347.                         i = res.start(0)
  348.                     else:
  349.                         self.unknown_entityref(name)
  350.                     self.lineno = self.lineno + res.group(0).count('\n')
  351.                     continue
  352.                 
  353.             elif rawdata[i] == ']':
  354.                 if self.literal:
  355.                     data = rawdata[i]
  356.                     self.handle_data(data)
  357.                     i = i + 1
  358.                     continue
  359.                 if n - i < 3:
  360.                     break
  361.                 if cdataclose.match(rawdata, i):
  362.                     self.syntax_error("bogus `]]>'")
  363.                 self.handle_data(rawdata[i])
  364.                 i = i + 1
  365.                 continue
  366.             else:
  367.                 raise Error('neither < nor & ??')
  368.         if i > 0:
  369.             self._XMLParser__at_start = 0
  370.         if end and i < n:
  371.             data = rawdata[i]
  372.             self.syntax_error("bogus `%s'" % data)
  373.             if not (self._XMLParser__accept_utf8) and illegal.search(data):
  374.                 self.syntax_error('illegal character in content')
  375.             self.handle_data(data)
  376.             self.lineno = self.lineno + data.count('\n')
  377.             self.rawdata = rawdata[i + 1:]
  378.             return self.goahead(end)
  379.         self.rawdata = None[i:]
  380.         if end:
  381.             if not self._XMLParser__seen_starttag:
  382.                 self.syntax_error('no elements in file')
  383.             if self.stack:
  384.                 self.syntax_error('missing end tags')
  385.                 while self.stack:
  386.                     self.finish_endtag(self.stack[-1][0])
  387.             
  388.  
  389.     
  390.     def parse_comment(self, i):
  391.         rawdata = self.rawdata
  392.         if rawdata[i:i + 4] != '<!--':
  393.             raise Error('unexpected call to handle_comment')
  394.         res = commentclose.search(rawdata, i + 4)
  395.         if res is None:
  396.             return -1
  397.         if None.search(rawdata, i + 4, res.start(0)):
  398.             self.syntax_error("`--' inside comment")
  399.         if rawdata[res.start(0) - 1] == '-':
  400.             self.syntax_error('comment cannot end in three dashes')
  401.         if not (self._XMLParser__accept_utf8) and illegal.search(rawdata, i + 4, res.start(0)):
  402.             self.syntax_error('illegal character in comment')
  403.         self.handle_comment(rawdata[i + 4:res.start(0)])
  404.         return res.end(0)
  405.  
  406.     
  407.     def parse_doctype(self, res):
  408.         rawdata = self.rawdata
  409.         n = len(rawdata)
  410.         name = res.group('name')
  411.         if self._XMLParser__map_case:
  412.             name = name.lower()
  413.         (pubid, syslit) = res.group('pubid', 'syslit')
  414.         if pubid is not None:
  415.             pubid = pubid[1:-1]
  416.             pubid = ' '.join(pubid.split())
  417.         if syslit is not None:
  418.             syslit = syslit[1:-1]
  419.         j = k = res.end(0)
  420.         if k >= n:
  421.             return -1
  422.         if None[k] == '[':
  423.             level = 0
  424.             k = k + 1
  425.             dq = sq = 0
  426.             while k < n:
  427.                 c = rawdata[k]
  428.                 if not sq and c == '"':
  429.                     dq = not dq
  430.                 elif not dq and c == "'":
  431.                     sq = not sq
  432.                 elif not sq:
  433.                     if dq:
  434.                         pass
  435.                     elif level <= 0 and c == ']':
  436.                         res = endbracket.match(rawdata, k + 1)
  437.                         if res is None:
  438.                             return -1
  439.                         None.handle_doctype(name, pubid, syslit, rawdata[j + 1:k])
  440.                         return res.end(0)
  441.                     if c == '<':
  442.                         level = level + 1
  443.                     elif c == '>':
  444.                         level = level - 1
  445.                         if level < 0:
  446.                             self.syntax_error("bogus `>' in DOCTYPE")
  447.                         
  448.                 k = k + 1
  449.         res = endbracketfind.match(rawdata, k)
  450.         if res is None:
  451.             return -1
  452.         if None.match(rawdata, k) is None:
  453.             self.syntax_error('garbage in DOCTYPE')
  454.         self.handle_doctype(name, pubid, syslit, None)
  455.         return res.end(0)
  456.  
  457.     
  458.     def parse_cdata(self, i):
  459.         rawdata = self.rawdata
  460.         if rawdata[i:i + 9] != '<![CDATA[':
  461.             raise Error('unexpected call to parse_cdata')
  462.         res = cdataclose.search(rawdata, i + 9)
  463.         if res is None:
  464.             return -1
  465.         if not (None._XMLParser__accept_utf8) and illegal.search(rawdata, i + 9, res.start(0)):
  466.             self.syntax_error('illegal character in CDATA')
  467.         if not self.stack:
  468.             self.syntax_error('CDATA not in content')
  469.         self.handle_cdata(rawdata[i + 9:res.start(0)])
  470.         return res.end(0)
  471.  
  472.     __xml_namespace_attributes = {
  473.         'ns': None,
  474.         'src': None,
  475.         'prefix': None }
  476.     
  477.     def parse_proc(self, i):
  478.         rawdata = self.rawdata
  479.         end = procclose.search(rawdata, i)
  480.         if end is None:
  481.             return -1
  482.         j = None.start(0)
  483.         if not (self._XMLParser__accept_utf8) and illegal.search(rawdata, i + 2, j):
  484.             self.syntax_error('illegal character in processing instruction')
  485.         res = tagfind.match(rawdata, i + 2)
  486.         if res is None:
  487.             raise Error('unexpected call to parse_proc')
  488.         k = res.end(0)
  489.         name = res.group(0)
  490.         if self._XMLParser__map_case:
  491.             name = name.lower()
  492.         if name == 'xml:namespace':
  493.             self.syntax_error('old-fashioned namespace declaration')
  494.             self._XMLParser__use_namespaces = -1
  495.             if self._XMLParser__seen_doctype or self._XMLParser__seen_starttag:
  496.                 self.syntax_error('xml:namespace declaration too late in document')
  497.             (attrdict, namespace, k) = self.parse_attributes(name, k, j)
  498.             if namespace:
  499.                 self.syntax_error('namespace declaration inside namespace declaration')
  500.             for attrname in attrdict.keys():
  501.                 if attrname not in self._XMLParser__xml_namespace_attributes:
  502.                     self.syntax_error("unknown attribute `%s' in xml:namespace tag" % attrname)
  503.                     continue
  504.             if 'ns' not in attrdict or 'prefix' not in attrdict:
  505.                 self.syntax_error('xml:namespace without required attributes')
  506.             prefix = attrdict.get('prefix')
  507.             if ncname.match(prefix) is None:
  508.                 self.syntax_error('xml:namespace illegal prefix value')
  509.                 return end.end(0)
  510.             if None in self._XMLParser__namespaces:
  511.                 self.syntax_error('xml:namespace prefix not unique')
  512.             self._XMLParser__namespaces[prefix] = attrdict['ns']
  513.         elif name.lower() == 'xml':
  514.             self.syntax_error('illegal processing instruction target name')
  515.         self.handle_proc(name, rawdata[k:j])
  516.         return end.end(0)
  517.  
  518.     
  519.     def parse_attributes(self, tag, i, j):
  520.         rawdata = self.rawdata
  521.         attrdict = { }
  522.         namespace = { }
  523.         while i < j:
  524.             res = attrfind.match(rawdata, i)
  525.             if res is None:
  526.                 break
  527.             (attrname, attrvalue) = res.group('name', 'value')
  528.             if self._XMLParser__map_case:
  529.                 attrname = attrname.lower()
  530.             i = res.end(0)
  531.             if attrvalue is None:
  532.                 self.syntax_error("no value specified for attribute `%s'" % attrname)
  533.                 attrvalue = attrname
  534.             elif "'" == "'":
  535.                 pass
  536.             elif not "'" == "'" == attrvalue[-1:]:
  537.                 if '"' == '"':
  538.                     pass
  539.                 elif '"' == attrvalue[-1:]:
  540.                     attrvalue = attrvalue[1:-1]
  541.                 elif not self._XMLParser__accept_unquoted_attributes:
  542.                     self.syntax_error("attribute `%s' value not quoted" % attrname)
  543.                 res = xmlns.match(attrname)
  544.                 if res is not None:
  545.                     ncname = res.group('ncname')
  546.                     if not attrvalue:
  547.                         pass
  548.                     if not ncname:
  549.                         pass
  550.                     namespace[''] = None
  551.                     if not self._XMLParser__use_namespaces:
  552.                         self._XMLParser__use_namespaces = len(self.stack) + 1
  553.                         continue
  554.                         continue
  555.             if '<' in attrvalue:
  556.                 self.syntax_error("`<' illegal in attribute value")
  557.             if attrname in attrdict:
  558.                 self.syntax_error("attribute `%s' specified twice" % attrname)
  559.             attrvalue = attrvalue.translate(attrtrans)
  560.             attrdict[attrname] = self.translate_references(attrvalue)
  561.         return (attrdict, namespace, i)
  562.  
  563.     
  564.     def parse_starttag(self, i):
  565.         rawdata = self.rawdata
  566.         end = endbracketfind.match(rawdata, i + 1)
  567.         if end is None:
  568.             return -1
  569.         tag = None.match(rawdata, i)
  570.         if tag is None or tag.end(0) != end.end(0):
  571.             self.syntax_error('garbage in starttag')
  572.             return end.end(0)
  573.         nstag = tagname = None.group('tagname')
  574.         if self._XMLParser__map_case:
  575.             nstag = tagname = nstag.lower()
  576.         if not (self._XMLParser__seen_starttag) and self._XMLParser__seen_doctype and tagname != self._XMLParser__seen_doctype:
  577.             self.syntax_error('starttag does not match DOCTYPE')
  578.         if self._XMLParser__seen_starttag and not (self.stack):
  579.             self.syntax_error('multiple elements on top level')
  580.         (k, j) = tag.span('attrs')
  581.         (attrdict, nsdict, k) = self.parse_attributes(tagname, k, j)
  582.         self.stack.append((tagname, nsdict, nstag))
  583.         if self._XMLParser__use_namespaces:
  584.             res = qname.match(tagname)
  585.         else:
  586.             res = None
  587.         if res is not None:
  588.             (prefix, nstag) = res.group('prefix', 'local')
  589.             if prefix is None:
  590.                 prefix = ''
  591.             ns = None
  592.             for t, d, nst in self.stack:
  593.                 if prefix in d:
  594.                     ns = d[prefix]
  595.                     continue
  596.             if ns is None and prefix != '':
  597.                 ns = self._XMLParser__namespaces.get(prefix)
  598.             if ns is not None:
  599.                 nstag = ns + ' ' + nstag
  600.             elif prefix != '':
  601.                 nstag = prefix + ':' + nstag
  602.             self.stack[-1] = (tagname, nsdict, nstag)
  603.         attrnamemap = { }
  604.         for key in attrdict.keys():
  605.             attrnamemap[key] = key
  606.         
  607.         if self._XMLParser__use_namespaces:
  608.             nattrdict = { }
  609.             for key, val in attrdict.items():
  610.                 okey = key
  611.                 res = qname.match(key)
  612.                 if res is not None:
  613.                     (aprefix, key) = res.group('prefix', 'local')
  614.                     if self._XMLParser__map_case:
  615.                         key = key.lower()
  616.                     if aprefix is not None:
  617.                         ans = None
  618.                         for t, d, nst in self.stack:
  619.                             if aprefix in d:
  620.                                 ans = d[aprefix]
  621.                                 continue
  622.                         if ans is None:
  623.                             ans = self._XMLParser__namespaces.get(aprefix)
  624.                         if ans is not None:
  625.                             key = ans + ' ' + key
  626.                         else:
  627.                             key = aprefix + ':' + key
  628.                     
  629.                 nattrdict[key] = val
  630.                 attrnamemap[key] = okey
  631.             
  632.             attrdict = nattrdict
  633.         attributes = self.attributes.get(nstag)
  634.         if attributes is not None:
  635.             for key in attrdict.keys():
  636.                 if key not in attributes:
  637.                     self.syntax_error("unknown attribute `%s' in tag `%s'" % (attrnamemap[key], tagname))
  638.                     continue
  639.             for key, val in attributes.items():
  640.                 if val is not None and key not in attrdict:
  641.                     attrdict[key] = val
  642.                     continue
  643.         method = self.elements.get(nstag, (None, None))[0]
  644.         self.finish_starttag(nstag, attrdict, method)
  645.         if tag.group('slash') == '/':
  646.             self.finish_endtag(tagname)
  647.         return tag.end(0)
  648.  
  649.     
  650.     def parse_endtag(self, i):
  651.         rawdata = self.rawdata
  652.         end = endbracketfind.match(rawdata, i + 1)
  653.         if end is None:
  654.             return -1
  655.         res = None.match(rawdata, i + 2)
  656.         if res is None:
  657.             if self.literal:
  658.                 self.handle_data(rawdata[i])
  659.                 return i + 1
  660.             if not None._XMLParser__accept_missing_endtag_name:
  661.                 self.syntax_error('no name specified in end tag')
  662.             tag = self.stack[-1][0]
  663.             k = i + 2
  664.         else:
  665.             tag = res.group(0)
  666.             if self._XMLParser__map_case:
  667.                 tag = tag.lower()
  668.             if self.literal:
  669.                 if not (self.stack) or tag != self.stack[-1][0]:
  670.                     self.handle_data(rawdata[i])
  671.                     return i + 1
  672.             k = res.end(0)
  673.         if endbracket.match(rawdata, k) is None:
  674.             self.syntax_error('garbage in end tag')
  675.         self.finish_endtag(tag)
  676.         return end.end(0)
  677.  
  678.     
  679.     def finish_starttag(self, tagname, attrdict, method):
  680.         if method is not None:
  681.             self.handle_starttag(tagname, method, attrdict)
  682.         else:
  683.             self.unknown_starttag(tagname, attrdict)
  684.  
  685.     
  686.     def finish_endtag(self, tag):
  687.         self.literal = 0
  688.         if not tag:
  689.             self.syntax_error('name-less end tag')
  690.             found = len(self.stack) - 1
  691.             if found < 0:
  692.                 self.unknown_endtag(tag)
  693.                 return None
  694.         found = -1
  695.         for i in range(len(self.stack)):
  696.             if tag == self.stack[i][0]:
  697.                 found = i
  698.                 continue
  699.         if found == -1:
  700.             self.syntax_error('unopened end tag')
  701.             return None
  702.         if len(self.stack) > found:
  703.             if found < len(self.stack) - 1:
  704.                 self.syntax_error('missing close tag for %s' % self.stack[-1][2])
  705.             nstag = self.stack[-1][2]
  706.             method = self.elements.get(nstag, (None, None))[1]
  707.             if method is not None:
  708.                 self.handle_endtag(nstag, method)
  709.             else:
  710.                 self.unknown_endtag(nstag)
  711.             if self._XMLParser__use_namespaces == len(self.stack):
  712.                 self._XMLParser__use_namespaces = 0
  713.             del self.stack[-1]
  714.  
  715.     
  716.     def handle_xml(self, encoding, standalone):
  717.         pass
  718.  
  719.     
  720.     def handle_doctype(self, tag, pubid, syslit, data):
  721.         pass
  722.  
  723.     
  724.     def handle_starttag(self, tag, method, attrs):
  725.         method(attrs)
  726.  
  727.     
  728.     def handle_endtag(self, tag, method):
  729.         method()
  730.  
  731.     
  732.     def handle_charref(self, name):
  733.         
  734.         try:
  735.             if name[0] == 'x':
  736.                 n = int(name[1:], 16)
  737.             else:
  738.                 n = int(name)
  739.         except ValueError:
  740.             self.unknown_charref(name)
  741.             return None
  742.  
  743.         if n <= n:
  744.             pass
  745.         elif not n <= 255:
  746.             self.unknown_charref(name)
  747.             return None
  748.         self.handle_data(chr(n))
  749.  
  750.     entitydefs = {
  751.         'lt': '<',
  752.         'gt': '>',
  753.         'amp': '&',
  754.         'quot': '"',
  755.         'apos': ''' }
  756.     
  757.     def handle_data(self, data):
  758.         pass
  759.  
  760.     
  761.     def handle_cdata(self, data):
  762.         pass
  763.  
  764.     
  765.     def handle_comment(self, data):
  766.         pass
  767.  
  768.     
  769.     def handle_proc(self, name, data):
  770.         pass
  771.  
  772.     
  773.     def syntax_error(self, message):
  774.         raise Error('Syntax error at line %d: %s' % (self.lineno, message))
  775.  
  776.     
  777.     def unknown_starttag(self, tag, attrs):
  778.         pass
  779.  
  780.     
  781.     def unknown_endtag(self, tag):
  782.         pass
  783.  
  784.     
  785.     def unknown_charref(self, ref):
  786.         pass
  787.  
  788.     
  789.     def unknown_entityref(self, name):
  790.         self.syntax_error("reference to unknown entity `&%s;'" % name)
  791.  
  792.  
  793.  
  794. class TestXMLParser(XMLParser):
  795.     
  796.     def __init__(self, **kw):
  797.         self.testdata = ''
  798.         XMLParser.__init__(self, **kw)
  799.  
  800.     
  801.     def handle_xml(self, encoding, standalone):
  802.         self.flush()
  803.         print 'xml: encoding =', encoding, 'standalone =', standalone
  804.  
  805.     
  806.     def handle_doctype(self, tag, pubid, syslit, data):
  807.         self.flush()
  808.         print 'DOCTYPE:', tag, repr(data)
  809.  
  810.     
  811.     def handle_data(self, data):
  812.         self.testdata = self.testdata + data
  813.         if len(repr(self.testdata)) >= 70:
  814.             self.flush()
  815.  
  816.     
  817.     def flush(self):
  818.         data = self.testdata
  819.         if data:
  820.             self.testdata = ''
  821.             print 'data:', repr(data)
  822.  
  823.     
  824.     def handle_cdata(self, data):
  825.         self.flush()
  826.         print 'cdata:', repr(data)
  827.  
  828.     
  829.     def handle_proc(self, name, data):
  830.         self.flush()
  831.         print 'processing:', name, repr(data)
  832.  
  833.     
  834.     def handle_comment(self, data):
  835.         self.flush()
  836.         r = repr(data)
  837.         if len(r) > 68:
  838.             r = r[:32] + '...' + r[-32:]
  839.         print 'comment:', r
  840.  
  841.     
  842.     def syntax_error(self, message):
  843.         print 'error at line %d:' % self.lineno, message
  844.  
  845.     
  846.     def unknown_starttag(self, tag, attrs):
  847.         self.flush()
  848.         if not attrs:
  849.             print 'start tag: <' + tag + '>'
  850.         else:
  851.             print 'start tag: <' + tag,
  852.             for name, value in attrs.items():
  853.                 print name + '=' + '"' + value + '"',
  854.             
  855.             print '>'
  856.  
  857.     
  858.     def unknown_endtag(self, tag):
  859.         self.flush()
  860.         print 'end tag: </' + tag + '>'
  861.  
  862.     
  863.     def unknown_entityref(self, ref):
  864.         self.flush()
  865.         print '*** unknown entity ref: &' + ref + ';'
  866.  
  867.     
  868.     def unknown_charref(self, ref):
  869.         self.flush()
  870.         print '*** unknown char ref: &#' + ref + ';'
  871.  
  872.     
  873.     def close(self):
  874.         XMLParser.close(self)
  875.         self.flush()
  876.  
  877.  
  878.  
  879. def test(args = None):
  880.     import sys
  881.     import getopt
  882.     time = time
  883.     import time
  884.     if not args:
  885.         args = sys.argv[1:]
  886.     (opts, args) = getopt.getopt(args, 'st')
  887.     klass = TestXMLParser
  888.     do_time = 0
  889.     for o, a in opts:
  890.         if o == '-s':
  891.             klass = XMLParser
  892.             continue
  893.         if o == '-t':
  894.             do_time = 1
  895.             continue
  896.     if args:
  897.         file = args[0]
  898.     else:
  899.         file = 'test.xml'
  900.     if file == '-':
  901.         f = sys.stdin
  902.     else:
  903.         
  904.         try:
  905.             f = open(file, 'r')
  906.         except IOError:
  907.             msg = None
  908.             print file, ':', msg
  909.             sys.exit(1)
  910.  
  911.     data = f.read()
  912.     if f is not sys.stdin:
  913.         f.close()
  914.     x = klass()
  915.     t0 = time()
  916.     
  917.     try:
  918.         if do_time:
  919.             x.feed(data)
  920.             x.close()
  921.         else:
  922.             for c in data:
  923.                 x.feed(c)
  924.             
  925.             x.close()
  926.     except Error:
  927.         msg = None
  928.         t1 = time()
  929.         print msg
  930.         if do_time:
  931.             print 'total time: %g' % (t1 - t0)
  932.         sys.exit(1)
  933.  
  934.     t1 = time()
  935.     if do_time:
  936.         print 'total time: %g' % (t1 - t0)
  937.  
  938. if __name__ == '__main__':
  939.     test()
  940.