diff --git a/algam.py b/algam.py index b71d9ac..ac85bce 100644 --- a/algam.py +++ b/algam.py @@ -42,12 +42,59 @@ class xlsx_filer(): self.sheet.cell(row=row, column=9).value = object.explanations row += 1 - def __init__(self,data=[], path=""): + def update_connections_data(self): + """Обновляет данные на листе Связи""" + self.connections_sheet.cell(row=1, column=1).value = "№ п/п" + self.connections_sheet.cell(row=1, column=2).value = "Раздел КПТР" + self.connections_sheet.cell(row=1, column=3).value = "Кадастровый номер" + self.connections_sheet.cell(row=1, column=4).value = "Кадастровый квартал" + self.connections_sheet.cell(row=1, column=5).value = "Вид объекта" + self.connections_sheet.cell(row=1, column=6).value = "Связь" + + row = 2 + counter = 1 + for connection in self.connections_data: + self.connections_sheet.cell(row=row, column=1).value = counter + self.connections_sheet.cell(row=row, column=2).value = connection.section_KPTR + self.connections_sheet.cell(row=row, column=3).value = connection.cadastral_number + self.connections_sheet.cell(row=row, column=4).value = connection.cadastral_quarter + self.connections_sheet.cell(row=row, column=5).value = connection.object_type + self.connections_sheet.cell(row=row, column=6).value = connection.connection + row += 1 + counter += 1 + + def update_access_data(self): + """Обновляет данные на листе Сведения о доступе""" + self.access_sheet.cell(row=1, column=1).value = "№ п/п" + self.access_sheet.cell(row=1, column=2).value = "Раздел КПТР" + self.access_sheet.cell(row=1, column=3).value = "Кадастровый номер" + self.access_sheet.cell(row=1, column=4).value = "Кадастровый квартал" + self.access_sheet.cell(row=1, column=5).value = "Сведения о доступе" + + row = 2 + counter = 1 + for access in self.access_data: + self.access_sheet.cell(row=row, column=1).value = counter + self.access_sheet.cell(row=row, column=2).value = access.section_KPTR + self.access_sheet.cell(row=row, column=3).value = access.cadastral_number + self.access_sheet.cell(row=row, column=4).value = access.cadastral_quarter + self.access_sheet.cell(row=row, column=5).value = access.access_info + row += 1 + counter += 1 + + def __init__(self,data=[], connections_data=[], access_data=[], path=""): self.data = data + self.connections_data = connections_data + self.access_data = access_data self.path = path if os.path.isdir(path): self.workbook = openpyxl.Workbook() - self.sheet = self.workbook.create_sheet("Новый лист") + self.sheet = self.workbook.create_sheet("Основные данные") + self.connections_sheet = self.workbook.create_sheet("Связи") + self.access_sheet = self.workbook.create_sheet("Сведения о доступе") + # Удаляем стандартный лист + if "Sheet" in self.workbook.sheetnames: + self.workbook.remove(self.workbook["Sheet"]) class Data_farame(): @@ -62,6 +109,23 @@ class Data_farame(): self.explanations = explanations #Пояснения +class Connection_Data(): + def __init__(self, section_KPTR, cadastral_number, cadastral_quarter, object_type, connection): + self.section_KPTR = section_KPTR + self.cadastral_number = cadastral_number + self.cadastral_quarter = cadastral_quarter + self.object_type = object_type + self.connection = connection + + +class Access_Data(): + def __init__(self, section_KPTR, cadastral_number, cadastral_quarter, access_info): + self.section_KPTR = section_KPTR + self.cadastral_number = cadastral_number + self.cadastral_quarter = cadastral_quarter + self.access_info = access_info + + class super_visor(): def find_best_match(self,input_str: str) -> str: @@ -70,6 +134,7 @@ class super_visor(): "SpecifyParcels":"Уточнение ЗУ", "CadastralErrorsParcels":"Исправление ЗУ", "ExistObjectsRealty":"Уточнение ОКС", + "ExistNewObjectsRealty":"Уточнение ОКС", "CadastralErrorsOKS":"Исправление ОКС" } @@ -145,6 +210,61 @@ class super_visor(): return atrebut['Explanation'][0]['#text'] return "нет" + def get_connections(self, atrebut): + """Получает связи объекта""" + connections = [] + + # Для ЗУ ищем ObjectsRealty -> ObjectRealty -> InnerCadastralNumbers -> CadastralNumber + if 'ObjectsRealty' in atrebut: + objects_realty = atrebut['ObjectsRealty'] + for obj_realty in objects_realty: + if 'ObjectRealty' in obj_realty: + for obj in obj_realty['ObjectRealty']: + if 'InnerCadastralNumbers' in obj: + for inner_cad in obj['InnerCadastralNumbers']: + if 'CadastralNumber' in inner_cad: + for cad_num in inner_cad['CadastralNumber']: + if '#text' in cad_num: + connections.append(cad_num['#text']) + + # Для ОКС ищем ParentCadastralNumbers -> CadastralNumber + if 'ParentCadastralNumbers' in atrebut: + parent_cad = atrebut['ParentCadastralNumbers'] + for parent in parent_cad: + if 'CadastralNumber' in parent: + for cad_num in parent['CadastralNumber']: + if '#text' in cad_num: + connections.append(cad_num['#text']) + + return connections + + def get_access_info(self, atrebut): + """Получает сведения о доступе""" + access_info = [] + + if 'ProvidingPassCadastralNumbers' in atrebut: + providing_pass = atrebut['ProvidingPassCadastralNumbers'] + for provide in providing_pass: + # CadastralNumber + if 'CadastralNumber' in provide: + for cad_num in provide['CadastralNumber']: + if '#text' in cad_num: + access_info.append(f"Кадастровый номер: {cad_num['#text']}") + + # Definition + if 'Definition' in provide: + for definition in provide['Definition']: + if '#text' in definition: + access_info.append(f"Обозначение: {definition['#text']}") + + # Other + if 'Other' in provide: + for other in provide['Other']: + if '#text' in other: + access_info.append(f"Прочее: {other['#text']}") + + return access_info + def chec_object(self, atrebut): if '@attributes' in atrebut: if 'CadastralNumber' in atrebut['@attributes']: @@ -159,8 +279,16 @@ class super_visor(): def return_data(self): return self.data + def return_connections_data(self): + return self.connections_data + + def return_access_data(self): + return self.access_data + def __init__(self, xml): self.data = [] + self.connections_data = [] + self.access_data = [] i = 0 for section_name, section_data in xml.get('Package', [{}])[0].items(): for group in section_data: @@ -169,6 +297,7 @@ class super_visor(): for obj in item_list: if isinstance(obj, dict): if self.chec_object(obj): + # Основные данные self.data.append( Data_farame( section_KPTR=self.find_best_match(section_name), @@ -181,6 +310,33 @@ class super_visor(): explanations=self.chec_explanations(obj) ) ) + + # Обработка связей + connections = self.get_connections(obj) + for connection in connections: + self.connections_data.append( + Connection_Data( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(obj), + cadastral_quarter=self.chec_cad_block(obj), + object_type=self.chec_object_type(obj), + connection=connection + ) + ) + + # Обработка сведений о доступе (только для ЗУ) + if self.chec_object_type(obj) == "зу": + access_infos = self.get_access_info(obj) + for access_info in access_infos: + self.access_data.append( + Access_Data( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(obj), + cadastral_quarter=self.chec_cad_block(obj), + access_info=access_info + ) + ) + i += 1 if i == 785: pass @@ -189,6 +345,7 @@ class super_visor(): for real_obj in inner_items: if isinstance(real_obj, dict): if self.chec_object(real_obj): + # Основные данные self.data.append( Data_farame( section_KPTR=self.find_best_match(section_name), @@ -200,7 +357,33 @@ class super_visor(): availability_coordinates=self.chec_koordinat(real_obj), explanations=self.chec_explanations(real_obj) ) - ) + ) + + # Обработка связей + connections = self.get_connections(real_obj) + for connection in connections: + self.connections_data.append( + Connection_Data( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(real_obj), + cadastral_quarter=self.chec_cad_block(real_obj), + object_type=self.chec_object_type(real_obj), + connection=connection + ) + ) + + # Обработка сведений о доступе (только для ЗУ) + if self.chec_object_type(real_obj) == "зу": + access_infos = self.get_access_info(real_obj) + for access_info in access_infos: + self.access_data.append( + Access_Data( + section_KPTR=self.find_best_match(section_name), + cadastral_number=self.chec_kad_number(real_obj), + cadastral_quarter=self.chec_cad_block(real_obj), + access_info=access_info + ) + ) else: for inner_key, inner_items in obj.items(): for real_obj_real in inner_items: @@ -208,6 +391,7 @@ class super_visor(): test_item = real_obj_real[real_wtf][0] if self.chec_object(test_item): + # Основные данные self.data.append( Data_farame( section_KPTR=self.find_best_match(real_wtf), @@ -220,6 +404,32 @@ class super_visor(): explanations=self.chec_explanations(test_item) ) ) + + # Обработка связей + connections = self.get_connections(test_item) + for connection in connections: + self.connections_data.append( + Connection_Data( + section_KPTR=self.find_best_match(real_wtf), + cadastral_number=self.chec_kad_number(test_item), + cadastral_quarter=self.chec_cad_block(test_item), + object_type=self.chec_object_type(test_item), + connection=connection + ) + ) + + # Обработка сведений о доступе (только для ЗУ) + if self.chec_object_type(test_item) == "зу": + access_infos = self.get_access_info(test_item) + for access_info in access_infos: + self.access_data.append( + Access_Data( + section_KPTR=self.find_best_match(real_wtf), + cadastral_number=self.chec_kad_number(test_item), + cadastral_quarter=self.chec_cad_block(test_item), + access_info=access_info + ) + ) i += 1 if i == 785: pass @@ -258,11 +468,32 @@ class Parser(): def __init__(self, dir_xml=[], save_dir=""): xlsx_file = xlsx_filer(path=save_dir) + all_data = [] + all_connections_data = [] + all_access_data = [] + for item in dir_xml: - tree = etree.parse(item) - temp = self.lxml_to_dict(tree.getroot()) - new_data = super_visor(temp) - xlsx_file.data = new_data.return_data() - xlsx_file.path = save_dir + try: + tree = etree.parse(item) + temp = self.lxml_to_dict(tree.getroot()) + new_data = super_visor(temp) + all_data.extend(new_data.return_data()) + all_connections_data.extend(new_data.return_connections_data()) + all_access_data.extend(new_data.return_access_data()) + except Exception as e: + print(f"Ошибка при обработке файла {item}: {e}") + continue + + xlsx_file.data = all_data + xlsx_file.connections_data = all_connections_data + xlsx_file.access_data = all_access_data + xlsx_file.path = save_dir + + if all_data: xlsx_file.update_data() + if all_connections_data: + xlsx_file.update_connections_data() + if all_access_data: + xlsx_file.update_access_data() + xlsx_file.save_file() diff --git a/test_parsing.py b/test_parsing.py new file mode 100644 index 0000000..8fb7c37 --- /dev/null +++ b/test_parsing.py @@ -0,0 +1,26 @@ +import algam +import glob +import os + +# Путь к директории с XML файлами дополнительного задания +xml_dir = r"c:\Users\USER\Downloads\Доп.задание1" +save_dir = r"c:\Users\USER\Documents\git\kadastr12" + +def get_all_xml_files(directory): + """Возвращает список полных путей ко всем .xml файлам в директории""" + return glob.glob(os.path.join(os.path.abspath(directory), "*.xml")) + +# Получаем список XML файлов +xml_files = get_all_xml_files(xml_dir) +print(f"Найдено XML файлов: {len(xml_files)}") +for file in xml_files: + print(f" - {file}") + +# Запускаем парсер +try: + parser = algam.Parser(dir_xml=xml_files, save_dir=save_dir) + print("Парсинг завершен успешно!") +except Exception as e: + print(f"Ошибка при парсинге: {e}") + import traceback + traceback.print_exc()