Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMLRenderer when passed a list of items #41

Open
AronForero opened this issue Oct 3, 2019 · 2 comments
Open

XMLRenderer when passed a list of items #41

AronForero opened this issue Oct 3, 2019 · 2 comments

Comments

@AronForero
Copy link

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

@SukiCZ
Copy link

SukiCZ commented Oct 27, 2021

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)

@decibyte
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants