xrd.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. from xml.dom.minidom import getDOMImplementation, parseString, Node
  2. from rd.core import RD, Element, Link, Property, Title
  3. XRD_NAMESPACE = "http://docs.oasis-open.org/ns/xri/xrd-1.0"
  4. def _get_text(root):
  5. text = ''
  6. for node in root.childNodes:
  7. if node.nodeType == Node.TEXT_NODE and node.nodeValue:
  8. text += node.nodeValue
  9. else:
  10. text += _get_text(node)
  11. return text.strip() or None
  12. def loads(content):
  13. import isodate
  14. def expires_handler(node, obj):
  15. obj.expires = isodate.parse_datetime(_get_text(node))
  16. def subject_handler(node, obj):
  17. obj.subject = _get_text(node)
  18. def alias_handler(node, obj):
  19. obj.aliases.append(_get_text(node))
  20. def property_handler(node, obj):
  21. obj.properties.append(Property(node.getAttribute('type'), _get_text(node)))
  22. def title_handler(node, obj):
  23. obj.titles.append(Title(_get_text(node), node.getAttribute('xml:lang')))
  24. def link_handler(node, obj):
  25. l = Link()
  26. l.rel = node.getAttribute('rel')
  27. l.type = node.getAttribute('type')
  28. l.href = node.getAttribute('href')
  29. l.template = node.getAttribute('template')
  30. obj.links.append(l)
  31. handlers = {
  32. 'Expires': expires_handler,
  33. 'Subject': subject_handler,
  34. 'Alias': alias_handler,
  35. 'Property': property_handler,
  36. 'Link': link_handler,
  37. 'Title': title_handler,
  38. }
  39. def unknown_handler(node, obj):
  40. obj.elements.append(Element(
  41. name=node.tagName,
  42. value=_get_text(node),
  43. ))
  44. def handle_node(node, obj):
  45. handler = handlers.get(node.nodeName, unknown_handler)
  46. if handler and node.nodeType == node.ELEMENT_NODE:
  47. handler(node, obj)
  48. doc = parseString(content)
  49. root = doc.documentElement
  50. rd = RD(root.getAttribute('xml:id'))
  51. for name, value in list(root.attributes.items()):
  52. if name != 'xml:id':
  53. rd.attributes.append((name, value))
  54. for node in root.childNodes:
  55. handle_node(node, rd)
  56. if node.nodeName == 'Link':
  57. link = rd.links[-1]
  58. for child in node.childNodes:
  59. handle_node(child, link)
  60. return rd
  61. def dumps(xrd):
  62. doc = getDOMImplementation().createDocument(XRD_NAMESPACE, "XRD", None)
  63. root = doc.documentElement
  64. root.setAttribute('xmlns', XRD_NAMESPACE)
  65. if xrd.xml_id:
  66. root.setAttribute('xml:id', xrd.xml_id)
  67. for attr in xrd.attributes:
  68. root.setAttribute(attr.name, attr.value)
  69. if xrd.expires:
  70. node = doc.createElement('Expires')
  71. node.appendChild(doc.createTextNode(xrd.expires.isoformat()))
  72. root.appendChild(node)
  73. if xrd.subject:
  74. node = doc.createElement('Subject')
  75. node.appendChild(doc.createTextNode(xrd.subject))
  76. root.appendChild(node)
  77. for alias in xrd.aliases:
  78. node = doc.createElement('Alias')
  79. node.appendChild(doc.createTextNode(alias))
  80. root.appendChild(node)
  81. for prop in xrd.properties:
  82. node = doc.createElement('Property')
  83. node.setAttribute('type', prop.type)
  84. if prop.value:
  85. node.appendChild(doc.createTextNode(str(prop.value)))
  86. else:
  87. node.setAttribute('xsi:nil', 'true')
  88. root.appendChild(node)
  89. for element in xrd.elements:
  90. node = doc.createElement(element.name)
  91. node.appendChild(doc.createTextNode(element.value))
  92. root.appendChild(node)
  93. for link in xrd.links:
  94. if link.href and link.template:
  95. raise ValueError('only one of href or template attributes may be specified')
  96. link_node = doc.createElement('Link')
  97. if link.rel:
  98. link_node.setAttribute('rel', link.rel)
  99. if link.type:
  100. link_node.setAttribute('type', link.type)
  101. if link.href:
  102. link_node.setAttribute('href', link.href)
  103. if link.template:
  104. link_node.setAttribute('template', link.template)
  105. for title in link.titles:
  106. node = doc.createElement('Title')
  107. node.appendChild(doc.createTextNode(str(title)))
  108. if title.lang:
  109. node.setAttribute('xml:lang', title.lang)
  110. link_node.appendChild(node)
  111. for prop in link.properties:
  112. node = doc.createElement('Property')
  113. node.setAttribute('type', prop.type)
  114. if prop.value:
  115. node.appendChild(doc.createTextNode(str(prop.value)))
  116. else:
  117. node.setAttribute('xsi:nil', 'true')
  118. link_node.appendChild(node)
  119. root.appendChild(link_node)
  120. return doc