mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 08:56: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:
parent
98901e5b86
commit
64e686584a
@ -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 '<?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
|
||||
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'} ] }
|
||||
# --> <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)
|
||||
|
Loading…
Reference in New Issue
Block a user