Парсинг и конвертация тестового XML файла в файл формата YAML на языке Python
Здравствуйте! Нужна помощь с написанием нормально работающей программы конвертера XML в YAML .
Сделать это нужно при помощи языка Python. Нельзя использовать готовые библиотеки, в том числе регулярные выражения в Python и библиотеки для загрузки XML-файлов. Встроенные модули разрешены!
1. На руках есть файл формата XML .
<?xml version="1.0"?>
<timetable>
<lang> ru </lang>
<day> Wednesday </day>
<lessons>
<lesson1>
<teacher> Балакшин Павел Валерьевич </teacher>
<time> 08:20-09:50 </time>
<group> ИНФОРМ 3 </group>
<room> Актовый зал </room>
<place> ул.Ломоносова, д.9, лит. М </place>
<subject> ИНФОРМАТИКА (ЛЕК): АКТОВЫЙ ЗАЛ</subject>
<lesson-format> Очно-дистанционный </lesson-format>
</lesson1>
<lesson2>
<teacher> Клименков Сергей Викторович </teacher>
<time> 10:00-11:30 </time>
<group> ОСН ПРОФ ДЕЯТ 1 </group>
<room> Актовый зал </room>
<place> ул.Ломоносова, д.9, лит. М </place>
<subject> ОСНОВЫ ПРОФЕССИОНАЛЬНОЙ ДЕЯТЕЛЬНОСТИ (ЛЕК) : АКТОВЫЙ ЗАЛ</subject>
<lesson-format> Очно-дистанционный </lesson-format>
</lesson2>
</lessons>
</timetable>
2. Нужно преобразовать его в файл формата YAML, чтобы программа создала новый файла с только что полученным YAML внутри:
timetable:
lang: ru
day: Wednesday
lessons:
lesson1:
teacher: Балакшин Павел Валерьевич
time: '08:20-09:50'
group: ИНФОРМ 3
room: Актовый зал
place: 'ул.Ломоносова, д.9, лит. М'
subject: 'ИНФОРМАТИКА (ЛЕК): АКТОВЫЙ ЗАЛ'
lesson-format: Очно-дистанционный
lesson2:
teacher: Клименков Сергей Викторович
time: '10:00-11:30'
group: ОСН ПРОФ ДЕЯТ 1
room: Актовый зал
place: 'ул.Ломоносова, д.9, лит. М'
subject: 'ОСНОВЫ ПРОФЕССИОНАЛЬНОЙ ДЕЯТЕЛЬНОСТИ (ЛЕК) : АКТОВЫЙ ЗАЛ'
lesson-format: Очно-дистанционный
Сделать это нужно при помощи языка Python. Что самое весёлое, нельзя использовать готовые библиотеки, в том числе регулярные выражения в Python и библиотеки для загрузки XML-файлов. Встроенные модули разрешены!
Есть пример кода, который неправильно работает:
fin = open('schedule.xml', encoding='UTF-8')
fout = open('schedule_out.yaml', 'w+')
fout.write('---\n')
read = 0
word = ''
for line in fin:
xml = line
yaml = ''
for i in range(len(xml)):
if read != 2 and xml[i] == '\t' or xml[i] == ' ' or xml[i] == '\n':
yaml = yaml + xml[i]
elif xml[i] == '<':
if xml[i + 1] != '/':
read = 1
else:
read = -1
elif xml[i] == '>':
if read == 1:
yaml = yaml + ': '
read = 2
elif read == -1:
if word != '':
if not word.isnumeric():
yaml = yaml + '"' + word + '"'
word = ''
else:
yaml = yaml + word
word = ''
read = 0
elif read == 1:
yaml = yaml + xml[i]
elif read == 2:
word = word + xml[i]
fout.write(yaml)
fout.write('\n...')
fout.close()
Вывод такого недокода:
---
?xml version="1.0"?:
timetable:
lang: " ru"
day: "Wednesday"
lessons:
lesson1:
teacher: " БалакшинПавелВалерьевич"
time: "08:20-09:50"
group: "ИНФОРМ3"
room: "Актовыйзал"
place: "ул.Ломоносова,д.9,лит.М"
subject: "ИНФОРМАТИКА(ЛЕК):АКТОВЫЙЗАЛ"
lesson-format: "Очно-дистанционный"
lesson2:
teacher: " КлименковСергейВикторович"
time: "10:00-11:30"
group: "ОСНПРОФДЕЯТ1"
room: "Актовыйзал"
place: "ул.Ломоносова,д.9,лит.М"
subject: "ОСНОВЫПРОФЕССИОНАЛЬНОЙДЕЯТЕЛЬНОСТИ(ЛЕК):АКТОВЫЙЗАЛ"
lesson-format: "Очно-дистанционный"
...
Буду признателен, если поможете!
Ответы (1 шт):
Вот +- рабочий парсер, наверно с багами, надо тестить, но тот тест кейс, который вы прислали проходит
PUNCTUATION = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
def get_open_tag_name(s: str) -> str:
for i in range(len(s)):
if s[i] == '>':
return s[:i+1]
raise ValueError('Key not found')
def get_close_tag_name(s: str) -> str:
return s.replace('<', '</')
def get_text_without_tag(text: str, open_tag: str, close_tag: str):
result = text.replace(open_tag, '').replace(close_tag, '').strip()
if result:
if not result.isalnum() or not result.isascii():
result = f'\'{result}\''
return result
def get_yaml_content(lines) -> str:
open_tags = []
yml_content = []
for row in lines:
tab_lenght = '\t' * len(open_tags)
tmp_row = row.strip()
if tmp_row[0] == '<' and tmp_row[1] not in PUNCTUATION:
open_tag = get_open_tag_name(tmp_row)
close_tag = get_close_tag_name(open_tag)
text = get_text_without_tag(tmp_row, open_tag, close_tag)
if tmp_row[-len(close_tag):] != close_tag:
open_tags.append(close_tag)
yml_content.append(f'{tab_lenght}{open_tag[1:-1]}: {text}')
elif tmp_row[0] == '<' and tmp_row[1] == '/':
if open_tags[-1] != tmp_row:
raise ValueError('Bad XML file')
open_tags.pop()
if len(open_tags) != 0:
raise ValueError('Bad XML file')
return '\n'.join(yml_content)
def main():
with open('test.xml', mode='r') as f:
xml_lines = f.readlines()
yaml_content = get_yaml_content(xml_lines)
with open('test.yml', mode='w') as f:
f.write(yaml_content)
if __name__ == '__main__':
main()
Вывод
timetable:
lang: ru
day: Wednesday
lessons:
lesson1:
teacher: 'Балакшин Павел Валерьевич'
time: '08:20-09:50'
group: 'ИНФОРМ 3'
room: 'Актовый зал'
place: 'ул.Ломоносова, д.9, лит. М'
subject: 'ИНФОРМАТИКА (ЛЕК): АКТОВЫЙ ЗАЛ'
lesson-format: 'Очно-дистанционный'
lesson2:
teacher: 'Клименков Сергей Викторович'
time: '10:00-11:30'
group: 'ОСН ПРОФ ДЕЯТ 1'
room: 'Актовый зал'
place: 'ул.Ломоносова, д.9, лит. М'
subject: 'ОСНОВЫ ПРОФЕССИОНАЛЬНОЙ ДЕЯТЕЛЬНОСТИ (ЛЕК) : АКТОВЫЙ ЗАЛ'
lesson-format: 'Очно-дистанционный'