client.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # -*- coding: utf-8 -*-
  2. from xml.etree import ElementTree
  3. from Tea.model import TeaModel
  4. from collections import defaultdict
  5. class Client(object):
  6. _LIST_TYPE = (list, tuple, set)
  7. @staticmethod
  8. def __get_xml_factory(elem, val, parent_element=None):
  9. if val is None:
  10. return
  11. if isinstance(val, dict):
  12. Client.__get_xml_by_dict(elem, val)
  13. elif isinstance(val, Client._LIST_TYPE):
  14. if parent_element is None:
  15. raise RuntimeError("Missing root tag")
  16. Client.__get_xml_by_list(elem, val, parent_element)
  17. else:
  18. elem.text = str(val)
  19. @staticmethod
  20. def __get_xml_by_dict(elem, val):
  21. for k in val:
  22. sub_elem = ElementTree.SubElement(elem, k)
  23. Client.__get_xml_factory(sub_elem, val[k], elem)
  24. @staticmethod
  25. def __get_xml_by_list(elem, val, parent_element):
  26. i = 0
  27. tag_name = elem.tag
  28. if val.__len__() > 0:
  29. Client.__get_xml_factory(elem, val[0], parent_element)
  30. for item in val:
  31. if i > 0:
  32. sub_elem = ElementTree.SubElement(parent_element, tag_name)
  33. Client.__get_xml_factory(sub_elem, item, parent_element)
  34. i = i + 1
  35. @staticmethod
  36. def _parse_xml(t):
  37. d = {t.tag: {} if t.attrib else None}
  38. children = list(t)
  39. if children:
  40. dd = defaultdict(list)
  41. for dc in map(Client._parse_xml, children):
  42. for k, v in dc.items():
  43. dd[k].append(v)
  44. d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.items()}}
  45. if t.attrib:
  46. d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())
  47. if t.text:
  48. text = t.text.strip()
  49. if children or t.attrib:
  50. if text:
  51. d[t.tag]['#text'] = text
  52. else:
  53. d[t.tag] = text
  54. return d
  55. @staticmethod
  56. def parse_xml(body, response=None):
  57. """
  58. Parse body into the response, and put the resposne into a object
  59. @param body: source content
  60. @param response: target model
  61. @return the final object
  62. """
  63. return Client._parse_xml(ElementTree.fromstring(body))
  64. @staticmethod
  65. def to_xml(body):
  66. """
  67. Parse body as a xml string
  68. @param body: source body
  69. @return the xml string
  70. """
  71. if body is None:
  72. return
  73. dic = {}
  74. if isinstance(body, TeaModel):
  75. dic = body.to_map()
  76. elif isinstance(body, dict):
  77. dic = body
  78. if dic.__len__() == 0:
  79. return ""
  80. else:
  81. result_xml = '<?xml version="1.0" encoding="utf-8"?>'
  82. for k in dic:
  83. elem = ElementTree.Element(k)
  84. Client.__get_xml_factory(elem, dic[k])
  85. result_xml += bytes.decode(ElementTree.tostring(elem), encoding="utf-8")
  86. return result_xml