customizing XML emitter <response><resource> tags for bound model

52 views
Skip to first unread message

drewda

unread,
Mar 23, 2010, 6:36:46 PM3/23/10
to django-piston
Hi all,

I'm working with handlers bound to models and I'd like the model names
to be displayed by the XML emitter. Rather than:

<response><resource>...</resource><resource>...</resource></response>

I'd like to produce:

<photos><photo>...</photo><photo>...</photo></photos>

for the handler I have bound to the photo model.

I understand that I'll need to create a custom emitter that changes
lines 351, 353, 367, and 371 of django-piston/piston/emitters.py. Can
anyone recommend a straightforward change that will insert the plural
and singular names of the respective model?

Thank you,
Drew

Joe J

unread,
Apr 1, 2010, 12:29:09 PM4/1/10
to django-piston
I've been wondering about how to do this also.

HolaMan

unread,
Apr 14, 2010, 1:15:23 PM4/14/10
to django-piston
I have the same problem also. Is there any easier way to achieve?

Joe J

unread,
May 6, 2010, 7:34:07 PM5/6/10
to django-piston
Drew's suggestion seems to work well. Making a custom emitter for
each response turns out to do the trick. (Thanks you Drew!)

The only thing that seems to be an issue is responses with XML
elements that go several levels deep. For example, when I make the
simple changes to the emitter code (example 4) to display xml output
in example 1 as a list of messages, the output works great.

However, the problem comes when my messages have other related
objects, such as, for example, multiple tags associated with a
message. Instead of letting me customize the second level of related
elements, it takes the name of the top-level 'message' element. I'd
rather have the output look something like example 3. Does anyone
know how to customize this XML output in this way such that I have
control over all of the XML tags?

Thanks for considering my question.
Joe

example 1:
<response>
<message>....</message>
<message>....</message>
</response>

example 2:
<response>
<message>
<list_of_tags>
<message><name>age</name></message>
<message><name>jjj</name></message>
</list_of_tags>
</message>
<message>
<list_of_tags>
<message><name>age</name></message>
<message><name>jjj</name></message>
</list_of_tags>
</message>
</response>


example 3:
<response>
<message>
<list_of_tags>
<tag><name>age</name></tag>
<tag><name>jjj</name></tag>
</list_of_tags>
</message>
<message>
<list_of_tags>
<tag><name>age</name></tag>
<tag><name>jjj</name></tag>
</list_of_tags>
</message>
</response>


example 4:
class myXMLMessageEmitter(Emitter):
def _to_xml(self, xml, data):
if isinstance(data, (list, tuple)):
for item in data:
xml.startElement("message", {})
self._to_xml(xml, item)
xml.endElement("message")
elif isinstance(data, dict):
for key, value in data.iteritems():
xml.startElement(key, {})
self._to_xml(xml, value)
xml.endElement(key)
else:
xml.characters(smart_unicode(data))

def render(self, request):
stream = StringIO.StringIO()

xml = SimplerXMLGenerator(stream, "utf-8")
xml.startDocument()
xml.startElement("response", {})

self._to_xml(xml, self.construct())

xml.endElement("response")
xml.endDocument()

return stream.getvalue()

Emitter.register('messagexml', myXMLMessageEmitter, 'text/xml;
charset=utf-8')
Mimer.register(lambda *a: None, ('text/xml',))


On Mar 23, 5:36 pm, drewda <dre...@gmail.com> wrote:
--
You received this message because you are subscribed to the Google Groups "django-piston" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-pisto...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-piston?hl=en.

Peter Sanchez

unread,
Jun 8, 2010, 3:19:24 AM6/8/10
to django-piston
I have a custom Emitter working that does exactly what you want. It
takes a structured data "tiered" dictionary and turns it into the
appropriate XML.

First, in my Handlers I add an additional field called "xml_id_tag",
example:

class SaleHandler(BaseHandler):
xml_id_tag = 'sale'
.....

I'll use that tag in the Emitter later. For my XML parsing I use a
custom parser I wrote for another open source project I own. You can
get the parser here:

http://bitbucket.org/petersanchez/zerigodns/src/tip/zerigodns/parser.py

And this is my Emitter class:

class CFXMLEmitter(Emitter):
def __init__(self, *args, **kwargs):
super(CFXMLEmitter, self).__init__(*args, **kwargs)
self.xml_parser = Parser()

def render(self, request):
id_tag = self.handler.xml_id_tag
id_tag_plus = id_tag + 's' # pluralize the tag
ret = dict()
data = self.construct()

if isinstance(data, (tuple, list)):
ret[id_tag_plus] = [{
id_tag: x
} for x in data]
else:
ret[id_tag] = data

return self.xml_parser.build_request_string(ret)

This returns the data in the tiered structure that you want..

Example:

{'sales': [
{'sale':
{'id': 1, 'name': 'test1', 'null-field': None}},
{'sale':
{'id': 2, 'name': 'test2'}}
]}

Becomes:

<sales type="array">
<sale>
<id type="integer">1</id>
<name>test1</name>
<null-field nil="true" />
</sale>
<sale>
<id type="integer">2</id>
<name>test2</name>
</sale>
</sales>

And vise versa.

Call Parser().build_request_string() to convert a dictionary to
XML.

Call Parser().parse() to convert an XML string to a dictionary.

Obviously this is a fairly custom solution to fit my needs, but it's
pretty easy to duplicate and use in whatever project.

Hope this helps you guys...

Peter
Reply all
Reply to author
Forward
0 new messages