Проверка на пустые элементы в XML
Есть xml файл:
<row>
<row_id>11</row_id>
<col_account_id>2783</col_account_id>
<col_login>unknown</col_login>
<col_full_name>unknown</col_full_name>
<col_actual_payment_date>Tue Jul 13 14:08:35 MSK 2021</col_actual_payment_date>
<col_date_of_payment>Tue Jul 13 14:09:01 MSK 2021</col_date_of_payment>
<col_volume>9.500</col_volume>
<col_currency>BYN</col_currency>
<col_comment>Ошибочно начисленная абон. плата</col_comment>
<col_payment_method>Перерасчет (103)</col_payment_method>
<col_recieved_by>evandrushenko (-44)</col_recieved_by>
</row>
<row>
<row_id>12</row_id>
<col_account_id></col_account_id>
<col_login>ubil1_20</col_login>
<col_full_name>(РОУТ)Демидова Наталья Васильевна</col_full_name>
<col_actual_payment_date>Tue Jul 13 10:00:03 MSK 2021</col_actual_payment_date>
<col_date_of_payment>Tue Jul 13 10:00:31 MSK 2021</col_date_of_payment>
<col_volume>15.900</col_volume>
<col_currency>BYN</col_currency>
<col_comment>No comment</col_comment>
<col_payment_method>Оплата наличными (абон плата при подкл) (108)</col_payment_method>
<col_recieved_by>evandrushenko (-44)</col_recieved_by>
</row>
<row>
<row_id>13</row_id>
<col_account_id>2784</col_account_id>
<col_login>chong8_25-2</col_login>
<col_full_name>(РОУТ )Новиков Александр Владимирович</col_full_name>
<col_actual_payment_date>Fri Jul 09 12:00:26 MSK 2021</col_actual_payment_date>
<col_date_of_payment>Fri Jul 09 12:00:43 MSK 2021</col_date_of_payment>
<col_volume>12.900</col_volume>
<col_currency>BYN</col_currency>
<col_comment></col_comment>
<col_payment_method>Оплата наличными (абон плата при подкл) (108)</col_payment_method>
<col_recieved_by>evandrushenko (-44)</col_recieved_by>
</row>
Есть парсер для XML файла:
import xml.dom.minidom as minidom
try:
with minidom.parse(xml) as doc:
books = doc.getElementsByTagName("row")
xml_tuple = ("col_date_of_payment", "col_actual_payment_date", "col_account_id",\
"col_full_name", "col_volume", "col_comment", "col_payment_method")
titles = []
[[titles.append(book.getElementsByTagName(i)[0]) for i in xml_tuple] \
for book in books]
"""Поля не должны быть пустыми"""
y = []
[[y.append(node.data) for node in title.childNodes \
if node.nodeType == node.TEXT_NODE]\
for title in titles]
except (Exception, TypeError, AttributeError):
log.error("Exception occurred", exc_info=True)
time.sleep(20)
else:
log.info("Считаем количество платежей")
y = zip(*[iter(y)] * 7)
yield tuple(y)
Как здесь можно реализовать проверку на пустые поля?
Скажем, если col_actual_payment_date пустой, то заполнить это поле звездочками(***).
Результат должен быть следующий:
[['Tue Jul 13 14:09:01 MSK 2021', 'Tue Jul 13 14:08:35 MSK 2021', '2783', 'unknown', '9.500', 'Ошибочно начисленная абон. плата', 'Перерасчет (103)'],
['16.07.2021', '16.07.2021', '***', '(РОУТ)Демидова Наталья Васильевна', '14,97', 'Перенос с СКТ на СПД Справка №56 от 13.07.2021', 'Оплата наличными (абон плата при подкл) (108)'],
['Fri Jul 09 12:00:43 MSK 2021', 'Fri Jul 09 12:00:26 MSK 2021', '2784', '(РОУТ )Новиков Александр Владимирович', '12.900', '***', 'Оплата наличными (абон плата при подкл) (108)']]
Ответы (1 шт):
Автор решения: gil9red
→ Ссылка
Добавил функцию для получения текста из элемента с значением по умолчанию
Переписал алгоритм парсинга
Пример:
import xml.dom.minidom as minidom
def get_all_text(node) -> str:
if node.nodeType == node.TEXT_NODE:
return node.data
else:
return ''.join(get_all_text(child_node) for child_node in node.childNodes)
xml = '1.xml'
with minidom.parse(xml) as doc:
xml_tuple = (
"col_date_of_payment", "col_actual_payment_date", "col_account_id",
"col_full_name", "col_volume", "col_comment", "col_payment_method"
)
items = []
for row_el in doc.getElementsByTagName("row"):
row = []
for tag_name in xml_tuple:
child_el = row_el.getElementsByTagName(tag_name)[0]
child_text = get_all_text(child_el) or '***'
row.append(child_text)
items.append(row)
print(items)
Результат:
[
['Tue Jul 13 14:09:01 MSK 2021', 'Tue Jul 13 14:08:35 MSK 2021', '2783', 'unknown', '9.500', 'Ошибочно начисленная абон. плата', 'Перерасчет (103)'],
['Tue Jul 13 10:00:31 MSK 2021', 'Tue Jul 13 10:00:03 MSK 2021', '***', '(РОУТ)Демидова Наталья Васильевна', '15.900', 'No comment', 'Оплата наличными (абон плата при подкл) (108)'],
['Fri Jul 09 12:00:43 MSK 2021', 'Fri Jul 09 12:00:26 MSK 2021', '2784', '(РОУТ )Новиков Александр Владимирович', '12.900', '***', 'Оплата наличными (абон плата при подкл) (108)']
]
UPD.
Думаю, указывать *** в функции в качестве значения по умолчанию нехорошая идея, лучше вынести проверку из функции:
def get_all_text(node) -> str:
if node.nodeType == node.TEXT_NODE:
return node.data
else:
return ''.join(get_all_text(child_node) for child_node in node.childNodes)
with minidom.parse(xml) as doc:
...
for row_el in doc.getElementsByTagName("row"):
...
child_text = get_all_text(child_el) or '***'