functions.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. from __future__ import absolute_import
  2. # Copyright (c) 2010-2019 openpyxl
  3. """
  4. XML compatability functions
  5. """
  6. # Python stdlib imports
  7. import re
  8. from functools import partial
  9. # compatibility
  10. # package imports
  11. from openpyxl import DEFUSEDXML, LXML
  12. if LXML is True:
  13. from lxml.etree import (
  14. Element,
  15. ElementTree,
  16. SubElement,
  17. register_namespace,
  18. QName,
  19. xmlfile,
  20. XMLParser,
  21. )
  22. from lxml.etree import XMLSyntaxError
  23. if DEFUSEDXML is True:
  24. from defusedxml.common import DefusedXmlException
  25. from defusedxml.cElementTree import iterparse
  26. from defusedxml.lxml import fromstring as _fromstring, tostring
  27. def fromstring(*args, **kwargs):
  28. try:
  29. return _fromstring(*args, **kwargs)
  30. except XMLSyntaxError as e:
  31. raise DefusedXmlException(str(e))
  32. else:
  33. from lxml.etree import fromstring, tostring
  34. from xml.etree.cElementTree import iterparse
  35. # do not resolve entities
  36. safe_parser = XMLParser(resolve_entities=False)
  37. fromstring = partial(fromstring, parser=safe_parser)
  38. else:
  39. try:
  40. from xml.etree.cElementTree import (
  41. ElementTree,
  42. Element,
  43. SubElement,
  44. QName,
  45. register_namespace
  46. )
  47. if DEFUSEDXML is True:
  48. from defusedxml.cElementTree import (
  49. fromstring,
  50. tostring,
  51. iterparse,
  52. )
  53. else:
  54. from xml.etree.cElementTree import (
  55. fromstring,
  56. tostring,
  57. iterparse
  58. )
  59. except ImportError:
  60. from xml.etree.ElementTree import (
  61. ElementTree,
  62. Element,
  63. SubElement,
  64. QName,
  65. register_namespace
  66. )
  67. if DEFUSEDXML is True:
  68. from defusedxml.ElementTree import (
  69. fromstring,
  70. tostring,
  71. iterparse,
  72. )
  73. else:
  74. from xml.etree.ElementTree import (
  75. fromstring,
  76. tostring,
  77. iterparse,
  78. )
  79. from et_xmlfile import xmlfile
  80. from openpyxl.xml.constants import (
  81. CHART_NS,
  82. DRAWING_NS,
  83. SHEET_DRAWING_NS,
  84. CHART_DRAWING_NS,
  85. SHEET_MAIN_NS,
  86. REL_NS,
  87. VTYPES_NS,
  88. COREPROPS_NS,
  89. DCTERMS_NS,
  90. DCTERMS_PREFIX,
  91. XML_NS
  92. )
  93. register_namespace(DCTERMS_PREFIX, DCTERMS_NS)
  94. register_namespace('dcmitype', 'http://purl.org/dc/dcmitype/')
  95. register_namespace('cp', COREPROPS_NS)
  96. register_namespace('c', CHART_NS)
  97. register_namespace('a', DRAWING_NS)
  98. register_namespace('s', SHEET_MAIN_NS)
  99. register_namespace('r', REL_NS)
  100. register_namespace('vt', VTYPES_NS)
  101. register_namespace('xdr', SHEET_DRAWING_NS)
  102. register_namespace('cdr', CHART_DRAWING_NS)
  103. register_namespace('xml', XML_NS)
  104. tostring = partial(tostring, encoding="utf-8")
  105. NS_REGEX = re.compile("({(?P<namespace>.*)})?(?P<localname>.*)")
  106. def localname(node):
  107. if callable(node.tag):
  108. return "comment"
  109. m = NS_REGEX.match(node.tag)
  110. return m.group('localname')
  111. def whitespace(node):
  112. if node.text != node.text.strip():
  113. node.set("{%s}space" % XML_NS, "preserve")