1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-11-10 04:02:17 +00:00

New way of building XML

Less error-prone
Allows setting both attirbutes and text-data on a single element
This commit is contained in:
spl0k 2013-11-24 19:18:33 +01:00
parent 98901e5b86
commit 64e686584a

View File

@ -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,10 +111,14 @@ class ResponseHelper:
'version': version,
'xmlns': "http://subsonic.org/restapi"
})
return '<?xml version="1.0" encoding="UTF-8" ?>' + ResponseHelper.jsonp2xml({'subsonic-response': ret}).replace("&", "\\&amp;")
elem = ElementTree.Element('subsonic-response')
ResponseHelper.dict2xml(elem, ret)
return '<?xml version="1.0" encoding="UTF-8" ?>' + 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" }]}
@ -123,67 +127,24 @@ class ResponseHelper:
ex. {"subsonic-response": { "musicFolders": {"musicFolder": [{ "id": 0,"name": "Music"}]},
"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'} ] }
# --> <index a="1" /> <index b="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)