from __future__ import annotations from typing import Any from xml.etree import ElementTree as ET XML_LANG = "{http://www.w3.org/XML/1998/namespace}lang" def _text(value: Any) -> str: return str(value or "").strip() def _labels(node: ET.Element) -> dict[str, dict[str, str]]: result = { "ru": {"label": "", "description": "", "short": ""}, "en": {"label": "", "description": "", "short": ""}, } for label in node.findall("./label"): language = _text(label.attrib.get(XML_LANG) or label.attrib.get("lang") or "ru").lower() if language not in result: continue result[language] = { "label": _text(label.text), "description": _text(label.attrib.get("description")), "short": _text(label.attrib.get("short")), } return result def _merge_entry(target: dict[str, Any], source: dict[str, Any]) -> None: for language in ("ru", "en"): current = target.setdefault(language, {"label": "", "description": "", "short": ""}) incoming = source.get(language, {}) for key in ("label", "description", "short"): if not current.get(key) and incoming.get(key): current[key] = incoming[key] def parse_navigation_labels_xml(content: bytes | str) -> dict[str, Any]: raw = content.encode("utf-8") if isinstance(content, str) else content root = ET.fromstring(raw) columns: dict[str, dict[str, Any]] = {} by_section: dict[str, dict[str, dict[str, Any]]] = {} sections: dict[str, dict[str, Any]] = {} for item in root.findall(".//list//item[@section]"): section = _text(item.attrib.get("section")) if section: entry = _labels(item) target = sections.setdefault(section, {}) _merge_entry(target, entry) for columns_node in root.findall(".//columns"): section_names = [part for part in _text(columns_node.attrib.get("sections")).split() if part] for index, cell in enumerate(columns_node.findall("./cell")): ref = _text(cell.attrib.get("ref")) labels = _labels(cell) if not ref: ru = labels.get("ru", {}).get("label", "").casefold() en = labels.get("en", {}).get("label", "").casefold() if ru in {"игрок", "хоккеист"} or en == "player": ref = "player" elif ru in {"клуб", "команда"} or en == "team": ref = "team" elif ru == "№" or en in {"№", "no.", "number"}: ref = "number" elif index == 0: ref = "rank" else: continue entry = { **labels, "datatype": _text(cell.attrib.get("datatype")), "sortable": _text(cell.attrib.get("sortable")), "default": _text(cell.attrib.get("default")), } global_entry = columns.setdefault(ref, {}) _merge_entry(global_entry, entry) for key in ("datatype", "sortable", "default"): if not global_entry.get(key) and entry.get(key): global_entry[key] = entry[key] for section in section_names: section_entry = by_section.setdefault(section, {}).setdefault(ref, {}) _merge_entry(section_entry, entry) for key in ("datatype", "sortable", "default"): if not section_entry.get(key) and entry.get(key): section_entry[key] = entry[key] return { "available": bool(columns or sections), "columns": columns, "columns_by_section": by_section, "sections": sections, }