home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2880 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  25.4 KB  |  995 lines

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