XMLRenderer when passed a list of items

#41 · open · 2 comments

View on GitHub ↗

AronForero

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 :)

Comments

SukiCZ

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. ```py ... 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) ```

decibyte

Hey friends! Thank you for not only posting a problem, but also providing a potential solution to it. You just saved me from hours of hacking :)