1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06: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 # coding: utf-8
from flask import request from flask import request
from xml.etree import ElementTree
import simplejson import simplejson
import cgi
import uuid import uuid
from web import app from web import app
@ -111,79 +111,40 @@ class ResponseHelper:
'version': version, 'version': version,
'xmlns': "http://subsonic.org/restapi" '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 @staticmethod
def jsonp2xml(json, indent = 0): def dict2xml(elem, dictionary):
"""Convert a json structure to xml. The game is trivial. Nesting uses the [] parenthesis. """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" } }
ex. { 'musicFolder': [{'id': 1234, 'name': "sss" }, {'id': 456, 'name': "aaa" }]} ex. { 'musicFolder': [{'id': 1234, 'name': "sss" }, {'id': 456, 'name': "aaa" }]}
ex. { 'musicFolders': {'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. { 'index': [{'name': 'A', 'artist': [{'id': '517674445', 'name': 'Antonello Venditti'}] }] }
ex. {"subsonic-response": { "musicFolders": {"musicFolder": [{ "id": 0,"name": "Music"}]}, 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 subelems = { k: v for k, v in dictionary.iteritems() if isinstance(v, dict) }
content = None sequences = { k: v for k, v in dictionary.iteritems() if isinstance(v, list) }
for c in [str, int, unicode]: attributes = { k: v for k, v in dictionary.iteritems() if k != '_value_' and k not in subelems and k not in sequences }
if isinstance(json, c):
return str(json)
if not isinstance(json, dict):
raise Exception("class type: %s" % json)
# every tag is a dict. if '_value_' in dictionary:
# its value can be a string, a list or a dict elem.text = dictionary['_value_']
for tag in json.keys(): for attr, value in attributes.iteritems():
tag_list = json[tag] elem.set(attr, str(value).lower() if isinstance(value, bool) else str(value))
for sub, subdict in subelems.iteritems():
# if tag_list is a list, then it represent a list of elements subelem = ElementTree.SubElement(elem, sub)
# ex. {index: [{ 'a':'1'} , {'a':'2'} ] } ResponseHelper.dict2xml(subelem, subdict)
# --> <index a="1" /> <index b="2" /> for seq, dicts in sequences.iteritems():
if isinstance(tag_list, list): for subdict in dicts:
for t in tag_list: subelem = ElementTree.SubElement(elem, seq)
# for every element, get the attributes ResponseHelper.dict2xml(subelem, subdict)
# 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"')
def get_entity(req, ent, param = 'id'): def get_entity(req, ent, param = 'id'):
eid = req.args.get(param) eid = req.args.get(param)