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