muryshev's picture
init
57cf043
raw
history blame
3.37 kB
import os
from bs4 import BeautifulSoup
from components.parser.xml.constants import (
ACTUAL_STATUSES,
EXCLUDE_OWNERS,
NAME_TAG,
OWNER_TAGS,
STATUS_TAG,
USEFUL_STATUSES,
)
from components.parser.xml.structures import ParsedXML
class XMLInfoParser:
"""
Класс для парсинга основной информации из xml файлов.
"""
def __init__(self, soup: BeautifulSoup, filepath: os.PathLike):
"""
Инициализация парсера.
Args:
soup: BeautifulSoup - суп, содержащий xml документ
filepath: os.PathLike - путь к файлу
"""
self.filepath = filepath
self.soup = soup
def parse(self) -> ParsedXML | None:
"""
Парсинг основной информации о xml файле.
Returns:
ParsedXML - информация о xml файле
"""
status = self._extract_info_value(STATUS_TAG)
owner = self._extract_info_recurse(OWNER_TAGS, EXCLUDE_OWNERS)
name = self._extract_info_value(NAME_TAG)
if (name == '') and (status == '') and (owner == ''):
status = ACTUAL_STATUSES[0]
owner = '-'
name = self.filepath.stem
if status not in USEFUL_STATUSES:
return None
return ParsedXML(status=status, owner=owner, name=name, filename=self.filepath)
def _extract_info_value(self, key: str) -> str:
"""
Извлечение значения из xml по тегу с использованием BeautifulSoup.
Args:
key: str - тег, по которому будет производиться поиск. Либо название документа, либо статус, либо владелец
Returns:
str - значение статуса, владельца или названия документа
"""
# Ищем тег в супе
key_tag = self.soup.find(string=key)
if not key_tag:
return ''
# Ищем следующий текстовый тег после ключевого
next_tag = key_tag.find_next('w:t')
if not next_tag:
return ''
return next_tag.get_text()
def _extract_info_recurse(
self,
keys: list[str],
excluding_values: list[str] | None = None,
) -> str:
"""
Извлечение значения из xml по нескольким тегам с использованием BeautifulSoup.
Args:
keys: list[str] - список тегов, по которым будет производиться поиск
excluding_values: list[str] | None - список значений, которые нужно исключить из результата
Returns:
str - значение статуса, владельца или названия документа
"""
result = []
for key in keys:
value = self._extract_info_value(key)
if excluding_values and (value in excluding_values):
continue
if value:
result.append(value)
return '/'.join(reversed(result))