在" OGC之路(1)WMS总结 "中我们讨论了WMS标准。我们可以从WMS服务器很方便的获得指定区域内的地图,但是我们只能获得渲染后的地图。有时候我们希望获得指定图层的Feature数据包括地理坐标和属性,更进一步,当我们需要修改数据源的数据的时候,WMS就不能满足需要了。OGC为我们提供了另外一个标准Web Feature Service(WFS)来对应以上需求。顾名思义,WFS是通过网络操作Feature的服务。它支持客户端对服务器的Feature执行INSERT, UPDATE, DELETE, LOCK, QUERY,DISCOVERY操作。乍一看感觉WFS像是一个数据库。那么是不是还有类似于SQL的东东呢,确实是这样,关于这个主题我们会在随后讨论。让我们先从一些基本概念开始。
先来说说Feature与FeatureType。我们说过Feature是对现实抽象的基本元素。它把现实物体抽象为属性数据和地理数据,然后再加上一个Id来标识。许多同类的Feature往往会要求统一处理,对他们分组就显得有必要了。于是Layer出现了,一个Layer就是一组具有相同属性结构的Feature(这是我的理解)。很多系统中同一个Layer里面的Feature还必须具有相同的几何类型,例如都是Point或者都是Polygon。Layer还有一个的Style,这样Feature就会以一致的方式渲染。
Feature的属性范围很宽,几乎没有限制,只要能和它代表的现实物体产生联系的数据,包括地理数据,都可以作为属性。实际上,我见过的几乎所有GIS系统都把一个Feature对应到一条数据库记录上,在C#里这往往表现为DataRow对象的实例。把Layer对应到数据库表(视图)上,在C#里这往往表现为DataTable对象的实例。于是我们会发现GIS数据的持久化依然是一个古老的主题"ORM"。那么对Feature的检索是不是也类似数据库的检索呢。差不多吧,一般,企业级的GIS应用,Feature的属性数据和地理数据都保存在数据库里。对他们的操作也就是一大串的SQL。有些系统的地理数据访问有专门的中间件来辅助,目前几乎所有的商用数据库都自己提供了GIS数据访问支持,看来GIS很快就会成为Web应用的标配了。OGC有一个" 简单对象访问协议 ",里面有很完整的关于GIS 对象建模 和 数据库建模 的设计指导,是相当不错的学习资料。
那FeatureType是什么呢,我们可以用类比的方式来描述:用OO语言中类型(Type)和实例(Instance)的关系来类比,FeatureType是Feature的类型,Feature是FeatureType的实例。
从数据库获取数据我们会使用SQL,我们需要告诉数据库服务器我们需要哪些表的哪些数据,"select name from peoples where age > 30",这条语句的含义相信大家一看就明白了。从WFS服务器获得数据时我们面临同样的问题,我们需要告诉服务器我们希望得到哪些FeatureType的哪些Feature。具体的格式我们会在介绍GetFeature时讨论,这里需要介绍一个很重要的概念Filter。在前一章我们已经使用过Filter,当时并没有过多纠缠,但是我们已经知道Filter是一种语言,就像SQL一样Filter也提供了表达式,函数等语法与扩展来帮助构建查询。我们可以把Filter看做SQL语句中"where"的部分。
WFS定义了如下方法:GetCapabilities,DescribeFeatureType,GetFeature, LockFeature(可选),Transaction(可选)。
- GetCapabilities。
WMS有"GetCapabilities",WFS也有"GetCapabilities",将来我们还会看到WCS也提供"GetCapabilities"。而且他们的意义都是一样的,返回服务器的Capability。OGC在定义各种标准时经常会遇到这种情况,本来在一个标准中使用的概念在其他的标准中同样会用到,为了不违反DRY原则,专家们抽象出一些标准来描述基础操作,相应的,先前的标准就成了抽象标准的派生物。是不是有点OO的感觉:)。这里我们就会遇到一个抽象标准OGC Web Services Common Specification(OWS)。GetCapabilities就是OWS的主要方法。派生标准会重写这个方法,WMS的GetCapabilities我们已经很熟悉了,现在我们来看看WFS的GetCapabilities。
WFS的GetCapabilities的调用格式与WMS差不多, http://localhost:8080/geoserver/ows?service=WFS&request=GetCapabilities ,但是返回数据却有很大区别。由于数据太多我就不把Capability数据块贴上来了。
我们看到了这样几个节点:ServiceIdentification,ServiceProvider,OperationsMetadata,FeatureTypeList和Filter_Capabilities。前三个节点是OWS定义的,后面两个是WFS追加的。如果你一直从第一章看过来,那你应该很熟悉这种结构了。这些节点的自描述能力很好,从字面上我们就能看出他们的作用。再对比他们的内容,也就八九不离十了。跳过前三个节点,目前他们对我们用处不大。
我们来看节点FeatureTypeList。很清楚,这个节点包含服务器发布的FeatureType(FeatureType节点)。以及对这些FeatureType的操作(Operations节点)。FeatureType都有一个Name节点,我们可以用它的值来指定FeatureType。DefaultSRS节点告诉我FeatureType在使用哪个坐标系。OutputFormats告诉我们FeatureType用哪些格式返回数据。WGS84BoundingBox就是这个FeatureType的范围的经纬度。
另外一个值得关注的就是Filter_Capabilities节点。这个节点告诉我们服务器对Filter的支持情况。
其实在WFS标准里面,Capability数据块的结构还要复杂得多。目前我们了解这些也就足够了。有了这些数据我们就知道我们该如何访问一个WFS服务器。
- DescribeFeatureType
在操作数据库的时候,我们有时需要反射数据库的结构,在ADO.NET里我们会使用函数"GetSchema"来获得一个描述了数据库元信息的XML数据块。在使用WFS的时候我们也存在同样问题。有时候我们需要知道某个FeatureType有哪些属性以及分别是什么类型,这时我们就需要DescribeFeatureType方法。一个典型的DescribeFeatureType调用是这样的: http://localhost:8080/geoserver/ows?service=WFS&request=DescribeFeatureType&TypeName=states 。返回值是这样的
Code