基于GDAL/OGR命令行工具实现表格到KML等矢量格式的转换

目录

1.需求分析

2.为什么要用命令行

3.转换方法 

3.1读取文件信息

3.2通过CSV格式中转

3.3直接用Excel转换

3.4关于ShapeFile的转换

4.总结


1.需求分析

在测绘和地理信息系统(GIS)项目中,数据来源多样,包括野外采集的数据以及来自第三方的数据。这些数据有时以表格形式提供,例如 Excel 表格或 CSV 文件。然而,为了进行空间分析、制图和其他 GIS 操作,通常需要将这些表格数据转换为矢量数据格式(如Shapefile或KML)。这种转换不仅使数据能够更好地集成到现有的地理信息系统中,还便于进一步的空间处理和可视化,从而支持各类项目的顺利实施。

GDAL(Geospatial Data Abstraction Library)是强大的开源GIS程序库,广泛用于处理和转换各种地理空间数据格式,其支持读或者写的矢量数据格式就达到了80多种。本文主要讲述利用GDAL/OGR工具将Excel表格(xlsx)转换为矢量数据(kml,shp)的方法,中间会穿插讲述怎么将CSV表格转换为矢量数据的方法。

本文对于没有信息技术工作经验者来说,阅读起来可能有点费力。本文的矢量数据文件均为点状矢量文件,面状、线状的数据的转换更加复杂,这里暂时不介绍。

如果时间有限,无法详细阅读整个过程,可以直接跳至第4节获取转换方法的最佳实践。


2.为什么要用命令行

市面上有许多成熟的GIS软件(如ArcGIS、QGIS等)能够实现表格转矢量文件的功能,但使用GDAL/OGR工具进行此类操作仍有其独特的优势和应用场景。比如以下场景:

(1)批量处理时,gdal/ogr命令行程序有较大优势。

(2)服务器执行定时任务时,gdal/ogr命令行程序比较方便。

(3)桌面GIS软件的启动速度往往较慢,gdal/ogr命令行程序启动很快。

(4)在对计算机处理数据性能要求较高的情况下,gdal/ogr命令行程序有优势。

(5)命令行程序的参数可以用配置文件输入,桌面GIS软件有类似功能,设置起来较麻烦。

(6)适合开发者使用。

以上仅仅是作者的经验之谈。 在处理少量简单数据时,各类桌面GIS软件也很好用。


3.转换方法 

转换主要用到了ogrinfo和ogr2ogr两个命令。这里主要介绍转换为kml的方法,最后会给出转换为Shapefile的方法。这两种格式的数据在GIS领域有着广泛的应用,这里不再赘述。值得注意的是,不论是那种数据格式的转换,都应该认真阅读gdal的官方文档,因为转换不同格式的数据执行的参数有较大的差异。

下面的命令行代码是基于windows系统的cmd写的,gdal的版本是3.2。如果是linux或者mac平台,代码略有差异。

3.1读取文件信息

已知我们有一个名叫部分世界著名景点.xlsx的Excel表格,它是由WPS Office编辑录入的,以下是数据的预览:

工作簿有2个工作表(sheet),分别是西欧和北美,里面存放的是世界知名景点的信息及经纬度。

因为后续数据转换涉及到指定空间数据字段和属性字段,所以我们要使用ogrinfo程序读取这个表格,观察其在OGR中是的表现形式。windows系统的简体中文版默认字符集一般是GBK。为了能用ogr程序处理中文,我们在运行时需要切换到UTF-8的字符集。

切换字符集为UTF-8,需要在cmd窗口执行以下代码。

chcp 65001

然后切换到表格所在父目录(这一步省略),指定读取Excel文档的代码,-where "fid <=2 "的作用是只读取前3行,避免数据过多的显示在屏幕上。

ogrinfo -al -where "fid <=2 " 部分世界著名景点.xlsx

 以下是部分截图:

“西欧”图层的信息
“北美”图层的信息

从上述信息中,我们可以发现:

Layer Name指的是Excel工作表中的不同表格,在这个例子中有两个图层,分别是“西欧”和“北美”。OGR将Excel的工作表作为图层来读取处理。由于这些Excel工作表不包含任何空间信息,因此Geometry显示为“None”,相应的Layer SRS WKT(图层空间参考系统WKT)也为空。

接下来的部分列出了6个属性字段及其数据类型,这里就不详细展开解释了。每条OGRFeature对应于工作表中的一行记录;如果某行记录的某个属性值为空,则该属性不会出现在对应的要素属性列表中。

根据GDAL文档关于xlsx驱动打开参数的描述,直接通过打开参数将xlsx格式的数据转换成OGR支持的空间数据格式是不行的。然而,对于CSV驱动,文档中记录了X_POSSIBLE_NAMES、Y_POSSIBLE_NAMES和Z_POSSIBLE_NAMES等参数选项,这意味着可以通过先将xlsx文件转换为CSV文件,然后再利用ogr2ogr工具,将CSV文件转换为KML或ESRI Shapefile等空间数据格式。

3.2通过CSV格式中转

首先将xlsx转为cvs格式,由于ogr中所有的csv文件都被默认为UTF-8编码的文件来处理,这里用到了-lco WRITE_BOM=YES是使用UTF-8 BOM编码,是为了和Excel办公软件兼容。如果要用Excel编辑保存csv文档,则需要另存为UTF-8格式的csv文档。

ogr2ogr -f "CSV" 西欧.csv 部分世界著名景点.xlsx 西欧 -lco WRITE_BOM=YES
ogr2ogr -f "CSV" 北美.csv 部分世界著名景点.xlsx 北美 -lco WRITE_BOM=YES

利用csv的打开时的参数,将经纬度转换为图层中空间属性(Geometry)。这里没有指定Z坐标,如果需要,可以加上Z_POSSIBLE_NAMES参数。

ogr2ogr -f 输出格式的驱动名称 输出文件的路径  输入文件的路径 -oo X_POSSIBLE_NAMES=x坐标字段名称 -oo Y_POSSIBLE_NAMES=y坐标字段名称 -dsco NameField=kml图层Name的字段 -dsco DescriptionField=kml图层Description的字段

ogr2ogr -f "KML" 部分世界著名景点(西欧).kml 西欧.csv -oo X_POSSIBLE_NAMES=经度 -oo Y_POSSIBLE_NAMES=纬度 -dsco NameField=名称 -dsco DescriptionField=英文名称

上述命令会将CSV所有的属性都添加到目标图层,如果需要过滤部分字段,比较简单的情况可以用select来过滤,如果过滤行可以用-where参数。更复杂的情况,如需要拼接字段,可以通过执行SQL语句来实现。

ogr2ogr -f "KML" 部分世界著名景点(西欧).kml 西欧.csv -oo X_POSSIBLE_NAMES=经度 -oo Y_POSSIBLE_NAMES=纬度 -dsco NameField=名称 -dsco DescriptionField=英文名称 -select "名称,英文名称,坐落"

这里,会将源文件图层的“名称”,“英文名称”,“坐落”列输出,且将“名称”,“英文名称”分别映射到Name和Description。

在命令窗口写SQL比较麻烦,因为SQL中很多保留字和系统命令冲突,这会需要大量的转义字符,降低了可维护性。更加复杂的情况可以通过虚拟格式(VRT)文件来实现将配置数据都写在xml里面,这样会使得命令行很简单,比较容易维护。

我们编写一个vrt为后缀名的xml文档如下

<OGRVRTDataSource>
    <OGRVRTLayer name="西欧">
        <SrcDataSource>西欧.csv</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="经度" y="纬度"/>
		<Field name="Name" src="名称" type="String"/>
        <Field name="Description" src="英文名称" type="String"/>
        <Field name="坐落" src="坐落" type="String"/>
        <Field name="lon" src="经度" type="String"/>
        <Field name="lat" src="纬度" type="String"/>
    </OGRVRTLayer>
</OGRVRTDataSource>

执行下列命令,就可以实现转换。虽然在vrt中指定了图层坐标系为EPSG4490,但输出的KML文件坐标系还EPSG4326,这是ogr写KML文件的默认行为,3.2版本没有参数可以调整这个行为。 

ogr2ogr -f "KML" 部分世界著名景点(西欧).kml 西欧.csv.vrt

 以下是在vrt文件使用SQL语句来实现转换的例子,这里不需要转义SQL。

<OGRVRTDataSource>
    <OGRVRTLayer name="西欧">
        <SrcDataSource>西欧.csv</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="lon" y="lat"/>
		<SrcSQL dialect="SQLite">
            SELECT (名称 || ' ' || 英文名称) AS Name,
			坐落 AS Description,经度 AS lon,纬度 AS lat FROM 西欧
        </SrcSQL>
    </OGRVRTLayer>
</OGRVRTDataSource>

以下是多个图层写入目标文件的例子

ogr2ogr -f "KML" 部分世界著名景点.kml 西欧.csv.vrt
ogr2ogr -f "KML" 部分世界著名景点.kml -append 北美.csv.vrt

3.3直接用Excel转换

虽然直接通过打开参数将xlsx格式的数据转换成OGR支持的空间数据格式是不行的,但是可以通过SQL语句实现,或者在vrt文件的<GeometryField>标签中指定x、y、z属性实现。

ogr2ogr -f "KML" 部分世界著名景点(西欧)-x.kml.kml 部分世界著名景点.xlsx -dialect sqlite -sql "SELECT \"名称\" AS Name, \"英文名称\" AS Description,ST_GeomFromText(wktStr) as geom FROM (SELECT 'POINT('||\"经度\" ||' '||\"纬度\"||')' AS wktStr,*  FROM \"西欧\")" -nln 西欧

 这个是在cmd中执行SQL语句转换Excel为kml的方式,用到了SQLitef方言和ST_GeomFromText函数,由于有大量的转义字符,可维护性不好,不建议使用。

以下是推荐使用的方式,它可以实现在一个vrt中指定配置数据后,通过一行简洁的代码转换Excel到kml文件。值得注意的是使用SQL语句时,GeometryField中的x、y属性必须是SQL语句的查询结果中的字段。

<OGRVRTDataSource>
    <OGRVRTLayer name="西欧">
        <SrcDataSource>部分世界著名景点.xlsx</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="lon" y="lat"/>
		<SrcSQL dialect="SQLite">
            SELECT 名称 AS Name,坐落 AS Description,经度 AS lon,纬度 AS lat FROM 西欧
        </SrcSQL>
    </OGRVRTLayer>
    <OGRVRTLayer name="北美">
        <SrcDataSource>部分世界著名景点.xlsx</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="经线" y="纬线"/>
		<Field name="Name" src="名称" type="String"/>
        <Field name="Description" src="英文名称" type="String"/>
    </OGRVRTLayer>
</OGRVRTDataSource>
ogr2ogr -f "KML" 部分世界著名景点.kml 部分世界著名景点.xlsx.vrt

 部分世界著名景点.xlsx.vrt是上述xml的文件名称,也是相对路径。这是一个多图层的例子,删除一个OGRVRTLayer,就是单个图层的例子。

3.4关于ShapeFile的转换

前面讲述了怎么用表格文件转换为KML文件,是因为作者个人觉得写kml数据对于理解ogr写矢量文件更有帮助。因为ShapeFile在ogr中是单图层的,且属性长度有限制。但是日常项目中有大量的ShapeFile数据,所以有必要写一下它的转换方法。

首先介绍一下CSV转换ShapeFile,这里介绍的方法基本与转为kml一样。所不同的是,ogr写ESRI ShapeFile时,默认字符集是LDID/87,为了兼容中文,建议设置为UTF-8;还有一点是,需要通过-a_srs 参数指定坐标系,否则输出的ShapeFile不带坐标系。

ogr2ogr -f "ESRI Shapefile" 部分世界著名景点(西欧).shp 西欧.csv -oo X_POSSIBLE_NAMES=经度 -oo Y_POSSIBLE_NAMES=纬度 -lco ENCODING=UTF-8 -a_srs EPSG:4490

 接下来是Excel转换ShapeFile,编写如下vrt文件

<OGRVRTDataSource>
    <OGRVRTLayer name="西欧">
        <SrcDataSource>部分世界著名景点.xlsx</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="lon" y="lat"/>
		<SrcSQL dialect="SQLite">
            SELECT 名称 AS Name,坐落 AS Description,经度 AS lon,纬度 AS lat FROM 西欧
        </SrcSQL>
    </OGRVRTLayer>
</OGRVRTDataSource>

也可以是这样的vrt文件: 

<OGRVRTDataSource>
    <OGRVRTLayer name="北美">
        <SrcDataSource>部分世界著名景点.xlsx</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>EPSG:4490</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="经线" y="纬线"/>
		<Field name="Name" src="名称" type="String"/>
        <Field name="Description" src="英文名称" type="String"/>
    </OGRVRTLayer>
</OGRVRTDataSource>

 执行的转换代码中需要带上字符集设置、坐标系设置的有关参数。

ogr2ogr -f "ESRI Shapefile" 部分世界著名景点(西欧).shp 部分世界著名景点.xlsx.vrt -lco ENCODING=UTF-8 -a_srs EPSG:4490

由于“Description”超过了10个字节,作为字段名时,会被ogr截断。使用中文字段名也会面临这个情况,在UTF-8编码中,最多只能写3个汉字作为字段名。


4.总结

在利用GDAL/OGR命令行工具进行表格数据到矢量文件的转换时,存在多种方法,具体操作细节也较多。其中最佳实践是将字段映射及其他配置信息写入一个虚拟格式(VRT)文件中,然后再通过ogr2ogr命令行工具进行转换。这种方法特别适用于处理复杂的转换需求,在文档的3.3节和3.4节中有详细描述。然而,在转换任务相对简单的情况下,可以直接在命令行中输入必要的参数完成转换。例如,直接指定源文件路径、目标格式和其他基本选项即可。

在实际生产环境中,选择哪种方法应根据具体需求进行分析。对于复杂的数据转换任务,使用VRT文件能够提高效率并减少错误;而对于简单的转换任务,直接在命令行中指定参数则更加便捷。总之,结合实际需求选择最合适的方法,可以确保数据转换过程高效准确。

转换后的矢量数据的可视化表达

 

附件:本文实验数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我一时想不起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值