"""This module is for parsing and conversion functions that needs objects from both music library and music service data structures """ from functools import lru_cache import logging import lxml.etree as ET from .data_structures import didl_class_to_soco_class from .exceptions import DIDLMetadataError from .xml import ns_tag _LOG = logging.getLogger(__name__) _LOG.addHandler(logging.NullHandler()) _LOG.debug("%s imported", __name__) @lru_cache() def from_didl_string(string): """Convert a unicode xml string to a list of `DIDLObjects `. Args: string (str): A unicode string containing an XML representation of one or more DIDL-Lite items (in the form ``' ...'``) Returns: list: A list of one or more instances of `DidlObject` or a subclass """ items = [] parser = ET.XMLParser(recover=True, encoding="utf-8") root = ET.fromstring(string.encode("utf-8"), parser=parser) for elt in root: if elt.tag.endswith("item") or elt.tag.endswith("container"): item_class = elt.findtext(ns_tag("upnp", "class")) cls = didl_class_to_soco_class(item_class) item = cls.from_element(elt) items.append(item) else: # elements are allowed as an immediate child of # according to the spec, but I have not seen one there in Sonos, so # we treat them as illegal. May need to fix this if this # causes problems. raise DIDLMetadataError("Illegal child of DIDL element: <%s>" % elt.tag) _LOG.debug( 'Created data structures: %.20s (CUT) from Didl string "%.20s" (CUT)', items, string, ) return items