diff --git a/kptr_table.xlsx b/kptr_table.xlsx index bc19b55..48610c6 100644 Binary files a/kptr_table.xlsx and b/kptr_table.xlsx differ diff --git a/main.py b/main.py index 4153ed9..65abcea 100644 --- a/main.py +++ b/main.py @@ -1,151 +1,83 @@ -import xml.etree.ElementTree as ET -import openpyxl -import glob import os +import xml.etree.ElementTree as ET +import pandas as pd +from pathlib import Path -HEADERS = [ - "№ п/п", - "Раздел КПТР", - "Кадастровый номер", - "Кадастровый квартал", - "Вид объекта", - "Площадь ЗУ", - "Погрешность определения площади", - "наличие координат", - "Пояснения" -] +# === 🔧 НАСТРОЙКИ (меняйте под себя) === +FOLDER_WITH_XMLS = r"C:\Users\jze9\Documents\work\git\kadastr12\test" # Папка с XML-файлами +OUTPUT_XLSX_FILE = r"C:\Users\jze9\Documents\work\git\kadastr12\result.xlsx" # Куда сохранить результат + +# === ⛏ ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ === +def extract_text(elem, tag): + node = elem.find(f".//{tag}") + return node.text.strip() if node is not None and node.text else "" def has_spatial(elem): - """Проверяет наличие тега SpatialElement в рамках элемента.""" - return "да" if elem.find(".//SpatialElement") is not None else "нет" + return elem.find(".//SpatialElement") is not None -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 collect_explanations(elem): + return " ".join(e.text.strip() for e in elem.findall(".//Explanation") if e.text and e.text.strip()) -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] +def process_section(tree, tag, label, records, is_zemel=True): + section = tree.find(f".//{tag}") + if section is None: + return + subtag = next(iter(section), None) + if subtag is None: + return + for item in section.findall(f".//{subtag.tag}"): + rec = { + "Раздел КПТР": label, + "Кадастровый номер": extract_text(item, "CadastralNumber"), + "Кадастровый квартал": extract_text(item, "CadastralBlock"), + "Вид объекта": extract_text(item, "ObjectType"), + "Площадь ЗУ": extract_text(item.find("Area") or item, "Area") if is_zemel else "", + "Погрешность определения площади": extract_text(item.find("Area") or item, "Inaccuracy") if is_zemel else "", + "наличие координат": "да" if has_spatial(item) else "нет", + "Пояснения": collect_explanations(item), + } + records.append(rec) - 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] +# === 🚀 ОСНОВНОЙ КОД === +def main(): + records = [] + for file in os.listdir(FOLDER_WITH_XMLS): + if not file.lower().endswith(".xml"): + continue + xml_path = os.path.join(FOLDER_WITH_XMLS, file) + try: + tree = ET.parse(xml_path) + except ET.ParseError as e: + print(f"❌ Ошибка в файле {file}: {e}") + continue - 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] + root = tree.getroot() + process_section(root, "FormParcels", "Образование ЗУ", records) + process_section(root, "SpecifyParcels", "Уточнение ЗУ", records) + process_section(root, "CadastralErrorsParcels", "Исправление ЗУ", records) + process_section(root, "ExistNewObjectsRealty", "Уточнение ОКС", records, is_zemel=False) + process_section(root, "CadastralErrorsOKS", "Исправление ОКС", records, is_zemel=False) - 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] + if not records: + print("⚠️ Нет данных для экспорта.") + return - 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 + for i, rec in enumerate(records, 1): + rec["№ п/п"] = i -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}") + df = pd.DataFrame(records, columns=[ + "№ п/п", + "Раздел КПТР", + "Кадастровый номер", + "Кадастровый квартал", + "Вид объекта", + "Площадь ЗУ", + "Погрешность определения площади", + "наличие координат", + "Пояснения", + ]) + df.to_excel(OUTPUT_XLSX_FILE, index=False) + print(f"✔️ Файл успешно сохранён: {OUTPUT_XLSX_FILE}") if __name__ == "__main__": - # Папка с XML-файлами, измените при необходимости. - main("./test", "kptr_table.xlsx") \ No newline at end of file + main() diff --git a/main1.py b/main1.py new file mode 100644 index 0000000..697b2a8 --- /dev/null +++ b/main1.py @@ -0,0 +1,21 @@ +import xml.etree.ElementTree as ET +from bs4 import BeautifulSoup + +def open_file(file_path): + + + + with open(file_path, 'r') as f: + data = f.read() + Bs_data = BeautifulSoup(data, "xml") + b_unique = Bs_data.find_all('unique') + + print(b_unique) + b_name = Bs_data.find('child', {'name':'Frank'}) + + print(b_name) + value = b_name.get('test') + + print(value) + +open_file("C:/Users/jze9/Documents/work/git/kadastr12/test/MapPlanTerritory_E2DF5B75-E136-48DA-BB4C-8887BA4ABF46.xml") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 3bddc4e..b55ad02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,4 +4,6 @@ version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" -dependencies = [] +dependencies = [ + "bs4>=0.0.2", +] diff --git a/result.xlsx b/result.xlsx new file mode 100644 index 0000000..0b107d4 Binary files /dev/null and b/result.xlsx differ diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..0336edc --- /dev/null +++ b/uv.lock @@ -0,0 +1,57 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "beautifulsoup4" +version = "4.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, +] + +[[package]] +name = "bs4" +version = "0.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/aa/4acaf814ff901145da37332e05bb510452ebed97bc9602695059dd46ef39/bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925", size = 698, upload-time = "2024-01-17T18:15:47.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/bb/bf7aab772a159614954d84aa832c129624ba6c32faa559dfb200a534e50b/bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc", size = 1189, upload-time = "2024-01-17T18:15:48.613Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, +] + +[[package]] +name = "test12" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "bs4" }, +] + +[package.metadata] +requires-dist = [{ name = "bs4", specifier = ">=0.0.2" }] + +[[package]] +name = "typing-extensions" +version = "4.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, +]