import xml.etree.ElementTree as ET import openpyxl import glob import os HEADERS = [ "№ п/п", "Раздел КПТР", "Кадастровый номер", "Кадастровый квартал", "Вид объекта", "Площадь ЗУ", "Погрешность определения площади", "наличие координат", "Пояснения" ] def has_spatial(elem): """Проверяет наличие тега SpatialElement в рамках элемента.""" return "да" if elem.find(".//SpatialElement") is not None else "нет" def get_explanation(elem): """Ищет пояснения в тегах Explanation, ExplanationSection, NameSection""" for tag in ["Explanation", "ExplanationSection", "NameSection"]: sub = elem.find(f".//{tag}") if sub is not None and sub.text: return sub.text.strip() return "" def extract_fields(elem, tag): """ В зависимости от тега-объекта извлекает данные для строки: 2. Раздел КПТР – устанавливается по тегу 3. Кадастровый номер 4. Кадастровый квартал 5. Вид объекта 6. Площадь ЗУ 7. Погрешность определения площади 8. наличие координат 9. Пояснения """ if tag in {"NewParcel", "SpecifyParcel"}: section = "FormParcels" if tag=="NewParcel" else "SpecifyParcels" cadastral_number = elem.attrib.get("Definition", "") if cadastral_number.startswith(":"): cadastral_number = cadastral_number[1:] cadastral_block = (elem.findtext("CadastralBlock") or "").strip() # Если внутри есть тег ObjectType – берем его, иначе для ЗУ фиксированное значение ot = elem.findtext("ObjectType") object_type = ot.strip() if ot else "Земельный участок" area = (elem.findtext("Area/Area") or "").strip() inaccuracy = (elem.findtext("Area/Inaccuracy") or "").strip() coords = has_spatial(elem) explanation = get_explanation(elem) return [None, section, cadastral_number, cadastral_block, object_type, area, inaccuracy, coords, explanation] elif tag == "CadastralErrorParcel": # обрабатываем дочерний элемент CadastralErrorExistParcel sub = elem.find("CadastralErrorExistParcel") if sub is None: return None section = "CadastralErrorsParcels" cadastral_number = sub.attrib.get("CadastralNumber", "") cadastral_block = (sub.findtext("CadastralBlock") or "").strip() area = (sub.findtext("Area/Area") or "").strip() inaccuracy = (sub.findtext("Area/Inaccuracy") or "").strip() coords = has_spatial(sub) explanation = get_explanation(sub) object_type = "Земельный участок" return [None, section, cadastral_number, cadastral_block, object_type, area, inaccuracy, coords, explanation] elif tag == "ExistParcel": # элемент имеет атрибут CadastralNumber section = "ExistParcels" cadastral_number = elem.attrib.get("CadastralNumber", "") cadastral_block = (elem.findtext("CadastralBlock") or "").strip() area = (elem.findtext("Area/Area") or "").strip() inaccuracy = (elem.findtext("Area/Inaccuracy") or "").strip() coords = has_spatial(elem) explanation = get_explanation(elem) object_type = "Земельный участок" return [None, section, cadastral_number, cadastral_block, object_type, area, inaccuracy, coords, explanation] elif tag == "ExistNewObjectRealty": section = "ExistNewObjectsRealty" cadastral_number = (elem.findtext("CadastralNumber") or "").strip() ot = elem.findtext("ObjectType") object_type = ot.strip() if ot else "Объект недвижимости" cb_elem = elem.find("CadastralBlocks/CadastralBlock") cadastral_block = cb_elem.text.strip() if cb_elem is not None else "" # Пытаемся взять площадь из или альтернативный тег area = (elem.findtext("Area/Area") or elem.findtext("AreaInGKN") or "").strip() inaccuracy = (elem.findtext("Area/Inaccuracy") or "").strip() coords = has_spatial(elem) explanation = get_explanation(elem) return [None, section, cadastral_number, cadastral_block, object_type, area, inaccuracy, coords, explanation] elif tag == "CadastralErrorOKS": section = "CadastralErrorsOKS" cadastral_number = elem.attrib.get("CadastralNumber", "") cb_elem = elem.find("CadastralBlocks/CadastralBlock") cadastral_block = cb_elem.text.strip() if cb_elem is not None else "" # Возможно в данном разделе площадь находится в дочернем теге Area area = (elem.findtext("Area/Area") or "").strip() inaccuracy = (elem.findtext("Area/Inaccuracy") or "").strip() coords = has_spatial(elem) explanation = get_explanation(elem) object_type = "Объект недвижимости" return [None, section, cadastral_number, cadastral_block, object_type, area, inaccuracy, coords, explanation] else: return None def parse_all_stream(xml_file): """ Унифицированный итеративный парсинг. Обрабатываются объекты, у которых тег относится к: NewParcel, SpecifyParcel, CadastralErrorParcel, ExistParcel, ExistNewObjectRealty, CadastralErrorOKS. """ TARGET_TAGS = {"NewParcel", "SpecifyParcel", "CadastralErrorParcel", "ExistParcel", "ExistNewObjectRealty", "CadastralErrorOKS"} context = ET.iterparse(xml_file, events=("end",)) for event, elem in context: if elem.tag in TARGET_TAGS: row = extract_fields(elem, elem.tag) if row: yield row elem.clear() def main(xml_folder, output_excel): wb = openpyxl.Workbook() ws = wb.active ws.append(HEADERS) row_num = 1 xml_files = glob.glob(os.path.join(xml_folder, "*.xml")) for xml_file in xml_files: for row in parse_all_stream(xml_file): row[0] = row_num # заполняем № п/п ws.append(row) row_num += 1 wb.save(output_excel) print(f"Excel-файл сохранён: {output_excel}") if __name__ == "__main__": # Папка с XML-файлами, измените при необходимости. main("./test", "kptr_table.xlsx")