home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / Inkscape / Inkscape-0.48.2-1-win32.exe / python / Lib / site-packages / lxml / ElementInclude.py < prev    next >
Encoding:
Python Source  |  2010-05-29  |  7.5 KB  |  224 lines

  1. #
  2. # ElementTree
  3. # $Id: ElementInclude.py 1862 2004-06-18 07:31:02Z Fredrik $
  4. #
  5. # limited xinclude support for element trees
  6. #
  7. # history:
  8. # 2003-08-15 fl   created
  9. # 2003-11-14 fl   fixed default loader
  10. #
  11. # Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.
  12. #
  13. # fredrik@pythonware.com
  14. # http://www.pythonware.com
  15. #
  16. # --------------------------------------------------------------------
  17. # The ElementTree toolkit is
  18. #
  19. # Copyright (c) 1999-2004 by Fredrik Lundh
  20. #
  21. # By obtaining, using, and/or copying this software and/or its
  22. # associated documentation, you agree that you have read, understood,
  23. # and will comply with the following terms and conditions:
  24. #
  25. # Permission to use, copy, modify, and distribute this software and
  26. # its associated documentation for any purpose and without fee is
  27. # hereby granted, provided that the above copyright notice appears in
  28. # all copies, and that both that copyright notice and this permission
  29. # notice appear in supporting documentation, and that the name of
  30. # Secret Labs AB or the author not be used in advertising or publicity
  31. # pertaining to distribution of the software without specific, written
  32. # prior permission.
  33. #
  34. # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  35. # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
  36. # ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
  37. # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  38. # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  39. # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  40. # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  41. # OF THIS SOFTWARE.
  42. # --------------------------------------------------------------------
  43.  
  44. """
  45. Limited XInclude support for the ElementTree package.
  46.  
  47. While lxml.etree has full support for XInclude (see
  48. `etree.ElementTree.xinclude()`), this module provides a simpler, pure
  49. Python, ElementTree compatible implementation that supports a simple
  50. form of custom URL resolvers.
  51. """
  52.  
  53. from lxml import etree
  54. import copy
  55. try:
  56.     from urlparse import urljoin
  57.     from urllib2 import urlopen
  58. except ImportError:
  59.     # Python 3
  60.     from urllib.parse import urljoin
  61.     from urllib.request import urlopen
  62.  
  63. try:
  64.     set
  65. except NameError:
  66.     # Python 2.3
  67.     from sets import Set as set
  68.  
  69. XINCLUDE = "{http://www.w3.org/2001/XInclude}"
  70.  
  71. XINCLUDE_INCLUDE = XINCLUDE + "include"
  72. XINCLUDE_FALLBACK = XINCLUDE + "fallback"
  73.  
  74. ##
  75. # Fatal include error.
  76.  
  77. class FatalIncludeError(etree.LxmlSyntaxError):
  78.     pass
  79.  
  80. ##
  81. # ET compatible default loader.
  82. # This loader reads an included resource from disk.
  83. #
  84. # @param href Resource reference.
  85. # @param parse Parse mode.  Either "xml" or "text".
  86. # @param encoding Optional text encoding.
  87. # @return The expanded resource.  If the parse mode is "xml", this
  88. #    is an ElementTree instance.  If the parse mode is "text", this
  89. #    is a Unicode string.  If the loader fails, it can return None
  90. #    or raise an IOError exception.
  91. # @throws IOError If the loader fails to load the resource.
  92.  
  93. def default_loader(href, parse, encoding=None):
  94.     file = open(href, 'rb')
  95.     if parse == "xml":
  96.         data = etree.parse(file).getroot()
  97.     else:
  98.         data = file.read()
  99.         if not encoding:
  100.             encoding = 'utf-8'
  101.         data = data.decode(encoding)
  102.     file.close()
  103.     return data
  104.  
  105. ##
  106. # Default loader used by lxml.etree - handles custom resolvers properly
  107.  
  108. def _lxml_default_loader(href, parse, encoding=None, parser=None):
  109.     if parse == "xml":
  110.         data = etree.parse(href, parser).getroot()
  111.     else:
  112.         if "://" in href:
  113.             f = urlopen(href)
  114.         else:
  115.             f = open(href, 'rb')
  116.         data = f.read()
  117.         f.close()
  118.         if not encoding:
  119.             encoding = 'utf-8'
  120.         data = data.decode(encoding)
  121.     return data
  122.  
  123. ##
  124. # Wrapper for ET compatibility - drops the parser
  125.  
  126. def _wrap_et_loader(loader):
  127.     def load(href, parse, encoding=None, parser=None):
  128.         return loader(href, parse, encoding)
  129.     return load
  130.  
  131.  
  132. ##
  133. # Expand XInclude directives.
  134. #
  135. # @param elem Root element.
  136. # @param loader Optional resource loader.  If omitted, it defaults
  137. #     to {@link default_loader}.  If given, it should be a callable
  138. #     that implements the same interface as <b>default_loader</b>.
  139. # @throws FatalIncludeError If the function fails to include a given
  140. #     resource, or if the tree contains malformed XInclude elements.
  141. # @throws IOError If the function fails to load a given resource.
  142. # @returns the node or its replacement if it was an XInclude node
  143.  
  144. def include(elem, loader=None, base_url=None):
  145.     if base_url is None:
  146.         if hasattr(elem, 'getroot'):
  147.             tree = elem
  148.             elem = elem.getroot()
  149.         else:
  150.             tree = elem.getroottree()
  151.         if hasattr(tree, 'docinfo'):
  152.             base_url = tree.docinfo.URL
  153.     elif hasattr(elem, 'getroot'):
  154.         elem = elem.getroot()
  155.     _include(elem, loader, base_url=base_url)
  156.  
  157. def _include(elem, loader=None, _parent_hrefs=None, base_url=None):
  158.     if loader is not None:
  159.         load_include = _wrap_et_loader(loader)
  160.     else:
  161.         load_include = _lxml_default_loader
  162.  
  163.     if _parent_hrefs is None:
  164.         _parent_hrefs = set()
  165.  
  166.     parser = elem.getroottree().parser
  167.  
  168.     include_elements = list(
  169.         elem.iter('{http://www.w3.org/2001/XInclude}*'))
  170.  
  171.     for e in include_elements:
  172.         if e.tag == XINCLUDE_INCLUDE:
  173.             # process xinclude directive
  174.             href = urljoin(base_url, e.get("href"))
  175.             parse = e.get("parse", "xml")
  176.             parent = e.getparent()
  177.             if parse == "xml":
  178.                 if href in _parent_hrefs:
  179.                     raise FatalIncludeError(
  180.                         "recursive include of %r detected" % href
  181.                         )
  182.                 _parent_hrefs.add(href)
  183.                 node = load_include(href, parse, parser=parser)
  184.                 if node is None:
  185.                     raise FatalIncludeError(
  186.                         "cannot load %r as %r" % (href, parse)
  187.                         )
  188.                 node = _include(node, loader, _parent_hrefs)
  189.                 if e.tail:
  190.                     node.tail = (node.tail or "") + e.tail
  191.                 if parent is None:
  192.                     return node # replaced the root node!
  193.                 parent.replace(e, node)
  194.             elif parse == "text":
  195.                 text = load_include(href, parse, encoding=e.get("encoding"))
  196.                 if text is None:
  197.                     raise FatalIncludeError(
  198.                         "cannot load %r as %r" % (href, parse)
  199.                         )
  200.                 predecessor = e.getprevious()
  201.                 if predecessor is not None:
  202.                     predecessor.tail = (predecessor.tail or "") + text
  203.                 elif parent is None:
  204.                     return text # replaced the root node!
  205.                 else:
  206.                     parent.text = (parent.text or "") + text + (e.tail or "")
  207.                 parent.remove(e)
  208.             else:
  209.                 raise FatalIncludeError(
  210.                     "unknown parse type in xi:include tag (%r)" % parse
  211.                 )
  212.         elif e.tag == XINCLUDE_FALLBACK:
  213.             parent = e.getparent()
  214.             if parent is not None and parent.tag != XINCLUDE_INCLUDE:
  215.                 raise FatalIncludeError(
  216.                     "xi:fallback tag must be child of xi:include (%r)" % e.tag
  217.                     )
  218.         else:
  219.             raise FatalIncludeError(
  220.                 "Invalid element found in XInclude namespace (%r)" % e.tag
  221.                 )
  222.     return elem
  223.