home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / xbmc-9.11.exe / scripts / AppleMovieTrailers / resources / lib / elementtree / ElementPath.py < prev    next >
Encoding:
Python Source  |  2008-08-06  |  6.0 KB  |  197 lines

  1. #
  2. # ElementTree
  3. # $Id: ElementPath.py 1858 2004-06-17 21:31:41Z Fredrik $
  4. #
  5. # limited xpath support for element trees
  6. #
  7. # history:
  8. # 2003-05-23 fl   created
  9. # 2003-05-28 fl   added support for // etc
  10. # 2003-08-27 fl   fixed parsing of periods in element names
  11. #
  12. # Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
  13. #
  14. # fredrik@pythonware.com
  15. # http://www.pythonware.com
  16. #
  17. # --------------------------------------------------------------------
  18. # The ElementTree toolkit is
  19. #
  20. # Copyright (c) 1999-2004 by Fredrik Lundh
  21. #
  22. # By obtaining, using, and/or copying this software and/or its
  23. # associated documentation, you agree that you have read, understood,
  24. # and will comply with the following terms and conditions:
  25. #
  26. # Permission to use, copy, modify, and distribute this software and
  27. # its associated documentation for any purpose and without fee is
  28. # hereby granted, provided that the above copyright notice appears in
  29. # all copies, and that both that copyright notice and this permission
  30. # notice appear in supporting documentation, and that the name of
  31. # Secret Labs AB or the author not be used in advertising or publicity
  32. # pertaining to distribution of the software without specific, written
  33. # prior permission.
  34. #
  35. # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  36. # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
  37. # ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
  38. # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  39. # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  40. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  41. # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  42. # OF THIS SOFTWARE.
  43. # --------------------------------------------------------------------
  44.  
  45. ##
  46. # Implementation module for XPath support.  There's usually no reason
  47. # to import this module directly; the <b>ElementTree</b> does this for
  48. # you, if needed.
  49. ##
  50.  
  51. import re
  52.  
  53. xpath_tokenizer = re.compile(
  54.     "(::|\.\.|\(\)|[/.*:\[\]\(\)@=])|((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|\s+"
  55.     ).findall
  56.  
  57. class xpath_descendant_or_self:
  58.     pass
  59.  
  60. ##
  61. # Wrapper for a compiled XPath.
  62.  
  63. class Path:
  64.  
  65.     ##
  66.     # Create an Path instance from an XPath expression.
  67.  
  68.     def __init__(self, path):
  69.         tokens = xpath_tokenizer(path)
  70.         # the current version supports 'path/path'-style expressions only
  71.         self.path = []
  72.         self.tag = None
  73.         if tokens and tokens[0][0] == "/":
  74.             raise SyntaxError("cannot use absolute path on element")
  75.         while tokens:
  76.             op, tag = tokens.pop(0)
  77.             if tag or op == "*":
  78.                 self.path.append(tag or op)
  79.             elif op == ".":
  80.                 pass
  81.             elif op == "/":
  82.                 self.path.append(xpath_descendant_or_self())
  83.                 continue
  84.             else:
  85.                 raise SyntaxError("unsupported path syntax (%s)" % op)
  86.             if tokens:
  87.                 op, tag = tokens.pop(0)
  88.                 if op != "/":
  89.                     raise SyntaxError(
  90.                         "expected path separator (%s)" % (op or tag)
  91.                         )
  92.         if self.path and isinstance(self.path[-1], xpath_descendant_or_self):
  93.             raise SyntaxError("path cannot end with //")
  94.         if len(self.path) == 1 and isinstance(self.path[0], type("")):
  95.             self.tag = self.path[0]
  96.  
  97.     ##
  98.     # Find first matching object.
  99.  
  100.     def find(self, element):
  101.         tag = self.tag
  102.         if tag is None:
  103.             nodeset = self.findall(element)
  104.             if not nodeset:
  105.                 return None
  106.             return nodeset[0]
  107.         for elem in element:
  108.             if elem.tag == tag:
  109.                 return elem
  110.         return None
  111.  
  112.     ##
  113.     # Find text for first matching object.
  114.  
  115.     def findtext(self, element, default=None):
  116.         tag = self.tag
  117.         if tag is None:
  118.             nodeset = self.findall(element)
  119.             if not nodeset:
  120.                 return default
  121.             return nodeset[0].text or ""
  122.         for elem in element:
  123.             if elem.tag == tag:
  124.                 return elem.text or ""
  125.         return default
  126.  
  127.     ##
  128.     # Find all matching objects.
  129.  
  130.     def findall(self, element):
  131.         nodeset = [element]
  132.         index = 0
  133.         while 1:
  134.             try:
  135.                 path = self.path[index]
  136.                 index = index + 1
  137.             except IndexError:
  138.                 return nodeset
  139.             set = []
  140.             if isinstance(path, xpath_descendant_or_self):
  141.                 try:
  142.                     tag = self.path[index]
  143.                     if not isinstance(tag, type("")):
  144.                         tag = None
  145.                     else:
  146.                         index = index + 1
  147.                 except IndexError:
  148.                     tag = None # invalid path
  149.                 for node in nodeset:
  150.                     new = list(node.getiterator(tag))
  151.                     if new and new[0] is node:
  152.                         set.extend(new[1:])
  153.                     else:
  154.                         set.extend(new)
  155.             else:
  156.                 for node in nodeset:
  157.                     for node in node:
  158.                         if path == "*" or node.tag == path:
  159.                             set.append(node)
  160.             if not set:
  161.                 return []
  162.             nodeset = set
  163.  
  164. _cache = {}
  165.  
  166. ##
  167. # (Internal) Compile path.
  168.  
  169. def _compile(path):
  170.     p = _cache.get(path)
  171.     if p is not None:
  172.         return p
  173.     p = Path(path)
  174.     if len(_cache) >= 100:
  175.         _cache.clear()
  176.     _cache[path] = p
  177.     return p
  178.  
  179. ##
  180. # Find first matching object.
  181.  
  182. def find(element, path):
  183.     return _compile(path).find(element)
  184.  
  185. ##
  186. # Find text for first matching object.
  187.  
  188. def findtext(element, path, default=None):
  189.     return _compile(path).findtext(element, default)
  190.  
  191. ##
  192. # Find all matching objects.
  193.  
  194. def findall(element, path):
  195.     return _compile(path).findall(element)
  196.  
  197.