GML全称为Geography Markup Language,是由开放地理空间联盟(OGC)制定的一种基于XML的地理信息编码规范。它用统一的文本结构描述现实世界中的空间要素,包括它们的几何形状、空间参考、属性信息以及要素之间的关系。理解GML,关键在于把它看作“用XML写成的地图数据字典”,而不是某款软件专属的文件格式。

在GML出现之前,不同GIS平台往往使用封闭的二进制或专有文本格式存储数据,导致数据交换时要做大量格式转换,容易丢失坐标系或属性语义。GML通过XML的可读性与自描述特性,把“在哪里”和“是什么”写进同一份文档,任何支持XML的工具都能解析基础结构,再由GML的Schema进一步校验地理语义。
GML的核心设计思想
GML的设计建立在三个基础概念上:要素(Feature)、几何(Geometry)和属性(Property)。要素是现实对象的抽象,例如一栋建筑、一条河流;几何描述要素的空间形态,如点、线、面;属性则承载非空间信息,如名称、高度、建成年代。这种分离让同一套几何可以被多个要素复用,也方便在不变更几何的情况下扩展业务字段。
与单纯把坐标写成标签不同,GML要求明确空间参考系统。通过在根节点或几何元素上声明srsName属性,消费方能够知道坐标基于哪个坐标系,避免经纬度与投影坐标混淆。下面的片段展示了一个带EPSG编码的点要素:
<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<gml:featureMember>
<MyBuilding gml:id="bldg_01">
<gml:name>示例科技楼</gml:name>
<gml:position>
<gml:Point srsName="urn:ogc:def:crs:EPSG::4326">
<gml:pos>116.397 39.908</gml:pos>
<gml:Point>
<gml:position>
<height>58.5</height>
<MyBuilding>
<gml:featureMember>
<gml:FeatureCollection>
上面的代码虽然简化,但体现了GML的典型写法:用命名空间区分基础几何与业务要素,用srsName锁定坐标系,用嵌套元素表达属性。由于全部是文本,调试时可直接用浏览器或编辑器查看,也易于通过XSLT转为其他表现层格式。
GML与普通XML的区别
很多初学者会问,既然GML就是XML,为什么不直接自己写标签?核心差异在于约束与语义。普通XML只保证“良构”,而GML提供了一套标准的Schema(如gml.xsd),规定了哪些几何类型合法、坐标顺序如何、拓扑如何表达。遵循GML的文档可以被任意兼容OGC的服务识别,而随意定义的XML只能自己解析。
另外,GML在几何表达上支持曲线、曲面、复合几何以及拓扑关系,这些都不是基础XML能天然表达的。比如用gml:LineString描述道路中心线,用gml:Polygon描述地块,用gml:Topology表达相邻关系,都是OGC预先定义好的结构。下表列出常见几何类型与含义:
| 几何类型 | 说明 | 典型场景 |
|---|---|---|
| Point | 零维坐标点 | 井盖、信号灯位置 |
| LineString | 有序坐标连线 | 道路、管线走向 |
| Polygon | 闭合面状区域 | 行政区、地块边界 |
| MultiGeometry | 多种几何集合 | 岛屿群、分散设施 |
从表中可以看出,GML的几何体系覆盖了大多数二维GIS需求。如果需要在三维场景使用,GML还扩展了gml:Surface与gml:Solid,用以表达建筑外立面或体量,只是文档复杂度会明显上升。
如何使用GML进行数据交换
在实际项目中,GML常作为Web服务的中间格式。例如OGC的WFS(Web Feature Service)就以GML返回查询要素,客户端解析后转成内部对象。下面用Python演示如何读取一份GML并提取点坐标:
import xml.etree.ElementTree as ET
# 解析GML文本
tree = ET.parse('sample.gml')
root = tree.getroot()
# 定义命名空间
ns = {'gml': 'http://www.opengis.net/gml/3.2'}
# 查找所有Point
for point in root.findall('.//gml:Point', ns):
srs = point.get('srsName')
pos = point.find('gml:pos', ns).text
print('坐标系:', srs, '坐标:', pos)
这段代码利用标准库解析XML,通过命名空间定位GML元素。在真实系统里,你可能会用GDAL/OGR或GeoPandas,它们对GML的Schema校验更完善,能自动处理坐标反转、多维几何等情况。但若只做轻量提取,上面的方式已经足够直观。
需要注意,GML文件体积通常比二进制格式大,网络传输时应开启压缩。另外,由于XML解析存在实体扩展风险,处理外部来源的GML时要禁用不安全实体,防止恶意文档消耗内存。
GML的适用场景与局限
GML非常适合需要长期归档、跨组织共享或作为标准接口载体的场景,比如国土调查数据汇交、城市基础地理信息库对外服务。它的开放特性让数据在十年后依然可被新系统读取,不会绑定某家厂商。
但当数据量达到百万级要素或需要高频实时渲染时,GML的文本解析成本会成为瓶颈。此时常见做法是内部使用PostGIS或GeoJSON,仅在对外交换边界转成GML。也就是说,GML更像“通用语”而非“母语”,理解它在标准中的位置,才能用得恰当。
小结
把GML理解为基于XML的地理信息标准,重点在于它用Schema约束了空间语义,用坐标参考保证了位置准确,用要素模型统一了业务描述。掌握了要素、几何、属性的拆分方式,再配合解析工具,就能在异构GIS系统之间安稳地搬运空间数据。