django-rest-framework-xml
django-rest-framework-xml copied to clipboard
XMLRenderer when passed a list of items
When I pass a Python Dict like this to the renderer:
from rest_framework_xml.renderers import XMLRenderer
dictionary = {
'NAME': 'Aron Dev',
'ID': 555000777,
'PHONE_NUMBER': [
3124569874,
3021452361,
]
}
renderer = XMLRenderer()
new_data = renderer.render(dictionary)
The library will return the following XML struct:
<NAME>Aron Dev</NAME>
<ID>555000777</ID>
<PHONE_NUMBER>
<list-item>3124569874</list-item>
<list-item>3124569874</list-item>
<PHONE_NUMBER>
But I needed two 'PHONE_NUMBER' tags (that tag 'list-item' is not really useful), one for each value of the list, just like this:
<PHONE_NUMBER>3124569874<PHONE_NUMBER>
<PHONE_NUMBER>3124569874<PHONE_NUMBER>
I FOUND THIS WALKAROUND
Create a new custom class that inherits from the XMLRenderer class as follows (the lines between the arrows are the new ones I've added):
class CustomXmlRenderer(XMLRenderer):
item_tag_name = 'PHONE_NUMBER'
def _to_xml(self, xml, data):
...
elif isinstance(data, dict):
for key, value in six.iteritems(data):
--->if isinstance(value, list):<---
--->self._to_xml(xml, value)<---
--->continue<---
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)
I modified the first elif statement, adding a new condition that checks if the value is a List, to then create tags with the same name for each value of the List, and finally I added a continue to go on to the next item and avoid create more tags with the values of the list.
I Hope to help anyone who has got the same task that I had, and doesn't know what to do, or at least saven them some time
I don't know if it could be intagrated with the main project but I'll be watching :)
Hello and thanks for posting this. Had a similar issue where I was serializing a nested list in list of items. As the nested list has to have a different element to start with (item_tag_name
), my modification looks as following.
...
elif isinstance(data, dict):
for key, value in data.items():
if isinstance(value, list):
for v in value:
xml.startElement(key, {})
self._to_xml(xml, v)
xml.endElement(key)
else:
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)