fork download
  1. # coding: utf-8
  2.  
  3. import json
  4. import xml.dom.minidom as md
  5.  
  6.  
  7.  
  8. import json
  9.  
  10. def cheng(s):
  11. inp = json.loads(s)
  12. return dict2xml(inp, True)
  13.  
  14. def dict2xml(structure,tostring=False):
  15.  
  16. assert len(structure) == 1, 'Structure must have only one root element'
  17. assert isinstance(structure,Mapping), 'Structure must be a mapping object such as dict'
  18.  
  19. root_element_name, value = next(structure.iteritems())
  20. impl = minidom.getDOMImplementation()
  21. doc = impl.createDocument(None,str(root_element_name),None)
  22. dict2element(doc.documentElement,value,doc)
  23. return doc.toxml() if tostring else doc
  24.  
  25.  
  26.  
  27. def load_xml(xml):
  28. u"""
  29. Функция извлечения данных из XML-строки, содержащей JSON-данные
  30. """
  31. try:
  32. doc = md.parseString(xml)
  33. except TypeError:
  34. raise AssertionError(
  35. u'XML-документ должен быть строкой!')
  36. except:
  37. raise AssertionError(u'Невалидный XML!')
  38.  
  39. top = doc.firstChild
  40. assert top.tagName == u'JSON', (
  41. u'Тэг верхнего уровня должен иметь имя "JSON"')
  42. assert len(top.childNodes) == 1, (
  43. u'JSON не может быть пустым!')
  44.  
  45. def wrong_tag(el, parser):
  46. raise AssertionError(u'Недопустимый тэг: "%s"!' % el.tagName)
  47.  
  48. def item_in_wrong_place(el, parser):
  49. raise AssertionError(u'Неожиданное появление тэга "ITEM"!')
  50.  
  51. # парсеры отдельных элементов
  52. parse_integer = lambda el, parser: int(el.firstChild.wholeText)
  53. parse_float = lambda el, parser: float(el.firstChild.wholeText)
  54. parse_string = lambda el, parser: el.firstChild.wholeText
  55. parse_null = lambda el, parser: None
  56.  
  57. def parse_list(el, parser):
  58. result = []
  59. for subel in el.childNodes:
  60. result.append(parser(subel))
  61. return result
  62.  
  63. def parse_dict(el, parser):
  64. result = {}
  65. for subel in el.childNodes:
  66. if subel.tagName != u'ITEM':
  67. raise AssertionError(
  68. u'Элементами тэга "DICT" могут быть только тэги "ITEM"!')
  69. assert subel.hasAttribute('name'), (
  70. u'Тэг "ITEM" должен иметь атрибут "name"!')
  71. assert len(subel.childNodes) == 1, (
  72. u'Тэг "ITEM" должен ровно один дочерный элемент!')
  73. result[subel.getAttribute('name')] = parser(subel.firstChild)
  74. return result
  75.  
  76. # парсер - точка входа
  77. def parse(el):
  78. fn = {
  79. u'INTEGER': parse_integer,
  80. u'FLOAT': parse_float,
  81. u'STRING': parse_string,
  82. u'LIST': parse_list,
  83. u'DICT': parse_dict,
  84. u'NULL': parse_null,
  85. u'ITEM': item_in_wrong_place,
  86. }.get(el.tagName, wrong_tag)
  87. try:
  88. return fn(el, parse)
  89. except (TypeError, ValueError):
  90. raise AssertionError(u'Неверный формат тэга "%s"!' % el.tagName)
  91.  
  92. return parse(top.firstChild)
  93.  
  94.  
  95. src = [
  96. {'type': u'human', 'name': u'Vasiliy Pupkin', 'age': 12},
  97. {'type': u'pet', 'name': u'Spot',
  98. 'bread': u'hound', 'weight': 1.5, 'owner': None},
  99. {'type': u'pet', 'name': u'Leo', 'owners': [
  100. {'name': u'Masha'},
  101. {'name': u'Kolya', 'parents': {'mother': u'Maria', 'father': u'Ivan'}},
  102. ]},
  103. ]
  104.  
  105.  
  106. ch = lambda data: cheng(json.dumps(data))
  107. try:
  108. assert load_xml(ch(None)) == None, (
  109. u'Неверно преобразуется None!')
  110.  
  111. assert load_xml(ch(u"123")) == u"123", (
  112. u'Неверно преобразуются строки!')
  113.  
  114. assert load_xml(ch(777)) == 777, (
  115. u'Неверно преобразуются целые числа!')
  116.  
  117. assert load_xml(ch(77.7)) == 77.7, (
  118. u'Неверно преобразуются числа с плавающей точкой!')
  119.  
  120. assert load_xml(ch([1, 2, 3])) == [1, 2, 3], (
  121. u'Неверно преобразуются списки!')
  122.  
  123. assert load_xml(ch({'a': u'b'})) == {'a': u'b'}, (
  124. u'Неверно преобразуются словари!')
  125.  
  126. assert load_xml(ch(src)) == src, (
  127. u'Неверно обрабатываются комплексные данные!')
  128.  
  129. except AssertionError as msg:
  130. print '>>>', unicode(msg).encode('utf-8')
  131.  
Runtime error #stdin #stdout 0.13s 11968KB
stdin
Standard input is empty
stdout
Standard output is empty