import re import xml.etree.ElementTree as ET class InvoicePartyService: @staticmethod def extract_address_from_ksef_xml(xml_content: str): result = { 'street': None, 'city': None, 'postal_code': None, 'country': None, 'address': None, } if not xml_content: return result try: root = ET.fromstring(xml_content) except Exception: return result def local_name(tag: str) -> str: return tag.split('}', 1)[1] if '}' in tag else tag def clean(value): return (value or '').strip() def find_text(names: list[str]): wanted = {name.lower() for name in names} for node in root.iter(): if local_name(node.tag).lower() in wanted: text = clean(node.text) if text: return text return None street = find_text(['Ulica', 'AdresL1']) house_no = find_text(['NrDomu']) apartment_no = find_text(['NrLokalu']) city = find_text(['Miejscowosc']) postal_code = find_text(['KodPocztowy']) country = find_text(['Kraj', 'KodKraju']) adres_l2 = find_text(['AdresL2']) if adres_l2 and (not postal_code or not city): match = re.match(r'^(\d{2}-\d{3})\s+(.+)$', clean(adres_l2)) if match: postal_code = postal_code or match.group(1) city = city or clean(match.group(2)) elif not city: city = clean(adres_l2) street_line = clean(street) if not street_line: street_parts = [part for part in [street, house_no] if part] street_line = ' '.join([p for p in street_parts if p]).strip() if apartment_no: street_line = f'{street_line}/{apartment_no}' if street_line else apartment_no address_parts = [part for part in [street_line, postal_code, city, country] if part] result.update({ 'street': street_line or None, 'city': city, 'postal_code': postal_code, 'country': country, 'address': ', '.join(address_parts) if address_parts else None, }) return result