GML全称为Geography Markup Language,即地理标记语言,是一种用于表达地理空间数据的XML编码规范。它由开放地理空间联盟制定,主要解决不同系统之间地理信息交换的格式壁垒。与常见的图片或二进制空间数据不同,GML用纯文本方式记录几何对象、空间参考系以及要素属性,使得任何支持XML的工具都能读取和处理。

在GML文档中,最核心的概念是要素(Feature)、几何(Geometry)和属性(Property)。一个要素可以是一条河流、一个监测站或一块行政区,它包含若干几何信息与描述性字段。几何部分定义空间形态,属性部分承载业务数据,二者通过XML嵌套结构组合在一起。
GML的基础文档结构
一个最小的GML实例必须声明XML版本并引入GML命名空间。命名空间决定了标签的语义归属,通常写作http://www.opengis.net/gml。如果没有正确声明,解析器会把GML标签当作普通XML节点,导致空间信息丢失。下面展示一段描述单个点的GML片段。
<?xml version="1.0" encoding="UTF-8"?> <gml:Point xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"> <gml:coordinates>116.39,39.91</gml:coordinates> </gml:Point>
上述代码定义了一个位于经纬度坐标系下的点,srsName属性指明空间参考系为WGS84。坐标值按顺序书写,经度在前纬度在后,这与很多前端地图库的默认顺序一致。初学者容易把coordinates里的分隔符写错,GML标准使用英文逗号分隔同一点的坐标分量,用空格分隔多个点。
除了点,GML还支持线、多边形、多点集合等复杂几何。它们都继承自gml:AbstractGeometry类型,在schema中具有严格的子元素约束。理解这种类型体系,有助于在阅读他人数据时快速定位几何节点。
要素与属性的组织方式
实际业务中很少只传一个几何对象,更多是带有属性的要素集合。GML通过gml:featureMember包装具体要素,要素内部再用自定义标签表达字段。如下示例描述一个气象站。
<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
xmlns:gml="http://www.opengis.net/gml">
<gml:featureMember>
<Station>
<name>北京站</name>
<code>BJ001</code>
<gml:pointProperty>
<gml:Point srsName="EPSG:4326">
<gml:coordinates>116.40,39.90</gml:coordinates>
</gml:Point>
<gml:pointProperty>
</Station>
</gml:featureMember>
</wfs:FeatureCollection>
这里Station是用户定义的要素类型,name与code为其属性,几何通过pointProperty关联。这种设计把业务模型和空间模型解耦,既方便数据库映射,也利于接口扩展。要注意pointProperty标签本身属于GML预定义结构,不可随意改名。
当要素数量增多时,建议使用FeatureCollection统一包裹,这样符合WFS服务输出习惯,也便于程序批量解析。属性字段尽量使用简单类型,避免嵌套过深,否则会增加客户端反序列化难度。
如何用代码解析GML
由于GML本质是XML,任意XML解析器都能处理。Python环境下常用xml.etree.ElementTree提取节点,再按命名空间过滤。以下示例读取点坐标并打印。
import xml.etree.ElementTree as ET
xml_text = '''<gml:Point xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:coordinates>116.39,39.91</gml:coordinates>
</gml:Point>'''
ns = {'gml': 'http://www.opengis.net/gml'}
root = ET.fromstring(xml_text)
coords = root.find('gml:coordinates', ns).text
print('坐标:', coords)
代码先注册命名空间前缀,再用带前缀的路径查找元素。若忽略命名空间,直接写find('coordinates')会返回空值,这是新手最常见的解析错误。对于大型GML文件,建议使用流式解析如iterparse,防止内存占用过高。
在Java生态中,可借助GeoTools库将GML直接转为Feature对象,省去手动遍历标签的工作。不过引入该类库会增加打包体积,轻量场景仍推荐原生DOM或SAX处理。
GML与KML、GeoJSON的区别
不少初学者分不清GML、KML和GeoJSON。KML同样基于XML,但由Google推动,侧重浏览器地球展示;GeoJSON用JSON语法,前端友好但缺乏严格schema校验。GML的优势在于强类型与可扩展schema,适合政府、测绘等需要长期归档与跨机构分发的场景。
| 格式 | 语法基础 | 典型用途 |
|---|---|---|
| GML | XML | 地理数据交换与建模 |
| KML | XML | Google Earth可视化 |
| GeoJSON | JSON | Web地图快速渲染 |
选择格式时应看接收方系统能力。如果对方是Web前端,转成GeoJSON更高效;如果是国家级空间数据平台,提供GML往往是最稳妥的互操作方案。
入门实践建议
建议先下载一份标准GML样例,用浏览器或XML编辑器格式化查看,对照官方schema文档理解每个标签含义。随后写一个小程序完成“读取坐标、输出文本”的闭环,建立直观认知。遇到陌生标签时,优先查命名空间对应的规范而非猜测。
随着练习深入,可以尝试用PostGIS导出GML,或调用开源WFS服务获取实时要素。当你能不看文档就大致猜出一段GML表达的空间对象时,便真正完成了GML格式入门。