X-Git-Url: https://git.frykholm.com/friends.git/blobdiff_plain/ddf4123ddc9df1b3786c3950f0bed371d8bba352..511b6ecb108d9a00340f1e58b849c3fcdb4536c9:/friends/rd/xrd.py diff --git a/friends/rd/xrd.py b/friends/rd/xrd.py new file mode 100755 index 0000000..afc1247 --- /dev/null +++ b/friends/rd/xrd.py @@ -0,0 +1,163 @@ + +from xml.dom.minidom import getDOMImplementation, parseString, Node + +from rd.core import RD, Element, Link, Property, Title + +XRD_NAMESPACE = "http://docs.oasis-open.org/ns/xri/xrd-1.0" + + +def _get_text(root): + text = '' + for node in root.childNodes: + if node.nodeType == Node.TEXT_NODE and node.nodeValue: + text += node.nodeValue + else: + text += _get_text(node) + return text.strip() or None + + +def loads(content): + + import isodate + + def expires_handler(node, obj): + obj.expires = isodate.parse_datetime(_get_text(node)) + + def subject_handler(node, obj): + obj.subject = _get_text(node) + + def alias_handler(node, obj): + obj.aliases.append(_get_text(node)) + + def property_handler(node, obj): + obj.properties.append(Property(node.getAttribute('type'), _get_text(node))) + + def title_handler(node, obj): + obj.titles.append(Title(_get_text(node), node.getAttribute('xml:lang'))) + + def link_handler(node, obj): + l = Link() + l.rel = node.getAttribute('rel') + l.type = node.getAttribute('type') + l.href = node.getAttribute('href') + l.template = node.getAttribute('template') + obj.links.append(l) + + handlers = { + 'Expires': expires_handler, + 'Subject': subject_handler, + 'Alias': alias_handler, + 'Property': property_handler, + 'Link': link_handler, + 'Title': title_handler, + } + + def unknown_handler(node, obj): + obj.elements.append(Element( + name=node.tagName, + value=_get_text(node), + )) + + def handle_node(node, obj): + handler = handlers.get(node.nodeName, unknown_handler) + if handler and node.nodeType == node.ELEMENT_NODE: + handler(node, obj) + + doc = parseString(content) + root = doc.documentElement + + rd = RD(root.getAttribute('xml:id')) + + for name, value in list(root.attributes.items()): + if name != 'xml:id': + rd.attributes.append((name, value)) + + for node in root.childNodes: + handle_node(node, rd) + if node.nodeName == 'Link': + link = rd.links[-1] + for child in node.childNodes: + handle_node(child, link) + + return rd + + +def dumps(xrd): + + doc = getDOMImplementation().createDocument(XRD_NAMESPACE, "XRD", None) + root = doc.documentElement + root.setAttribute('xmlns', XRD_NAMESPACE) + + if xrd.xml_id: + root.setAttribute('xml:id', xrd.xml_id) + + for attr in xrd.attributes: + root.setAttribute(attr.name, attr.value) + + if xrd.expires: + node = doc.createElement('Expires') + node.appendChild(doc.createTextNode(xrd.expires.isoformat())) + root.appendChild(node) + + if xrd.subject: + node = doc.createElement('Subject') + node.appendChild(doc.createTextNode(xrd.subject)) + root.appendChild(node) + + for alias in xrd.aliases: + node = doc.createElement('Alias') + node.appendChild(doc.createTextNode(alias)) + root.appendChild(node) + + for prop in xrd.properties: + node = doc.createElement('Property') + node.setAttribute('type', prop.type) + if prop.value: + node.appendChild(doc.createTextNode(str(prop.value))) + else: + node.setAttribute('xsi:nil', 'true') + root.appendChild(node) + + for element in xrd.elements: + node = doc.createElement(element.name) + node.appendChild(doc.createTextNode(element.value)) + root.appendChild(node) + + for link in xrd.links: + + if link.href and link.template: + raise ValueError('only one of href or template attributes may be specified') + + link_node = doc.createElement('Link') + + if link.rel: + link_node.setAttribute('rel', link.rel) + + if link.type: + link_node.setAttribute('type', link.type) + + if link.href: + link_node.setAttribute('href', link.href) + + if link.template: + link_node.setAttribute('template', link.template) + + for title in link.titles: + node = doc.createElement('Title') + node.appendChild(doc.createTextNode(str(title))) + if title.lang: + node.setAttribute('xml:lang', title.lang) + link_node.appendChild(node) + + for prop in link.properties: + node = doc.createElement('Property') + node.setAttribute('type', prop.type) + if prop.value: + node.appendChild(doc.createTextNode(str(prop.value))) + else: + node.setAttribute('xsi:nil', 'true') + link_node.appendChild(node) + + root.appendChild(link_node) + + return doc