wqeq
This commit is contained in:
BIN
kptr_table.xlsx
BIN
kptr_table.xlsx
Binary file not shown.
208
main.py
208
main.py
@@ -1,151 +1,83 @@
|
|||||||
import xml.etree.ElementTree as ET
|
|
||||||
import openpyxl
|
|
||||||
import glob
|
|
||||||
import os
|
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):
|
def has_spatial(elem):
|
||||||
"""Проверяет наличие тега SpatialElement в рамках элемента."""
|
return elem.find(".//SpatialElement") is not None
|
||||||
return "да" if elem.find(".//SpatialElement") is not None else "нет"
|
|
||||||
|
|
||||||
def get_explanation(elem):
|
def collect_explanations(elem):
|
||||||
"""Ищет пояснения в тегах Explanation, ExplanationSection, NameSection"""
|
return " ".join(e.text.strip() for e in elem.findall(".//Explanation") if e.text and e.text.strip())
|
||||||
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):
|
def process_section(tree, tag, label, records, is_zemel=True):
|
||||||
"""
|
section = tree.find(f".//{tag}")
|
||||||
В зависимости от тега-объекта извлекает данные для строки:
|
if section is None:
|
||||||
2. Раздел КПТР – устанавливается по тегу
|
return
|
||||||
3. Кадастровый номер
|
subtag = next(iter(section), None)
|
||||||
4. Кадастровый квартал
|
if subtag is None:
|
||||||
5. Вид объекта
|
return
|
||||||
6. Площадь ЗУ
|
for item in section.findall(f".//{subtag.tag}"):
|
||||||
7. Погрешность определения площади
|
rec = {
|
||||||
8. наличие координат
|
"Раздел КПТР": label,
|
||||||
9. Пояснения
|
"Кадастровый номер": extract_text(item, "CadastralNumber"),
|
||||||
"""
|
"Кадастровый квартал": extract_text(item, "CadastralBlock"),
|
||||||
if tag in {"NewParcel", "SpecifyParcel"}:
|
"Вид объекта": extract_text(item, "ObjectType"),
|
||||||
section = "FormParcels" if tag=="NewParcel" else "SpecifyParcels"
|
"Площадь ЗУ": extract_text(item.find("Area") or item, "Area") if is_zemel else "",
|
||||||
cadastral_number = elem.attrib.get("Definition", "")
|
"Погрешность определения площади": extract_text(item.find("Area") or item, "Inaccuracy") if is_zemel else "",
|
||||||
if cadastral_number.startswith(":"):
|
"наличие координат": "да" if has_spatial(item) else "нет",
|
||||||
cadastral_number = cadastral_number[1:]
|
"Пояснения": collect_explanations(item),
|
||||||
cadastral_block = (elem.findtext("CadastralBlock") or "").strip()
|
}
|
||||||
# Если внутри есть тег ObjectType – берем его, иначе для ЗУ фиксированное значение
|
records.append(rec)
|
||||||
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
|
def main():
|
||||||
sub = elem.find("CadastralErrorExistParcel")
|
records = []
|
||||||
if sub is None:
|
for file in os.listdir(FOLDER_WITH_XMLS):
|
||||||
return None
|
if not file.lower().endswith(".xml"):
|
||||||
section = "CadastralErrorsParcels"
|
continue
|
||||||
cadastral_number = sub.attrib.get("CadastralNumber", "")
|
xml_path = os.path.join(FOLDER_WITH_XMLS, file)
|
||||||
cadastral_block = (sub.findtext("CadastralBlock") or "").strip()
|
try:
|
||||||
area = (sub.findtext("Area/Area") or "").strip()
|
tree = ET.parse(xml_path)
|
||||||
inaccuracy = (sub.findtext("Area/Inaccuracy") or "").strip()
|
except ET.ParseError as e:
|
||||||
coords = has_spatial(sub)
|
print(f"❌ Ошибка в файле {file}: {e}")
|
||||||
explanation = get_explanation(sub)
|
continue
|
||||||
object_type = "Земельный участок"
|
|
||||||
return [None, section, cadastral_number, cadastral_block, object_type,
|
|
||||||
area, inaccuracy, coords, explanation]
|
|
||||||
|
|
||||||
elif tag == "ExistParcel":
|
root = tree.getroot()
|
||||||
# элемент имеет атрибут CadastralNumber
|
process_section(root, "FormParcels", "Образование ЗУ", records)
|
||||||
section = "ExistParcels"
|
process_section(root, "SpecifyParcels", "Уточнение ЗУ", records)
|
||||||
cadastral_number = elem.attrib.get("CadastralNumber", "")
|
process_section(root, "CadastralErrorsParcels", "Исправление ЗУ", records)
|
||||||
cadastral_block = (elem.findtext("CadastralBlock") or "").strip()
|
process_section(root, "ExistNewObjectsRealty", "Уточнение ОКС", records, is_zemel=False)
|
||||||
area = (elem.findtext("Area/Area") or "").strip()
|
process_section(root, "CadastralErrorsOKS", "Исправление ОКС", records, is_zemel=False)
|
||||||
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":
|
if not records:
|
||||||
section = "ExistNewObjectsRealty"
|
print("⚠️ Нет данных для экспорта.")
|
||||||
cadastral_number = (elem.findtext("CadastralNumber") or "").strip()
|
return
|
||||||
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/Area> или альтернативный тег
|
|
||||||
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":
|
for i, rec in enumerate(records, 1):
|
||||||
section = "CadastralErrorsOKS"
|
rec["№ п/п"] = i
|
||||||
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):
|
df = pd.DataFrame(records, columns=[
|
||||||
"""
|
"№ п/п",
|
||||||
Унифицированный итеративный парсинг.
|
"Раздел КПТР",
|
||||||
Обрабатываются объекты, у которых тег относится к:
|
"Кадастровый номер",
|
||||||
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:
|
df.to_excel(OUTPUT_XLSX_FILE, index=False)
|
||||||
row = extract_fields(elem, elem.tag)
|
print(f"✔️ Файл успешно сохранён: {OUTPUT_XLSX_FILE}")
|
||||||
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__":
|
if __name__ == "__main__":
|
||||||
# Папка с XML-файлами, измените при необходимости.
|
main()
|
||||||
main("./test", "kptr_table.xlsx")
|
|
||||||
|
|||||||
21
main1.py
Normal file
21
main1.py
Normal file
@@ -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")
|
||||||
@@ -4,4 +4,6 @@ version = "0.1.0"
|
|||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = []
|
dependencies = [
|
||||||
|
"bs4>=0.0.2",
|
||||||
|
]
|
||||||
|
|||||||
BIN
result.xlsx
Normal file
BIN
result.xlsx
Normal file
Binary file not shown.
57
uv.lock
generated
Normal file
57
uv.lock
generated
Normal file
@@ -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" },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user