2

I am new to django-rest-framework i have working sample like

<root>
    <list-item>worrier1</list-item>
    <list-item>worrier2</list-item>
<root>

What i need is

<Hero>
    <worrier1>worrier1</worrier1>
    <worrier2>worrier2</worrier2>
<Hero>
user3370779
  • 21
  • 1
  • 6
  • What is your question? What you have tried ? Show some code. – Nishant Nawarkhede Apr 28 '14 at 17:28
  • at this point i just know the output i need, i need help to point me to the right direction toward achieve that output. Which is remove the tag and replace with my custom, also remove the default and use my custom. Thanks – user3370779 Apr 28 '14 at 17:59

5 Answers5

8

In the spirit of being helpful to anyone else who searches for this... Below is how you can subclass the XMLRenderer and override the root tag (previously "root") and item tags (previously "list-item") to whatever you like.

from django.utils.six.moves import StringIO
from django.utils.xmlutils import SimplerXMLGenerator
from rest_framework_xml.renderers import XMLRenderer

class ModifiedXMLRenderer(XMLRenderer):
    item_tag_name = "item"
    root_tag_name = "channel"

    def render(self, data, accepted_media_type=None, renderer_context=None):
        """
        Renders `data` into serialized XML.
        """
        if data is None:
            return ''

        stream = StringIO()

        xml = SimplerXMLGenerator(stream, self.charset)
        xml.startDocument()
        xml.startElement(self.root_tag_name, {})

        self._to_xml(xml, data)

        xml.endElement(self.root_tag_name)
        xml.endDocument()
        return stream.getvalue()

    def _to_xml(self, xml, data):
        if isinstance(data, (list, tuple)):
            for item in data:
                xml.startElement(self.item_tag_name, {})
                self._to_xml(xml, item)
                xml.endElement(self.item_tag_name)

        elif isinstance(data, dict):
            for key, value in six.iteritems(data):
                xml.startElement(key, {})
                self._to_xml(xml, value)
                xml.endElement(key)

        elif data is None:
            # Don't output any value
            pass

        else:
            xml.characters(smart_text(data))
madmanick
  • 1,268
  • 10
  • 10
5

If you wish to do this generically you don't need to override too much of the class:

class MyXMLRenderer(XMLRenderer):
    """Override XML tag names."""

    root_tag_name = 'file'
    item_tag_name = 'instance'
Danielle Madeley
  • 2,616
  • 1
  • 19
  • 26
1

I don't think you need to go so far as to create a whole subclass, I was able to do it by overriding the instance variables after creating the instance and before running render, see below:

renderer = XMLRenderer()
renderer.item_tag_name = 'warrior'
renderer.root_tag_name = 'Hero'
content = renderer.render(serializer.data)

Hope that helps anyone else who stumbles by

Artisan
  • 1,974
  • 1
  • 18
  • 23
0

Those are hardcoded values, so the only chance you get, is to create custom renderer by overriding the XMLRenderer (which in effect would be pretty much the whole class) and use that custom renderer in your view.

mariodev
  • 13,928
  • 3
  • 49
  • 61
0

For anyone who wants to edit the actual package, you can go to your Python folder, site-packages, rest_framework_xml, and edit renderers.py

When you get there, you can edit: item_tag_name = 'list-item' and change this to item_tag_name = 'item'

Note: By doing this method, you are overriding the actual class. For my project, it does not matter, but if you intend to use the xml library for another Django project, just keep this in mind.

dataviews
  • 2,466
  • 7
  • 31
  • 64