diff --git a/api/__init__.py b/api/__init__.py index a650c27..f555e2f 100755 --- a/api/__init__.py +++ b/api/__init__.py @@ -1,8 +1,8 @@ # coding: utf-8 from flask import request +from xml.etree import ElementTree import simplejson -import cgi import uuid from web import app @@ -111,79 +111,40 @@ class ResponseHelper: 'version': version, 'xmlns': "http://subsonic.org/restapi" }) - return '' + ResponseHelper.jsonp2xml({'subsonic-response': ret}).replace("&", "\\&") + + elem = ElementTree.Element('subsonic-response') + ResponseHelper.dict2xml(elem, ret) + + return '' + ElementTree.tostring(elem, 'utf-8') @staticmethod - def jsonp2xml(json, indent = 0): + def dict2xml(elem, dictionary): """Convert a json structure to xml. The game is trivial. Nesting uses the [] parenthesis. ex. { 'musicFolder': {'id': 1234, 'name': "sss" } } ex. { 'musicFolder': [{'id': 1234, 'name': "sss" }, {'id': 456, 'name': "aaa" }]} ex. { 'musicFolders': {'musicFolder' : [{'id': 1234, 'name': "sss" }, {'id': 456, 'name': "aaa" }] } } ex. { 'index': [{'name': 'A', 'artist': [{'id': '517674445', 'name': 'Antonello Venditti'}] }] } ex. {"subsonic-response": { "musicFolders": {"musicFolder": [{ "id": 0,"name": "Music"}]}, - "status": "ok","version": "1.7.0","xmlns": "http://subsonic.org/restapi"}} + "status": "ok","version": "1.7.0","xmlns": "http://subsonic.org/restapi"}} """ + if not isinstance(dictionary, dict): + raise TypeError('Expecting a dict') - ret = '\n' + '\t' * indent - content = None - for c in [str, int, unicode]: - if isinstance(json, c): - return str(json) - if not isinstance(json, dict): - raise Exception("class type: %s" % json) + subelems = { k: v for k, v in dictionary.iteritems() if isinstance(v, dict) } + sequences = { k: v for k, v in dictionary.iteritems() if isinstance(v, list) } + attributes = { k: v for k, v in dictionary.iteritems() if k != '_value_' and k not in subelems and k not in sequences } - # every tag is a dict. - # its value can be a string, a list or a dict - for tag in json.keys(): - tag_list = json[tag] - - # if tag_list is a list, then it represent a list of elements - # ex. {index: [{ 'a':'1'} , {'a':'2'} ] } - # --> - if isinstance(tag_list, list): - for t in tag_list: - # for every element, get the attributes - # and embed them in the tag named - attributes = "" - content = "" - for (attr, value) in t.iteritems(): - # only serializable values are attributes - if value.__class__.__name__ in 'str': - attributes = '%s %s="%s"' % ( - attributes, - attr, - cgi.escape(value, quote=None) - ) - elif value.__class__.__name__ in ['int', 'unicode', 'bool', 'long']: - attributes = '%s %s="%s"' % ( - attributes, attr, value) - # other values are content - elif isinstance(value, dict): - content += ResponseHelper.jsonp2xml(value, indent + 1) - elif isinstance(value, list): - content += ResponseHelper.jsonp2xml({attr: value}, indent + 1) - if content: - ret += "<%s%s>%s\n%s" % ( - tag, attributes, content, '\t' * indent, tag) - else: - ret += "<%s%s />" % (tag, attributes) - if isinstance(tag_list, dict): - attributes = "" - content = "" - - for (attr, value) in tag_list.iteritems(): - # only string values are attributes - if not isinstance(value, dict) and not isinstance(value, list): - attributes = '%s %s="%s"' % ( - attributes, attr, value) - else: - content += ResponseHelper.jsonp2xml({attr: value}, indent + 1) - if content: - ret += "<%s%s>%s\n%s" % (tag, attributes, content, '\t' * indent, tag) - else: - ret += "<%s%s />" % (tag, attributes) - - return ret.replace('"True"', '"true"').replace('"False"', '"false"') + if '_value_' in dictionary: + elem.text = dictionary['_value_'] + for attr, value in attributes.iteritems(): + elem.set(attr, str(value).lower() if isinstance(value, bool) else str(value)) + for sub, subdict in subelems.iteritems(): + subelem = ElementTree.SubElement(elem, sub) + ResponseHelper.dict2xml(subelem, subdict) + for seq, dicts in sequences.iteritems(): + for subdict in dicts: + subelem = ElementTree.SubElement(elem, seq) + ResponseHelper.dict2xml(subelem, subdict) def get_entity(req, ent, param = 'id'): eid = req.args.get(param)