Вопрос : Как получить доступ к элементу значения в iTunes xml
Следующее решение с использованием lxml.etree.iterparse
добавляет тег <key>
со следующим <value>
тег для создания Python dict {key:value}
.
Используется модуль и встроенные функции :
from lxml import etree
import io
class Playlist:
def __init__(self, fh):
"""
Initialize 'iterparse' to generate 'start' and 'end' events on all tags
:param fh: File Handle from the XML File to parse
"""
self.context = etree.iterparse(fh, events=("start", "end",))
def _parse(self):
"""
Yield only at 'end' event, except 'start' from tag 'dict'
:return: yield current Element
"""
for event, elem in self.context:
if elem.tag == 'plist' or \
(event == 'start' and not elem.tag == 'dict'):
continue
yield elem
def _parse_key_value(self, key=None):
_dict = {}
for elem in self._parse():
if elem.tag == 'key':
key = elem.text
continue
if elem.tag in ['integer', 'string', 'date']:
if not key is None:
_dict[key] = elem.text
key = None
else:
print('Missing key for value {}'.format(elem.text))
elif elem.tag in ['true', 'false']:
_dict[key] = elem.tag == 'true'
elif elem.tag == 'dict':
if not key is None:
_dict[key] = self._parse_dict(key)
key = None
else:
return elem, _dict
else:
print('Unknow tag {}'.format(elem.tag))
def _parse_dict(self, key=None):
elem = next(self._parse())
elem, _dict = self._parse_key_value(elem.text)
return _dict
def __iter__(self):
for elem in self._parse():
if elem.tag == 'dict':
yield self._parse_dict()
else:
print('Unknow tag {}'.format(elem.tag))
if __name__ == "__main__":
data = b'''<?xml...'''
with io.BytesIO(data) as in_xml:
for record in Playlist(in_xml):
print("record:{}".format(record))
for key, value in record.items():
print("{}:{}".format(key, value))
Выход :
record:{'Major Version': '1', 'Minor Version': '1'... (omitted for brevity)
Major Version:1
Minor Version:1
Date:2019-01-24T10:31:15Z
Tracks:{'99244': {'Track ID': '99244', 'Artist': 'Blaze Podcast Network', ... (omitted for brevity)}}
Проверено на Python: 3,5