Skip to content

Instantly share code, notes, and snippets.

@willcalderbank
Created October 11, 2013 16:39
Show Gist options
  • Save willcalderbank/6938004 to your computer and use it in GitHub Desktop.
Save willcalderbank/6938004 to your computer and use it in GitHub Desktop.
This is a highly modified version of the standard ``tastypie.Serialiser.to_etree`` and ``tastypie.Serialiser.to_xml``. These modifications allow use to do the following by optionally setting arguments in the serialiser constructor: - Change the item nodes name (item_title) - Exclude the node types (define_types) - Exclude the resource uri (exclu…
def to_etree(self, data, name=None, depth=0):
"""
Given some data, converts that data to an ``etree.Element`` suitable
for use in the XML output. (Using recursion)
This is a highly modified version of the standard
``tastypie.Serialiser.to_etree``. These modifications allow use to do
the following by optionally setting arguments in the serialiser
constructor:
- Change the item nodes name (item_title)
- Exclude the node types (define_types)
- Exclude the resource uri (exclude_resource_uri)
:param data: The data convert to an etree
:type data: dictionary
:param name: The name of the root node for the (sub)etree
:type name: String
:param depth: The depth of the node in the parent etree
:type depth: Integer
:returns: A etree that can be used for XML output
:rtype: etree
"""
def _append_to_element(element, data, name=None, depth=0):
"""
A helper function to add a subtree to the element
:param data: The data convert to an etree
:type data: dictionary
:param name: The name of the root node for the (sub)etree
:type name: String
:param depth: The depth of the node in the parent etree
:type depth: Integer
"""
if name != 'resource_uri' and self.exclude_resource_uri:
element.append(self.to_etree(data, name, depth))
element[:] = sorted(element, key=lambda x: x.tag)
if isinstance(data, (list, tuple)):
element = etree.Element(name or 'objects')
for item in data:
_append_to_element(element, item, depth=depth+1)
elif isinstance(data, dict):
element = etree.Element(name or 'response')
if self.define_types:
element.set('type', 'hash')
for (key, value) in data.items():
_append_to_element(element, value, name=key, depth=depth+1)
elif isinstance(data, resources.Bundle):
element = etree.Element(name or self.item_title)
for field_name, field_object in data.data.items():
_append_to_element(
element,
field_object,
name=field_name,
depth=depth+1
)
else:
element = etree.Element(name or 'value')
simple_data = self.to_simple(data, None)
data_type = serializers.get_type_string(simple_data)
if self.define_types and data_type != 'string':
element.set('type', serializers.get_type_string(simple_data))
if data_type != 'null':
if isinstance(simple_data, six.text_type):
element.text = simple_data
else:
element.text = force_text(simple_data)
return element
def to_xml(self, data, args, **kwargs):
"""
Given some Python data, produces XML output.
This is a highly version of the standard
``tastypie.Serialiser.to_xml``. These modifications allow use to do
the following by optionally setting arguments in the serialiser
constructor:
- Change the root nodes name (resource_title)
- Exclude the meta data node (exclude_resource_uri)
:param data: The data to convert to XML
:type data: Bundle, dictionary, list or dehydrated_type
:return: The XML created from the data
:rtype: XML
"""
data[self.resource_title] = data.pop('objects')
if not self.exclude_meta:
the_etree = self.to_etree(data)
else:
the_etree = self.to_etree(
data[self.resource_title],
self.resource_title
)
return etree.tostring(
the_etree,
xml_declaration=True,
encoding='utf-8'
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment