mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-23 01:16:18 +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:
parent
98901e5b86
commit
64e686584a
@ -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("&", "\\&")
|
|
||||||
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user