地理Web服务

MapServer 发布服务都是通过 Mapfile 来配置的,WFS 服务也不例外,和配置 WMS 类似,发布 WFS 要在 Mapfile 配置文件中的 METADATA 部分添加关于 WFS 的键值对。只有在图层满足如下条件的时候, MapServer 才会包含 WFS 的功能:

  • 数据源是矢量数据:shapefile、OGR、Postgis、sde(ArcSDE);
  • 图层名称必须设置;
  • 图层数据空间类型必须是 pointlinepolygon 三者之一;
  • wfs_onlineresourcewfs_enable_request 必须设置。

MapServer 本身可以配置支持 WFS,另外,还可以使用 TinyOWS 。使用 TinyOWS 能够支持 WFS-T ,实现在线编辑保存的功能。

配置实例

我们在发布 WMS 的 Mapfile 配置基础上,添加 WFS 配置,下面是一个配置好 WMS 和 WFS 的 Mapfile 实例。

Mapfile 如下:

01 MAP
02     IMAGETYPE "PNG"
03     EXTENT -180 -90 180 90
04     SIZE 600 300
05     SHAPEPATH "/gdata"
06     IMAGECOLOR 255 255 255
07     WEB
08         METADATA
09             "wms_title" "WMS Demo Server"
10             "wms_onlineresource" "http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfb1.map&"
11             "ows_onlineresource" "http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfb1.map&"
12             "wms_srs" "EPSG:4269 EPSG:4326"
13             "wms_enable_request" "* !GetFeatureInfo"
14             "wfs_title" "world country"
15             "wfs_onlineresource" "http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map"
16             "wfs_srs" "EPSG:4326"
17             "wfs_abstract" "This text describes your wfs service"
18             "wfs_enable_request" "*"
19             "ows_keywordlist" "world"
20         END
21     END
22     LAYER
23         NAME "world-country"
24         DATA "wcountry.shp"
25         STATUS OFF
26         TYPE POLYGON
27         METADATA
28             "wms_title" "world country"
29             "wms_srs" "EPSG:4326"
30             "wfs_title" "worldcountry"
31             "wfs_srs" "EPSG:4326"
32             "wfs_enable_request" "*"
33             "gml_include_items" "all"
34             "gml_featureid" "OBJECTID"
35         END
36         CLASS
37             NAME "The Upper Great Lakes States"
38             STYLE
39                 COLOR 232 232 232
40                 OUTLINECOLOR 32 32 32
41             END
42         END
43     END
44 END

相对于只配置 WMS 的 Mapfile,主要的改变在于 MAP 对象的 METADATA 子对象和 LAYER 对象的 METADATA 子对象,在 MAP 对象的 METADATA 中,增加的键值对包括:

  • wfs_title ,必需, GetCapabilities 请求中作为服务响应的 XML 文档的 title 元素返回;
  • wfs_onlineresource ,必需,提供 wfs 的服务器地址;
  • wfs_srs ,数据的空间参考系(Spatial Reference System);
  • wfs_abstractGetCapabilities 请求中作为服务响应的 XML 文档的 Abstract 元素返回;
  • wfs_enable_request,表示配置 MapServer 地图全局支持 wfs 的所有操作。

LAYER 对象的 METADATA 增加的键值对如下(注:配置和 MAP 对象的 METADATA 有很多重复,如果不设置,就会继承 MAP 对象的 METADATA 的配置,如果设置就会使用 LAYER 的配置,这在一个 MAP 对象包含多个 LAYER 时非常有用):

  • wfs_titleGetCapabilities 请求中作为服务响应的 XML 文档的 title 元素返回;
  • wfs_srs,数据的空间参考系(Spatial Reference System);
  • gml_featureid ,图层对应的要素 ID 属性名;
  • wfs_enable_request ,配置图层支持 wfs 的所有操作。

访问

我们通过 URL 便可以调用 MapServer WFS 服务, WFS 缺省会返回 GML 格式的结果,在浏览器中可看其调用结果。WFS 包含很多操作,从 GetCapabilities 响应中可以看到 Mapfile 支持的 WFS 操作:

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities

URL的解析如下:

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 SERVICE=WFS
2 VERSION=2.0.0
3 REQUEST=GetCapabilities

DescribeFeatureType

在操作数据库的时候,我们有时需要反射数据库的结构,在使用 WFS 的时候我们也存在同样问题。有时候我们需要知道某个FeatureType有哪些属性以及分别是什么类型,这时我们就需要 DescribeFeatureType 方法。一个典型的 DescribeFeatureType 调用是这样的: 

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=DescribeFeatureType&TypeName=world-country

URL 的解析如下:

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=DescribeFeatureType
4 TypeName=world-country

GetFeature

终于到了这个方法,这个方法可以说是WFS的基础,它的用途一目了然,获得Feature。如果你敲入这个调用: 下面的链接返回所有的要素。

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=GetFeature&TypeName=world-country

URL 的解析如下:

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=GetFeature
4 TypeName=world-country

这个调用意味着返回所有数据,通常会得到一个很大的 XML/GML 文档。。

可以返回有限数目的要素

通过使用参数 count=2 ,可以限制返回的要素数目。

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=GetFeature&TypeName=world-country&count=2

URL 的解析如下:

>>> [print(idx, x) for idx, x in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=GetFeature
4 TypeName=world-country
5 count=2

根据索引返回要素

可以根据索引返回要素,要实现此项功能,需要配置:

"gml_include_items" "all" ## Optional (serves all attributes for layer)
"gml_featureid"     "OBJECTID" ## REQUIRED

这里 OBJECTID 是 Shapefile 中的字段。

下面的链接,返回 ID 号为 227 的要素 :

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=GetFeature&TypeName=world-country&FeatureId=world-country.227

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=GetFeature
4 TypeName=world-country
5 FeatureId=world-country.227

使用 Filter

根据择舍器,如:

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=GetFeature&TypeName=world-country&Filter=<Filter><PropertyIsEqualTo><PropertyName>OBJECTID</PropertyName><Literal>227</Literal></PropertyIsEqualTo></Filter>

对 URL 解析如下:

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=GetFeature
4 TypeName=world-country
5 Filter=<Filter><PropertyIsEqualTo><PropertyName>OBJECTID</PropertyName><Literal>227</Literal></PropertyIsEqualTo></Filter>

更有意义的,根据名称选择。注意此处的选择,对属性的比较是区分大小写的。

http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map&service=WFS&VERSION=2.0.0&request=GetFeature&TypeName=world-country&Filter=<Filter><PropertyIsEqualTo><PropertyName>NAME</PropertyName><Literal>CHINA</Literal></PropertyIsEqualTo></Filter>

URL 的解析如下:

>>> [print(idx, x) for idx, x  in enumerate(url.split('&'))]
0 http://mapfig.cn/cgi-bin/mapserv?map=/owg/xmfw1.map
1 service=WFS
2 VERSION=2.0.0
3 request=GetFeature
4 TypeName=world-country
5 Filter=<Filter><PropertyIsEqualTo><PropertyName>NAME</PropertyName><Literal>CHINA</Literal></PropertyIsEqualTo></Filter>