Открыть xml-файлы в python с плохим представлением
У меня 100 файлов формата xml, которые я не могу открыть
Пример файла:
<?xml version="1.0" <?xml version="1.0" encoding="UTF-8"?>
<api version="3.2">
<peoplecount>
<entry id="1" name="" userid="">
<count datetime="2022.07.11 14:16:20" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:21:57" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:23:11" realin="0" realout="1" realpass="0" queuetime="0" />
%skipzero[1,2]%</entry>
</peoplecount>
<timezone name="Europe/Moscow" offset="10800"/>
</api>
Я использую xml.etree.ElementTree для парсинга файла
import xml.etree.ElementTree as ET
tree = ET.parse('pathname.xml')
root = tree.getroot()
for child in root.iter('count'):
print(child.tag, child.attrib)
Ошибка связана с "not well-formed"
Я знаю причину ошибки (In the beginning, you need to delete '<?xml version="1.0" ') , но так как файлов более 100, устану открывать каждый и удалять
Есть идеи, как поправить формат файла перед открытием?
Ответы (2 шт):
# with open('pathname.xml') as f:
# txt = f.read()
txt = '''<?xml version="1.0" <?xml version="1.0" encoding="UTF-8"?>
<api version="3.2">
<peoplecount>
<entry id="1" name="" userid="">
<count datetime="2022.07.11 14:16:20" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:21:57" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:23:11" realin="0" realout="1" realpass="0" queuetime="0" />
%skipzero[1,2]%</entry>
</peoplecount>
<timezone name="Europe/Moscow" offset="10800"/>
</api>
'''
# 1
import xml.etree.ElementTree as ET
txt_r = txt.replace('<?xml version="1.0" <?xml version="1.0" encoding="UTF-8"?>',
'<?xml version="1.0" encoding="UTF-8"?>')
root = ET.fromstring(txt_r)
for child in root.iter('count'):
print(child.tag, child.attrib)
# 2
from bs4 import BeautifulSoup
soup = BeautifulSoup(txt, 'xml')
for child in soup.find_all('count'):
print(child.name, child.attrs)
похожий вариант с recover-режимом обработки ошибочных xml, то есть замену делать не надо:
x = """<?xml version="1.0" <?xml version="1.0" encoding="UTF-8"?>
<api version="3.2">
<peoplecount>
<entry id="1" name="" userid="">
<count datetime="2022.07.11 14:16:20" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:21:57" realin="0" realout="1" realpass="0" queuetime="0" />
<count datetime="2022.07.11 14:23:11" realin="0" realout="1" realpass="0" queuetime="0" />
%skipzero[1,2]%</entry>
</peoplecount>
<timezone name="Europe/Moscow" offset="10800"/>
</api>
"""
from lxml import etree
x = x.encode('utf-8')
parser = etree.XMLParser(recover=True)
root = etree.fromstring(x, parser=parser)
for child in root.iter('count'):
print(child.tag, child.attrib)
вывод:
/bin/python3 /home/ru/py.1/p1/p.py
count {'datetime': '2022.07.11 14:16:20', 'realin': '0', 'realout': '1', 'realpass': '0', 'queuetime': '0'}
count {'datetime': '2022.07.11 14:21:57', 'realin': '0', 'realout': '1', 'realpass': '0', 'queuetime': '0'}
count {'datetime': '2022.07.11 14:23:11', 'realin': '0', 'realout': '1', 'realpass': '0', 'queuetime': '0'}