` - 测试几何属性字段中几何要素是否在另一个给定的几何要素内
`Openlayers`将这些与`GetFeature`操作相关的过滤操作都封装在`ol.format.filter`命名空间下:
其中的`ol.format.filter.During`是用于比较日期的,如果要素表中存在日期字段或时间戳字段,在进行比较时,需要转成`ISO-8601`时间格式的字符串形式。
>2020年12月8日20点0分0秒可以写成(带时区):2020-12-08T20:00:00+08:00 或 20201208T200000+08
**Filter示例**
```html
OpenLayers example
OGC WFS服务:加载GeoServer的WFS服务
```
示例中创建了一个面作为空间运算的输入,并创建对应的数据源和图层将其添加map中。通过`ol.format.WFS`中的`writeGetFeature()`方法创建`getFeature`操作的XML文本。再使用jquery或fetch发送`POST `请求获取要素集,最后使用对应的解析器解析响应结果,添加到矢量数据源中。
> jquery发送请求的Headers中的Content-Type默认是application/x-www-form-urlencoded表单,当发送XML文本是需要将其指定为application/xml。而fetch()方法发送的请求,会根据body中的数据自动设置Content-Type的类型。
当`outputFormat`参数设置为`application/json`时,请求结果会以`GeoJSON`的格式响应回来,可以使用`ol.format.GeoJSON`解析器进行解析。当`outputFormat`参数没有被设置时,默认是以XML的形式返回,可以使用`ol.format.WFS`解析器进行解析。
#### 1.2版本差异
1. 返回的GML版本不同
- WFS2.0.0请求默认返回的格式是GML3.2;
- WFS1.1.0请求默认返回的格式是GML3;
- WFS1.0.0请求默认返回的格式是GML2;
2. GeoServer 对于每种支持的GML格式,可以选择不同的SRS格式。
SRS Style:对返回数据的轴顺序有影响,对几何字段的坐标也会有影响。EPSG Code:以格式EPSG:XXXX(例如EPSG:4326)返回典型的EPSG号。这会以经度/纬度(x / y)的顺序格式化地理坐标。
| 版本 | GML | SRS | Axis ordering |
| --------------------- | ------ | ------------------------------------------------------------ | ----------------------- |
| WFS1.0.0 | GML2 | OGC HTTP URL (http://www.opengis.net/gml/srs/epsg.xml#4326)或EPSG:xxxx | longitude/latitude(x/y) |
| WFS1.1.0 | GML3 | urn:x-ogc:def:crs:EPSG:xxxx | latitude/longitude(y/x) |
| WFS1.1.1
WFS 2.0.0 | GML3.2 | urn:x-ogc:def:crs:EPSG:xxxx | latitude/longitude(y/x) |
3. WFS 1.1.0和2.0.0支持动态重新投影数据,这支持在本机SRS以外的SRS中返回数据。
4. WFS 2.0.0引入了新版本的过滤器编码规范,增加了对时间过滤器的支持。
5. WFS 2.0.0支持通过GetFeature请求进行联接。
6. WFS 2.0.0增加了通过startIndex和count参数分页GetFeature请求的结果的功能。GeoServer现在在WFS 1.0.0和1.1.0中支持此功能。
7. WFS 2.0.0支持存储的查询,这是存储在服务器上的常规WFS查询,因此可以通过将适当的标识符与WFS请求一起传递来调用它们。
8. WFS 2.0.0支持SOAP(简单对象访问协议)作为OGC接口的替代方法。
### 2 Transaction
在OWS规范中知道,Web服务体系规范的HTTP接口参数有XML和KVP两种形式,但WFS要求服务的`Transaction`接口必须由XML描述,另外空间数据交互必须由GML进行,数据过滤采用CQL语言。
每个事务将由零个或多个插入、更新和删除元素组成,每个事务元素按顺序执行。
> 在GeoServer中,每个事务都是原子的,这意味着如果任何元素失败,事务就会被放弃,数据也不会被修改。支持事务的WFS服务器有时称为WFS- t服务器。GeoServer完全支持事务。
#### 2.1 GML
地理标记语言(GML)是一种用于表示地理特征的XML语法。GML是地理系统的建模语言,也是Internet上地理事务的开放交换格式。与大多数基于XML的语法一样,语法分为两部分——描述文档的`schema`模式和包含实际数据的实例文档。
GML2 中Geometry schema的UML图
其中``是坐标``的子元素,用于描述坐标值。还添加了``用于描述一个范围 extent,坐标值为范围的左下角(最小值)和右上角(最大值)点。
`GML2`中几何标签的示例:
1. Coordinates
```xml
1.03,2.167 4.167,2.34
```
等价于
```xml
1.032.167
4.1672.34
```
注意:坐标值必须是相同的维度。
- cs(coordinate separated):坐标之间的分隔符;
- ts(tuples separated):坐标元组之间分隔符;
2. Point
```xml
5.0,40.0
```
Point 标签下面可以有 coordinates 标签用于描述点位信息。还可以使用ID、srsName 属性,srsName 指定要素的空间参考。
3. Box
```xml
0.0,0.0 100.0,100.0
```
Box用于描述一个范围 extent,坐标值为范围的左下角(最小值)和右上角(最大值)点。
4. LineString
```xml
0.0,0.0
100.0,100.0
```
LineString是一个分段的线状路径,用于描述线要素,至少两个点。
5. LinearRing
```xml
0.0,0.0
100.0,0.0
50.0,100.0
0.0,0.0
```
是一段封闭的分段的线状路径,(coordinates 标签中)至少4个坐标点,三个坐标可以确定 LinearRing,第四个坐标用于闭合,与第一个坐标相同。用于构造面元素(Polygon),所以不需要SRS属性。
6. Polygon
```xml
0.0,0.0 100.0,0.0 100.0,100.0 0.0,100.0
0.0,0.0
10.0,10.0 10.0,40.0 40.0,40.0 40.0,10.0
10.0,10.0
60.0,60.0 60.0,90.0 90.0,90.0 90.0,60.0
60.0,60.0
```
用于描述面要素(surface)。必须有一个且最多只有一个 Exterior boundary 和 零个或多个 Interior boundary。Interior boundary 之间不能相交或包含。路径(坐标)的顺序是顺时针或逆时针不重要。
7. MultiPoint
```xml
56.1,0.45
46.71,9.25
56.88,10.44
```
> 注意:srsName 属性只能出现在最外层要素的标签内,且其包含的子要素不能再出现 srsName属性。
8. MultiLineString
```xml
56.1,0.45 67.23,0.67
46.71,9.25 56.88,10.44
324.1,219.7 0.45,0.56
```
注意:跟 MuliPointElement 标签一样,srsName 属性只能出现在最外层要素上。
9. MultiPolygon
```xml
0.0,0.0 10.0,0.0 10.0,10.0 0.0,10.0
0.0,0.0
40.0,40.0 50.0,40.0 50.0,50.0 40.0,50.0
40.0,40.0
```
10. GeometryCollection
```xml
50.0,50.0
0.0,0.0 0.0,50.0 100.0,50.0 100.0,100.0
0.0,0.0 100.0,0.0 50.0,100.0 0.0,0.0
```
geometryMember 子标签可以包含任意类型的几何对象。
#### 2.2 Insert
使用``标签创建一个新的要素,添加到WFS服务的数据源中。默认是使用`GML3`(WFS1.1.0)来描述要创建的新要素,也可以使用`inputFormat`属性来兼容旧的`GML2`(inputFormat='text/xml;subtype=2.1.2')。当新的要素添加到数据源中时,会默认给新生的要输生成一个`gid`作为唯一标识来标识该要素。若想指定`gid`的值,可以只用`idgen`属性,将其设置为`UseExisting`,在插入的要素标签中添加`gml:id`属性指定`gid`的值,如果所给的值已经存在或数据类型不匹配,则会插入失败。
```xml
A94
测试
-8237795.685217111,4980323.905513588 -8238827.585098961,4978584.963120101
```
> PostGIS导入的shapefile文件的srid默认为0。新增加的要素带有空间参考srid,所以如果在导入文件的时候没有指定srid,则会不一致,新增的要素在PostgreSQL的几何查看器中显示不出来。
可能出现的问题:`is read-only`
解决方法:放开write权限。在GeoServer左侧的"Security"中的"Data"栏,点击"Rule path"中的"..w",勾选"Grant access to any role"下面的单选框,点击保存。
```xml
{http://localhost:8080/test}tiger_roads is read-only
```
在`writeTransaction`方法中笔者没有查找到关于`idgen`属性的配置方式,直接在创建Feature实例时添加`gid`是无效的,`gid`的生成方式是由服务端自动生成。
```html
OpenLayers example
OGC WFS服务:Transaction Insert
```
#### 2.3 Update
``标签用于修改单个Feature要素或要素集合,多个``标签可以出现在同一个`Transaction`事务里面。``标签里面包含一个或多个用于指定要修改的属性的``标签和一个用于筛选要素的``标签,对于没有使用`
name
测试Insert412
test:name
测试Insert4*
```
从上面的示例中可以看出,发送Transaction事务的XML文本可以实现类似于SQL语句一样的`Update`操作,但在`writeTransaction`方法中并没有提供类似`Filter`过滤的参数,而是直接将需要修改的Feature要素作为输入,进行修改。通常的作法是:
1. 先加载WFS服务;
2. 在通过`ol.interaction.Select`和`ol.interaction.Modify`控件选择WFS服务的要素,并对其进行修改,监听修改完的事件,获取要素修改后的`geometry`及其属性;
3. 还可以提供一个表单或弹出层界面来修改属性值;
4. 将最终修改得到的要素传入`writeTransaction`方法创建事务的XML文本,发送请求提交。
```html
OpenLayers example
OGC WFS服务:Transaction Update
```
修改的要素必须要有id,因为最终发送的Transaction的XML文本中,是通过`GmlObjectId`作为过滤表达式Filter筛选要素的。
> 修改操作需要注意,字段的类型。如果所给的属性值于字段类型不匹配或长度越界了,将会修改失败。
#### 2.4 Delete
``用于删除一个或多个要素,跟``、``标签一样通过``标签筛选要操作的要素。如果没有使用``标签对要素进行筛选,则该事务中的删除操作将无效。
```xml
```
删除操作和更新操作一样也是根据Feature的id来进行操作的。这里我们使用`ol.interaction.Select`控件来选择要删除的要素,在确定删除操作成功后,从矢量数据源中移除被删除的要素和清空在`Select`控件中已选要素的集合。
```html
OpenLayers example
OGC WFS服务:Transaction Delete
```
### 3 WFS运算示例
> WFS版本使用1.1.0
#### 3.1 简单查询
1. 查询该服务(图层)的所有要素
```xml
```
2. 指定返回的结果集中要素的属性(属性名称需要大写,XML是大小写敏感的,且需要添加工作空间)
```xml
topp:STATE_NAME
```
3. 指定响应数据的格式
```xml
topp:STATE_NAME
```
4. 查询多个服务(图层)
```xml
```
#### 3.2 比较运算
比较运算符可以说是表达式,应该放在Filter标签里面
1. 查找哪个州的总人口person等于3145585.0
```xml
topp:PERSONS
3145585.0
```
2. 模糊匹配,州名称以W开头的
```xml
topp:STATE_NAME
W*
```
wildCard :指定匹配零个或多个字符串字符的任何序列的模式字符
singleChar :指定匹配任何单个字符串字符的模式字符
escapeChar :指定可用于转义模式字符的转义字符
3. 查询state_name属性为null的记录
```xml
topp:STATE_NAME
```
4. 查询人口总数在[2477574,4781468]之间的州,并根据总人口persons属性倒序排序
```xml
test:persons
test:persons
2477574
4781468
test:persons
DESC
```
注意:
- 需要将state的shapefile文件导入postgresql中,发布postgis表的数据图层,否则将会因为无法序列化,而不能排序
- 入库后,postgresql表中的属性字段是默认小写的,所以PropertyName标签中的属性值应小写
- 用于排序的字段必须是结果集中存在的字段,即存在标签\值为排序属性
#### 3.3空间运算
1. Intersects:相交
```xml
test:cfcc
test:name
geom
-8236751.648901709 4974597.071767016
-8235757.967534002 4975476.097592296
```

2. Disjoint:不相交。下面将逻辑运算和空间运算结合(取不相交的非,得到与上面1一样的结果)
```xml
test:cfcc
test:name
geom
-8236751.648901709 4974597.071767016
-8235757.967534002 4975476.097592296
```
3. Contains:判断几何对象是否包含另一个几何(几何属性的要素是否包含所给的几何对象)
```xml
test:cfcc
test:name
geom
-8234663.297809127 4976806.185109221
```
常见的包含关系存在于线包含点,面包含线。
4. Within:判断几何属性字段中的几何要素是否被给定的另一个几何对象包含
```xml
test:cfcc
test:name
geom
-8236070.085302306 4974636.883205217 -8234716.512732034 4974464.899891576 -8234716.512732034 4973573.134464388 -8236391.757990729 4973614.537951903 -8236070.085302306 4974636.883205217
```

#### 3.4 Transaction
1. Insert
```xml
A94
测试
-8237795.685217111,4980323.905513588 -8238827.585098961,4978584.963120101
```
2. update
```xml
name
测试Insert312
```
3. delete
```xml
```
### 参考文章
[1] [WFS Reference](https://docs.geoserver.org/latest/en/user/services/wfs/reference.html) :`https://docs.geoserver.org/latest/en/user/services/wfs/reference.html`
[2] [Filter Reference](https://docs.geoserver.org/2.12.2/user/filter/filter_reference.html) :`https://docs.geoserver.org/2.12.2/user/filter/filter_reference.html`
[3] [Filter Encoding](https://www.ogc.org/standards/filter) :`https://www.ogc.org/standards/filter`