多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

KML转SHP格式转换实战:坐标系、几何类型与字段编码避坑指南

KML转SHP格式转换实战:坐标系、几何类型与字段编码避坑指南 简介这份资源面向GIS专业师生及需要处理空间数据的非专业用户解决Google地球数字化得到的kml/kmz矢量无法直接在ArcGIS等平台使用的问题。包内共5个文件包含两个tbx自定义工具箱、一份Python源码脚本、一份安装指南PDF和一份操作演示PPT压缩包仅158KB轻量易分发。其中tbx可直接添加到ArcGIS自定义工具箱中双击运行py源码便于二次修改与学习转换逻辑PDF与PPT则辅助理解安装与使用流程。目前已有2717人学习下载说明该工具在kml转shp这一常见需求中具备较高实用性。读者可获得一套开箱即用的转换工具同时通过源码与文档理解基于ArcGIS Python的实现思路适合课程实验、项目数据预处理及日常空间数据格式转换场景。1. 从 KML 到 SHP为什么你导出的图层总在 ArcGIS 里“缺胳膊少腿”手里拿到一个kml格式转shp格式神器.zip多数人第一反应是双击解压、找个 exe 或脚本跑一下然后拖进 ArcGIS 看结果。但真正在一线干过 GIS 数据交付的人都清楚KML 和 SHP 之间隔着的不是一次格式转换而是两套完全不同的数据模型KML 是 Google Earth 生态里的 XML 描述语言天生带样式、带三维、带网络链接SHP 是 Esri 的经典矢量格式一个图层只能装一种几何类型属性字段名还被限制在 10 个字符以内。所以“神器”能不能用关键不在它转得快不快而在它有没有替你处理坐标系、几何类型拆分、字段截断和中文字段编码这几件事。这份资源适合手里有 Google Earth 标绘的路线、点位、行政区边界需要落到 ArcGIS 或 QGIS 里做统计、出图、入库的从业者如果你只是想把 KML 丢进 Google Earth 看一眼那完全没必要转。下面按“它是什么、怎么用、坑在哪”的顺序拆开讲中间会给出可抄作业的命令和参数。2. 先搞懂 KML、KMZ 与 SHP 的几何映射关系2.1 KML 的几何类型和 SHP 的“单类型”约束KML 里一个Placemark可以装Point、LineString、Polygon、MultiGeometry甚至一个文件里混着点、线、面。SHP 不行一个.shp只能是一种几何类型点图层、线图层、面图层必须分开存。这就是为什么很多人转完发现“点怎么跑到线图层里去了”——转换工具要么按第一个几何类型硬转要么直接丢弃不匹配的要素。常见做法是转换前先按几何类型把 KML 拆成多个文件或者选一个支持自动分层的工具。判断方法很简单用文本编辑器打开 KML搜Point、LineString、Polygon各出现多少次心里先有数。2.2 坐标系KML 永远是 WGS84 经纬度KML 规范强制使用 WGS84 地理坐标系单位是度。SHP 的.prj文件可以定义任意投影比如 CGCS2000 高斯克吕格、Web Mercator。转换时如果工具不写.prjArcGIS 会当成“未知坐标系”你后续做面积量算、距离统计全是错的。我一般会在转换后立刻用ogrinfo看一眼ogrinfo -al -so output.shp输出里Layer SRS如果是(unknown)就得手动补.prj。补的方法是用 QGIS 打开后“另存为”坐标系选EPSG:4326或者用gdalsrsinfo生成gdalsrsinfo EPSG:4326 -o wkt output.prj参数说明-o wkt输出 WKT 格式ArcGIS 和 QGIS 都认EPSG:4326就是 WGS84 经纬度。注意别直接拿一个空.prj糊弄字段内容不对照样报错。2.3 属性字段10 字符限制和中文字段名SHP 的 DBF 字段名最长 10 个字符超出部分会被截断而且不支持中文名。KML 的Data name...里经常是“路线名称”“采集时间”这种中文转换后要么变乱码要么变成Field1、Field2。常见做法是转换前先把 KML 里的字段名改成英文短名或者转换后用 QGIS 字段计算器重命名。如果工具支持映射表优先用映射表别指望自动识别。3. 用 GDAL/OGR 命令行完成 KML 转 SHP 的完整流程3.1 环境准备与版本确认这份kml格式转shp格式神器.zip里如果带的是 GDAL 封装工具底层多半还是ogr2ogr。先确认版本老版本对 KML 的MultiGeometry支持有差异ogr2ogr --version建议 GDAL 3.0 以上。如果输出是GDAL 2.x遇到复杂 KML 可能丢要素。Windows 下可以用 OSGeo4W 装macOS 用brew install gdalLinux 直接apt install gdal-bin。3.2 一条命令转点图层假设 KML 里全是点目标坐标系用 WGS84ogr2ogr -f ESRI Shapefile points.shp source.kml \ -nln points \ -a_srs EPSG:4326 \ -lco ENCODINGUTF-8逻辑说明-f ESRI Shapefile指定输出格式-nln points指定图层名避免默认用文件名导致中文乱码-a_srs EPSG:4326强制写入坐标系-lco ENCODINGUTF-8让 DBF 用 UTF-8 编码ArcGIS 10.2 以后能正常读中文。如果 KML 里混了几何类型这条命令只会转出第一种其余静默丢弃所以下一步必须做类型检查。3.3 按几何类型拆分再转先用ogrinfo看 KML 里有哪些几何类型ogrinfo -al -so source.kml输出里Geometry:会列出Point、Line String、Polygon等。然后分别转ogr2ogr -f ESRI Shapefile lines.shp source.kml \ -where OGR_GEOMETRYLineString \ -nln lines -a_srs EPSG:4326 -lco ENCODINGUTF-8 ogr2ogr -f ESRI Shapefile polygons.shp source.kml \ -where OGR_GEOMETRYPolygon \ -nln polygons -a_srs EPSG:4326 -lco ENCODINGUTF-8参数说明-where OGR_GEOMETRYLineString是 OGR 的几何类型过滤表达式注意大小写和引号嵌套LineString对应 KML 的LineStringPolygon对应Polygon。如果 KML 里是MultiGeometry包着线和面这个过滤可能失效需要先用ogr2ogr转成 GeoJSON 再处理或者用 QGIS 手动炸开。3.4 KMZ 的解压与直接读取KMZ 就是 ZIP 压缩的 KMLGDAL 可以直接读但有些版本需要先解压unzip source.kmz -d source_kmz ogr2ogr -f ESRI Shapefile output.shp source_kmz/doc.kml \ -a_srs EPSG:4326 -lco ENCODINGUTF-8注意 KMZ 里可能包含多个 KML 和图片资源doc.kml是主文件但名字不固定解压后先ls看一眼。如果工具包里的“神器”是图形界面这一步它应该自动做了但你要知道它背后干了什么出问题才能定位。4. 避坑与排查KML 转 SHP 最常见的五类翻车4.1 转完要素数量对不上现象KML 里明明有 200 个点SHP 属性表只有 150 条。原因KML 里有MultiGeometry或嵌套Folder工具只读了第一层。解决用ogrinfo -al source.kml | grep -c OGRFeature数一下原始要素数再和 SHP 对比如果不等改用 QGIS 的“按几何类型拆分”或先用ogr2ogr转 GeoJSON 再转 SHP。4.2 中文属性变问号或乱码现象ArcGIS 打开属性表“路线名称”显示成????。原因DBF 编码不是 UTF-8或者 ArcGIS 默认用系统编码读。解决转换时加-lco ENCODINGUTF-8如果已经转了用 QGIS 打开后“导出要素为”重新选 UTF-8ArcGIS 里可以用“转换坐标系”工具顺带重写编码但最稳的还是重转。4.3 坐标系丢失导致面积量算错误现象在 ArcGIS 里算面积结果单位是“平方度”数值小得离谱。原因.prj缺失或写错。解决用gdalsrsinfo EPSG:4326 -o wkt output.prj补上如果要做面积统计建议转成投影坐标系比如EPSG:4547CGCS2000 3 度带命令里把-a_srs换成-t_srs EPSG:4547让 GDAL 自动做投影变换。4.4 字段名被截断后无法识别现象KML 里“采集时间”变成Field1“采集人”变成Field2。原因SHP 字段名 10 字符限制加中文不支持。解决转换前用文本编辑器批量替换 KML 里的Data name采集时间为Data namecollect_t或者转换后在 QGIS 里用“重构字段”重命名。别在 ArcGIS 里直接改容易把 DBF 写坏。4.5 大文件转换卡死或内存溢出现象几百 MB 的 KML 转 SHP 时工具无响应。原因KML 是 XMLDOM 解析吃内存。解决先用ogr2ogr加-skipfailures跳过错误要素或者用-limit分批转更稳的做法是先用ogr2ogr转成 GeoPackage.gpkg再从 GPKG 转 SHPGPKG 对大数据量友好得多。ogr2ogr -f GPKG temp.gpkg source.kml -a_srs EPSG:4326 ogr2ogr -f ESRI Shapefile output.shp temp.gpkg -lco ENCODINGUTF-85. 进阶批量转换、字段映射与 QGIS 统计路线公里数5.1 批量转换多个 KML/KMZ手里有几十个 KML 要转一个个敲命令不现实。写个 bash 循环for f in *.kml *.kmz; do base${f%.*} ogr2ogr -f ESRI Shapefile ${base}.shp $f \ -a_srs EPSG:4326 -lco ENCODINGUTF-8 -skipfailures done逻辑说明${f%.*}去掉扩展名作为输出名-skipfailures保证单个文件出错不中断整个批次。如果 KMZ 需要先解压在循环里加unzip -o $f -d ${base}_tmp再转${base}_tmp/doc.kml。注意输出目录别和输入混在一起否则下一轮循环会把.shp也当输入。5.2 字段映射把 KML 的 Data 转成规范字段KML 的Data name...在 OGR 里会变成属性字段但名字可能带空格或特殊字符。转换前用 Python 的xml.etree批量重命名import xml.etree.ElementTree as ET tree ET.parse(source.kml) ns {kml: http://www.opengis.net/kml/2.2} for data in tree.iter({http://www.opengis.net/kml/2.2}Data): name data.get(name) if name 路线名称: data.set(name, route_name) elif name 采集时间: data.set(name, collect_t) tree.write(source_fixed.kml, encodingutf-8, xml_declarationTrue)参数说明ns是 KML 的命名空间iter遍历所有Data节点data.set(name, ...)直接改属性名。改完再走ogr2ogr字段名就规范了。注意备份原文件别直接覆盖。5.3 在 QGIS 里统计 KML 路线公里数转成 SHP 后用 QGIS 打开线图层字段计算器新建字段length_km表达式length(transform($geometry, EPSG:4326, EPSG:4547)) / 1000逻辑说明transform把 WGS84 经纬度转成 CGCS2000 3 度带投影单位是米length算长度除以 1000 得公里。如果线图层是MultiLineString先用“多部件转单部件”炸开否则长度会算成整个多部件的总和。这一步是很多做路线统计的人卡住的地方——直接对经纬度算长度结果单位是度毫无意义。5.4 验证转换结果是否可用转完别急着关工具做三件事第一用ogrinfo -al -so output.shp看要素数和几何类型第二在 QGIS 里叠加 Google Satellite 或天地图底图看位置对不对第三打开属性表确认中文字段和数值字段没乱。我自己的习惯是每次转完都跑一遍ogrinfo确认Feature Count和原始 KML 的Placemark数量一致不一致就回头查MultiGeometry。从那以后我每次拿到 KML 都先数一遍几何类型再动手省得返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表