尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

矢量篇 - KMLKMZ转SHP

矢量篇 - KMLKMZ转SHP
📅 发布时间:2026/6/18 19:27:54

@ 20240908 & lth
目标:从kml或kmz带属性转成shp
逻辑:主要是对kml的description字段的处理,他的格式是html的
image
image

目前我搜了一下没有现成的工具,要想将kml带属性转成shp,我这里工具选的是fme或python
用fme的话,关键点就是StringSearcher转换器,(?<=<td>).+?(?=</td>),然后用AttributeExposer暴露出来把获取的字段

image
image

用python的话,关键点就是对description字段的处理
import xml.etree.ElementTree as ET
import os
from osgeo import ogrdef parse_kml_description(html_content):"""解析 KML description 字段中的 HTML 表格,提取属性字典。参数:html_content (str): 描述字段的 HTML 内容(如 '<table>...</table>')返回:dict: 提取的属性字典,例如 {'bh': '40339', 'name': '831774/2023', 'FID': '40338'}"""# 尝试修复不完整的 HTML(比如缺少根标签)if not html_content.strip().startswith('<table'):# 查找第一个 <table> 开始位置start = html_content.find('<table')end = html_content.find('</table>')if start == -1 or end == -1:return {}html_content = html_content[start:end + 8]  # 截取完整 tabletry:# 使用 XML 解析器解析 HTML 表格root = ET.fromstring(html_content)# 如果根节点不是 <table>,尝试找子节点中的 <table>if root.tag != 'table':table = root.find('.//table')if table is not None:root = tableelse:return {}attr_dict = {}# 遍历所有表格行for row in root.findall('.//tr'):ths = row.findall('th')tds = row.findall('td')if len(ths) > 0 and len(tds) > 0:key = ths[0].textvalue = tds[0].textif key:  # 确保字段名不为空attr_dict[key.strip()] = value.strip() if value else ''return attr_dictexcept ET.ParseError as e:print(f"HTML 解析失败: {e}")return {}def convert_kml_to_shp(in_file, out_file):"""将 KML 文件转换为 Shapefile,并从 description 中提取嵌套属性。参数:in_file (str): 输入 KML 文件路径。out_file (str): 输出 SHP 文件路径。"""# 打开输入 KML 文件ds_in = ogr.Open(in_file)if ds_in is None:print(f"无法打开输入文件:{in_file}")returnlayer = ds_in.GetLayer(0)srs = layer.GetSpatialRef()  # 获取空间参考# 创建输出 Shapefiledriver = ogr.GetDriverByName('ESRI Shapefile')# 删除已存在的输出文件(OGR 不会自动覆盖)if os.path.exists(out_file):driver.DeleteDataSource(out_file)ds_out = driver.CreateDataSource(out_file)if ds_out is None:print(f"无法创建输出文件:{out_file}")return# 获取输入图层定义layer_defn = layer.GetLayerDefn()geom_type = layer_defn.GetGeomType()# 创建输出图层(暂时无字段,后面动态添加)layer_out = ds_out.CreateLayer('output', srs=srs, geom_type=geom_type)# 存储已创建的字段名,避免重复创建created_fields = set()# === 第一步:遍历所有要素,提取 description 中的所有唯一字段名 ===print("正在扫描所有要素以提取字段...")all_attributes = set()features_data = []  # 临时存储每个要素的 geometry 和属性字典for feat_in in layer:desc = feat_in.GetField('description')  # 获取 description 字段if desc is not None:attrs = parse_kml_description(desc)all_attributes.update(attrs.keys())features_data.append({'geometry': feat_in.GetGeometryRef().Clone(),'attributes': attrs})else:features_data.append({'geometry': feat_in.GetGeometryRef().Clone(),'attributes': {}})# === 第二步:根据提取出的所有字段,创建 Shapefile 的字段 ===print(f"发现以下属性字段: {sorted(all_attributes)}")for field_name in sorted(all_attributes):# 检查字段名是否合法(Shapefile 字段名不能太长,且只能用字母数字下划线)safe_name = field_name.strip()if not safe_name.isidentifier():safe_name = ''.join(c if c.isalnum() or c == '_' else '_' for c in safe_name)if len(safe_name) > 10:  # Shapefile 字段名最多 10 字符safe_name = safe_name[:10]# 避免重复if safe_name not in created_fields:field_defn = ogr.FieldDefn(safe_name, ogr.OFTString)field_defn.SetWidth(254)layer_out.CreateField(field_defn)created_fields.add(safe_name)# 获取输出图层的要素定义feat_defn = layer_out.GetLayerDefn()# === 第三步:写入所有要素 ===for data in features_data:feat_out = ogr.Feature(feat_defn)feat_out.SetGeometry(data['geometry'])# 填充从 description 中提取的属性for key, value in data['attributes'].items():safe_key = key.strip()if not safe_key.isidentifier():safe_key = ''.join(c if c.isalnum() or c == '_' else '_' for c in safe_key)if len(safe_key) > 10:safe_key = safe_key[:10]if safe_key in created_fields:feat_out.SetField(safe_key, value)layer_out.CreateFeature(feat_out)feat_out = None  # 释放内存# 清理ds_out = Noneds_in = Noneprint(f"✅ 转换完成!已将 {len(features_data)} 个要素写入 {out_file}")
插入一个打包的知识点用Nuitka比pyinstaller要好很多,生成的exe要小很多大概是5倍,然后要注意的是pyqt5不太兼容Nuitka

image

相关新闻

  • js空值合并运算符?? - jerry
  • ubuntu上通过kvm新建虚拟机
  • 关于USB 无线 WIF 设备驱动安装的问题

最新新闻

  • 2026年AI论文软件推荐:9款高效AI工具终极指南
  • 武汉健身器材上门安装维修推荐良匠千艺 2026 口碑榜 - 我叫一
  • 如何5分钟配置完成:Translumo终极实时屏幕翻译工具快速上手指南
  • 2026年市南区专业的蹲便疏通公司推荐榜单 - 品牌排行榜
  • 三维雷达仿真技术:从原理到实践,构建高保真数字雷达试验场
  • 2026年当下,四川地区优异的扇形淋浴房改造服务深度解析 - 品牌鉴赏官2026

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号