SickGear/lib/etreetodict.py
Prinz23 9b3af8b84a Change optimise TheTVDB processes, 40% to 66% saved adding new and existing shows, 40% to 50% saved per show update.
Change improve shows with more episodes gain largest reductions in time spent processing.
Change when using "Add new show" reduce search time outs.
Change always allow incomplete show data.
Remove redundant config/general/"Allow incomplete show data".
2016-09-24 02:09:53 +01:00

141 lines
4 KiB
Python

try:
from lxml import ElementTree
except ImportError:
try:
import xml.etree.cElementTree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
class XmlDictObject(dict):
"""
Adds object like functionality to the standard dictionary.
"""
def __init__(self, initdict=None):
if initdict is None:
initdict = {}
dict.__init__(self, initdict)
def __getattr__(self, item):
return self.__getitem__(item)
def __setattr__(self, item, value):
self.__setitem__(item, value)
def __str__(self):
if self.has_key('_text'):
return self.__getitem__('_text')
else:
return ''
@staticmethod
def Wrap(x):
"""
Static method to wrap a dictionary recursively as an XmlDictObject
"""
if isinstance(x, dict):
return XmlDictObject((k, XmlDictObject.Wrap(v)) for (k, v) in x.iteritems())
elif isinstance(x, list):
return [XmlDictObject.Wrap(v) for v in x]
else:
return x
@staticmethod
def _UnWrap(x):
if isinstance(x, dict):
return dict((k, XmlDictObject._UnWrap(v)) for (k, v) in x.iteritems())
elif isinstance(x, list):
return [XmlDictObject._UnWrap(v) for v in x]
else:
return x
def UnWrap(self):
"""
Recursively converts an XmlDictObject to a standard dictionary and returns the result.
"""
return XmlDictObject._UnWrap(self)
def _ConvertDictToXmlRecurse(parent, dictitem):
assert type(dictitem) is not type([])
if isinstance(dictitem, dict):
for (tag, child) in dictitem.iteritems():
if str(tag) == '_text':
parent.text = str(child)
elif type(child) is type([]):
# iterate through the array and convert
for listchild in child:
elem = ElementTree.Element(tag)
parent.append(elem)
_ConvertDictToXmlRecurse(elem, listchild)
else:
elem = ElementTree.Element(tag)
parent.append(elem)
_ConvertDictToXmlRecurse(elem, child)
else:
parent.text = str(dictitem)
def ConvertDictToXml(xmldict):
"""
Converts a dictionary to an XML ElementTree Element
"""
roottag = xmldict.keys()[0]
root = ElementTree.Element(roottag)
_ConvertDictToXmlRecurse(root, xmldict[roottag])
return root
def _ConvertXmlToDictRecurse(node, dictclass):
nodedict = dictclass()
if len(node.items()) > 0:
# if we have attributes, set them
nodedict.update(dict(node.items()))
for child in node:
# recursively add the element's children
newitem = _ConvertXmlToDictRecurse(child, dictclass)
if nodedict.has_key(child.tag):
# found duplicate tag, force a list
if type(nodedict[child.tag]) is type([]):
# append to existing list
nodedict[child.tag].append(newitem)
else:
# convert to list
nodedict[child.tag] = [nodedict[child.tag], newitem]
else:
# only one, directly set the dictionary
nodedict[child.tag] = newitem
if node.text is None:
text = ''
else:
text = node.text.strip()
if len(nodedict) > 0:
# if we have a dictionary add the text as a dictionary value (if there is any)
if len(text) > 0:
nodedict['_text'] = text
else:
# if we don't have child nodes or attributes, just set the text
nodedict = text
return nodedict
def ConvertXmlToDict(root, dictclass=XmlDictObject):
"""
Converts an XML String to a dictionary
"""
if isinstance(root, basestring):
root = ElementTree.fromstring(root)
elif not isinstance(root, ElementTree.Element):
raise TypeError, 'Expected string'
return dictclass({root.tag: _ConvertXmlToDictRecurse(root, dictclass)})