1456 lines
53 KiB
Markdown
1456 lines
53 KiB
Markdown
---
|
||
title: WFS服务的CRUD
|
||
date: 2020-11-25
|
||
author: ac
|
||
tags:
|
||
- wfs
|
||
- Openlayers
|
||
categories:
|
||
- GIS
|
||
---
|
||
|
||
> CRUD的原理
|
||
|
||
在Openlayers中对WFS服务CRUD的支持都封装在`ol.format.WFS`的解析器里面,查询使用其中的`writeGetFeature`方法创建查询要素的XML文本,增加、修改、删除使用其中的`writeTransaction`方法创建事务的XML文本,最后通过发送`POST`请求将XML文本发送到地图服务器进行CRUD的操作。
|
||
|
||
### 1 GetFeature
|
||
|
||
WFS的查询是通过`GetFeature`接口实现的。在发送`GetFeature`请求时,使用Filter Encoding或CQL(Common Query Language)增加过滤的表达式,来筛选要素。
|
||
|
||
#### 1.1 CQL filters
|
||
|
||
在WFS GetFeature GET请求中,可以使用cql_filter参数来指定ECQL(Extended Common Query Language)格式的过滤器,通过过滤器筛选符合条件的要素集。
|
||
|
||
CQL是OGC创建一种查询语言,与基于xml的过滤器编码语言不同,CQL使用熟悉的基于文本的语法编写。因此,它更具可读性,更易于编码。然而,CQL也有一些局限性。例如,它不能对id过滤器进行编码,并且它要求在任何比较操作符的左侧都有一个属性。由于这个原因,GeoServer提供了CQL的扩展版本,称为ECQL。ECQL消除了CQL的限制,提供了一种与SQL有更强相似性的更灵活的语言。
|
||
|
||
CQL和ECQL常用与`WMS`服务的`GetMap`请求和`WFS`的`GetFeature`请求中,另外CQL还应用于SLD样式文件中。它们在功能上类似于SQL的“WHERE”子句。过滤器是使用条件指定的。
|
||
|
||
版本适用范围:
|
||
|
||
- Filter Encoding 1.0 适用于 WFS1.0和SLD1.0
|
||
- Filter Encoding 1.1 适用于 WFS1.1。ECQL完全适用于1.1的标准。
|
||
- Filter Encoding 2.0 适用于 WFS2.0
|
||
|
||
> Filter Encoding 是一种基于XML的过滤器编码语言。
|
||
|
||
示例:
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<ogc:Filter>
|
||
<ogc:FeatureId fid="states.3"/>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
<img src="./images/image854218.png" alt="image854218" style="zoom: 50%;" />
|
||
|
||
**比较运算符**
|
||
|
||
- `<PropertyIsEqualTo>`:等于
|
||
- `<PropertyIsNotEqualTo>`:不等于
|
||
- `<PropertyIsLessThan>`:小于
|
||
- `<PropertyIsLessThanOrEqualTo>`:小于或等于
|
||
- `<PropertyIsGreaterThan>`:大于
|
||
- `<PropertyIsGreaterThanOrEqualTo>`:大于或等于
|
||
- `<PropertyIsLike>`:模糊匹配
|
||
- `<PropertyIsNull>`:不等于null
|
||
- `<PropertyIsBetween>`:在区间内
|
||
|
||
> 这些比较运算符中都包含两个元素,属性名称\<ogc:PropertyName>和属性值\<ogc:Literal>,根据版本不同会有所变化,但都是用于确定运算的属性和属性值。
|
||
|
||
**逻辑运算**
|
||
|
||
- `<And>` - 逻辑与
|
||
- `<Or>` - 逻辑或
|
||
- `<Not>` - 非
|
||
|
||
**空间运算**
|
||
|
||
- `<Intersects>` - 测试几何属性字段中几何要素是否与给定的几何要素相交
|
||
- `<Disjoint>` - 测试两个几何是否不相交
|
||
- `<Contains>` - 测试几何属性字段中几何要素是否包含给定的几何要素
|
||
- `<Within>` - 测试几何属性字段中几何要素是否在另一个给定的几何要素内
|
||
|
||
`Openlayers`将这些与`GetFeature`操作相关的过滤操作都封装在`ol.format.filter`命名空间下:
|
||
|
||
<div style="text-align:center"><img src="./images/image45038.png" alt="image45038" style="zoom: 80%;" /></div>
|
||
|
||
其中的`ol.format.filter.During`是用于比较日期的,如果要素表中存在日期字段或时间戳字段,在进行比较时,需要转成`ISO-8601`时间格式的字符串形式。
|
||
|
||
>2020年12月8日20点0分0秒可以写成(带时区):2020-12-08T20:00:00+08:00 或 20201208T200000+08
|
||
|
||
**Filter示例**
|
||
|
||
```html
|
||
<!doctype html>
|
||
<html >
|
||
<head>
|
||
<link rel="stylesheet" href="css/ol.css" type="text/css">
|
||
<style>
|
||
.map {
|
||
height: 85vh;
|
||
width: 100%;
|
||
}
|
||
</style>
|
||
<script src="lib/ol.js"></script>
|
||
<script src="lib/jquery-3.1.1.js"></script>
|
||
<title>OpenLayers example</title>
|
||
<meta charset="UTF-8">
|
||
</head>
|
||
<body>
|
||
<h2>OGC WFS服务:加载GeoServer的WFS服务</h2>
|
||
<div id="map" class="map"></div>
|
||
<script type="text/javascript">
|
||
var inputPolygon = new ol.geom.Polygon([
|
||
//第一个LinearRing
|
||
[
|
||
[-8236070.085302306,4974636.883205217],
|
||
[-8234716.512732034,4974464.899891576],
|
||
[-8234716.512732034,4973573.134464388],
|
||
[-8236391.757990729,4973614.537951903],
|
||
[-8236070.085302306,4974636.883205217]
|
||
]
|
||
]);
|
||
var feature = new ol.Feature({
|
||
geometry:inputPolygon
|
||
})
|
||
var vec = new ol.source.Vector();
|
||
vec.addFeature(feature);
|
||
|
||
var wfsFormat = new ol.format.WFS();
|
||
var geojsonFormat = new ol.format.GeoJSON();
|
||
var vectorSource = new ol.source.Vector();
|
||
var wfsUrl = "http://localhost:8080/geoserver/wfs";
|
||
var getFeatureXml = wfsFormat.writeGetFeature({
|
||
"featureNS":"http://localhost:8080/test",//命名空间URI
|
||
"featurePrefix":"test",//命名空间的前缀
|
||
"featureTypes":["tiger_roads"],//图层名
|
||
"srsName":"EPSG:3857",//输出的要素集的空间参考
|
||
"outputFormat":"application/json",//输出格式
|
||
// "maxFeatures":"5",//最大要素数量
|
||
// "geometryName":"",//用于BBOX过滤的几何对象的名称
|
||
// "propertyNames":["state_name"],//属性数组,用于限定要素集中的要素有哪些属性
|
||
// "viewParams":"",//用于配置GeoServer中的视图参数
|
||
// "startIndex":"",//起始索引,与count参数配置使用,进行分页查询。(WFS2.0.0后加入的功能)
|
||
// "count":"",//查询数量
|
||
// "bbox":"",//用于BBOX过滤的边界,可以是Extent对象
|
||
// "resultType":""//用于指示WFS应该向用户返回结果(results:返回所有要素实例,hits:返回一个空的响应,但有匹配的要素总数)
|
||
// "filter":new ol.format.filter.IsLike('name','W*','*','.','!'),//过滤表达式
|
||
// "filter":new ol.format.filter.Intersects('geom',intersectPolygon)
|
||
// "filter":new ol.format.filter.Contains('geom',intersectPolygon)
|
||
"filter":new ol.format.filter.Within('geom',inputPolygon)
|
||
});
|
||
|
||
/**
|
||
* jquery默认的Content-Type是application/x-www-form-urlencoded表单
|
||
* HTML文档标记:text/html;
|
||
* 普通ASCII文档标记:text/html;
|
||
* JPEG图片标记:image/jpeg;
|
||
* GIF图片标记:image/gif;
|
||
* js文档标记:application/javascript;
|
||
* xml文件标记:application/xml;text/xml的话,将忽略xml数据里的编码格式
|
||
* 文件上传: multipart/form-data
|
||
* 普通表单:application/x-www-form-urlencoded
|
||
*/
|
||
// $.ajax({
|
||
// url:wfsUrl,
|
||
// type:"post",
|
||
// contentType:"application/xml",
|
||
// processData:false,
|
||
// data:new XMLSerializer().serializeToString(getFeatureXml),
|
||
// dataType:"json",
|
||
// success:function (result) {
|
||
// console.log("result:" ,result);
|
||
// var featureCollection = geojsonFormat.readFeatures(result);
|
||
// vectorSource.addFeatures(featureCollection);
|
||
// },
|
||
// error:function(e){
|
||
// console.log("error:" ,e)
|
||
// }
|
||
// })
|
||
fetch(wfsUrl, {
|
||
method: 'POST',
|
||
body: new XMLSerializer().serializeToString(getFeatureXml),
|
||
})
|
||
.then(function (response) {
|
||
return response.json();
|
||
})
|
||
.then(function (result) {
|
||
var featureCollection = geojsonFormat.readFeatures(result);
|
||
vectorSource.addFeatures(featureCollection);
|
||
// map.getView().fit(vectorSource.getExtent());
|
||
// console.log("result:" , result);
|
||
});
|
||
|
||
var nyc = [-73.92722,40.774221];
|
||
var map = new ol.Map({
|
||
layers: [
|
||
// new ol.layer.Tile({
|
||
// source: new ol.source.OSM()
|
||
// }),
|
||
new ol.layer.Vector({
|
||
source:vectorSource
|
||
}),
|
||
new ol.layer.Vector({
|
||
source:vec,
|
||
style:new ol.style.Style({
|
||
stroke:new ol.style.Stroke({
|
||
color: 'rgba(255, 0, 255, 1.0)',
|
||
width: 2
|
||
})
|
||
})
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new ol.View({
|
||
center:ol.proj.fromLonLat(nyc),
|
||
zoom: 11
|
||
})
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
示例中创建了一个面作为空间运算的输入,并创建对应的数据源和图层将其添加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<br>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`模式和包含实际数据的实例文档。
|
||
|
||
<img src="./images/image753.png" alt="image753" style="zoom: 67%;" />
|
||
|
||
<div style="text-align:center">GML2 中Geometry schema的UML图</div>
|
||
|
||
其中`<coord>`是坐标`<coordinates>`的子元素,用于描述坐标值。还添加了`<Box>`用于描述一个范围 extent,坐标值为范围的左下角(最小值)和右上角(最大值)点。
|
||
|
||
`GML2`中几何标签的示例:
|
||
|
||
1. Coordinates
|
||
|
||
```xml
|
||
<coordinates decimal="." cs="," ts=" ">
|
||
1.03,2.167 4.167,2.34
|
||
</coordinates>
|
||
```
|
||
|
||
等价于
|
||
|
||
```xml
|
||
<coord><X>1.03</X><Y>2.167</Y></coord>
|
||
<coord><X>4.167</X><Y>2.34</Y></coord>
|
||
```
|
||
|
||
注意:坐标值必须是相同的维度。
|
||
|
||
- cs(coordinate separated):坐标之间的分隔符;
|
||
- ts(tuples separated):坐标元组之间分隔符;
|
||
|
||
|
||
|
||
2. Point
|
||
|
||
```xml
|
||
<Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
|
||
<coordinates>5.0,40.0</coordinates>
|
||
</Point>
|
||
```
|
||
|
||
Point 标签下面可以有 coordinates 标签用于描述点位信息。还可以使用ID、srsName 属性,srsName 指定要素的空间参考。
|
||
|
||
|
||
|
||
3. Box
|
||
|
||
```xml
|
||
<Box srsName="EPSG:4326">
|
||
<coordinates>
|
||
0.0,0.0 100.0,100.0
|
||
</coordinates>
|
||
</Box>
|
||
```
|
||
|
||
Box用于描述一个范围 extent,坐标值为范围的左下角(最小值)和右上角(最大值)点。
|
||
|
||
|
||
|
||
4. LineString
|
||
|
||
```xml
|
||
<LineString srsName="EPSG:4326">
|
||
<coordinates>
|
||
0.0,0.0
|
||
100.0,100.0
|
||
</coordinates>
|
||
</LineString>
|
||
```
|
||
|
||
LineString是一个分段的线状路径,用于描述线要素,至少两个点。
|
||
|
||
|
||
|
||
5. LinearRing
|
||
|
||
```xml
|
||
<LinearRing>
|
||
<coordinates>
|
||
0.0,0.0
|
||
100.0,0.0
|
||
50.0,100.0
|
||
0.0,0.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
```
|
||
|
||
是一段封闭的分段的线状路径,(coordinates 标签中)至少4个坐标点,三个坐标可以确定 LinearRing,第四个坐标用于闭合,与第一个坐标相同。用于构造面元素(Polygon),所以不需要SRS属性。
|
||
|
||
|
||
|
||
6. Polygon
|
||
|
||
```xml
|
||
<Polygon srsName="EPSG:4326">
|
||
<outerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
0.0,0.0 100.0,0.0 100.0,100.0 0.0,100.0
|
||
0.0,0.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</outerBoundaryIs>
|
||
<innerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
10.0,10.0 10.0,40.0 40.0,40.0 40.0,10.0
|
||
10.0,10.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</innerBoundaryIs>
|
||
<innerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
60.0,60.0 60.0,90.0 90.0,90.0 90.0,60.0
|
||
60.0,60.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</innerBoundaryIs>
|
||
</Polygon>
|
||
```
|
||
|
||
用于描述面要素(surface)。必须有一个且最多只有一个 Exterior boundary 和 零个或多个 Interior boundary。Interior boundary 之间不能相交或包含。路径(坐标)的顺序是顺时针或逆时针不重要。
|
||
|
||
|
||
|
||
7. MultiPoint
|
||
|
||
```xml
|
||
<MultiPoint srsName="EPSG:4326">
|
||
<pointMember>
|
||
<Point>
|
||
<coordinates>56.1,0.45</coordinates>
|
||
</Point>
|
||
</pointMember>
|
||
<pointMember>
|
||
<Point>
|
||
<coordinates>46.71,9.25</coordinates>
|
||
</Point>
|
||
</pointMember>
|
||
<pointMember>
|
||
<Point>
|
||
<coordinates>56.88,10.44</coordinates>
|
||
</Point>
|
||
</pointMember>
|
||
</MultiPoint >
|
||
```
|
||
|
||
> 注意:srsName 属性只能出现在最外层要素的标签内,且其包含的子要素不能再出现 srsName属性。
|
||
|
||
|
||
|
||
8. MultiLineString
|
||
|
||
```xml
|
||
<MultiLineString srsName="EPSG:4326">
|
||
<lineStringMember>
|
||
<LineString>
|
||
<coordinates>56.1,0.45 67.23,0.67</coordinates>
|
||
</LineString>
|
||
</lineStringMember>
|
||
<lineStringMember>
|
||
<LineString>
|
||
<coordinates>46.71,9.25 56.88,10.44</coordinates>
|
||
</LineString>
|
||
</lineStringMember>
|
||
<lineStringMember>
|
||
<LineString>
|
||
<coordinates>324.1,219.7 0.45,0.56</coordinates>
|
||
</LineString>
|
||
</lineStringMember>
|
||
</MultiLineString>
|
||
```
|
||
|
||
注意:跟 MuliPointElement 标签一样,srsName 属性只能出现在最外层要素上。
|
||
|
||
|
||
|
||
9. MultiPolygon
|
||
|
||
```xml
|
||
<MultiPolygon srsName="EPSG:4326">
|
||
<polygonMember>
|
||
<Polygon>
|
||
<outerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
0.0,0.0 10.0,0.0 10.0,10.0 0.0,10.0
|
||
0.0,0.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</outerBoundaryIs>
|
||
</Polygon>
|
||
</polygonMember>
|
||
<polygonMember>
|
||
<Polygon>
|
||
<outerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
40.0,40.0 50.0,40.0 50.0,50.0 40.0,50.0
|
||
40.0,40.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</outerBoundaryIs>
|
||
</Polygon>
|
||
</polygonMember>
|
||
</MultiPolygon>
|
||
```
|
||
|
||
|
||
|
||
10. GeometryCollection
|
||
|
||
```xml
|
||
<GeometryCollection srsName="EPSG:4326">
|
||
<geometryMember>
|
||
<Point>
|
||
<coordinates>
|
||
50.0,50.0
|
||
</coordinates>
|
||
</Point>
|
||
</geometryMember>
|
||
<geometryMember>
|
||
<LineString>
|
||
<coordinates>
|
||
0.0,0.0 0.0,50.0 100.0,50.0 100.0,100.0
|
||
</coordinates>
|
||
</LineString>
|
||
</geometryMember>
|
||
<geometryMember>
|
||
<Polygon>
|
||
<outerBoundaryIs>
|
||
<LinearRing>
|
||
<coordinates>
|
||
0.0,0.0 100.0,0.0 50.0,100.0 0.0,0.0
|
||
</coordinates>
|
||
</LinearRing>
|
||
</outerBoundaryIs>
|
||
</Polygon>
|
||
</geometryMember>
|
||
</GeometryCollection>
|
||
```
|
||
|
||
geometryMember 子标签可以包含任意类型的几何对象。
|
||
|
||
|
||
|
||
#### 2.2 Insert
|
||
|
||
使用`<Insert>`标签创建一个新的要素,添加到WFS服务的数据源中。默认是使用`GML3`(WFS1.1.0)来描述要创建的新要素,也可以使用`inputFormat`属性来兼容旧的`GML2`(inputFormat='text/xml;subtype=2.1.2')。当新的要素添加到数据源中时,会默认给新生的要输生成一个`gid`作为唯一标识来标识该要素。若想指定`gid`的值,可以只用`idgen`属性,将其设置为`UseExisting`,在插入的要素标签中添加`gml:id`属性指定`gid`的值,如果所给的值已经存在或数据类型不匹配,则会插入失败。
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:Transaction
|
||
version="1.1.0"
|
||
service="WFS"
|
||
xmlns="http://www.someserver.com/myns"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.someserver.com/myns
|
||
http://www.someserver.com/wfs/cwwfs.cgi?
|
||
http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd">
|
||
<wfs:Insert inputFormat="text/xml;subtype=2.1.2" idgen="UseExisting">
|
||
<test:tiger_roads gml:id="10002">
|
||
<cfcc>A94</cfcc>
|
||
<name>测试</name>
|
||
<geom>
|
||
<MultiLineString srsName="EPSG:3857">
|
||
<lineStringMember>
|
||
<LineString>
|
||
<coordinates>-8237795.685217111,4980323.905513588 -8238827.585098961,4978584.963120101</coordinates>
|
||
</LineString>
|
||
</lineStringMember>
|
||
</MultiLineString>
|
||
</geom>
|
||
</test:tiger_roads>
|
||
</wfs:Insert>
|
||
</wfs:Transaction>
|
||
```
|
||
|
||
<img src="./images/image9076.png" alt="image9076" style="zoom: 80%;" />
|
||
|
||
> PostGIS导入的shapefile文件的srid默认为0。新增加的要素带有空间参考srid,所以如果在导入文件的时候没有指定srid,则会不一致,新增的要素在PostgreSQL的几何查看器中显示不出来。
|
||
|
||
|
||
|
||
可能出现的问题:`is read-only`
|
||
|
||
解决方法:放开write权限。在GeoServer左侧的"Security"中的"Data"栏,点击"Rule path"中的"..w",勾选"Grant access to any role"下面的单选框,点击保存。
|
||
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<ows:ExceptionReport xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ows="http://www.opengis.net/ows" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/ows http://localhost:8080/geoserver/schemas/ows/1.0.0/owsExceptionReport.xsd">
|
||
<ows:Exception exceptionCode="NoApplicableCode">
|
||
<ows:ExceptionText>{http://localhost:8080/test}tiger_roads is read-only</ows:ExceptionText>
|
||
</ows:Exception>
|
||
</ows:ExceptionReport>
|
||
```
|
||
|
||
|
||
|
||
在`writeTransaction`方法中笔者没有查找到关于`idgen`属性的配置方式,直接在创建Feature实例时添加`gid`是无效的,`gid`的生成方式是由服务端自动生成。
|
||
|
||
```html
|
||
<!doctype html>
|
||
<html >
|
||
<head>
|
||
<link rel="stylesheet" href="css/ol.css" type="text/css">
|
||
<style>
|
||
.map {
|
||
height: 85vh;
|
||
width: 100%;
|
||
}
|
||
</style>
|
||
<script src="lib/ol.js"></script>
|
||
<script src="lib/jquery-3.1.1.js"></script>
|
||
<title>OpenLayers example</title>
|
||
<meta charset="UTF-8">
|
||
</head>
|
||
<body>
|
||
<h2>OGC WFS服务:Transaction Insert</h2>
|
||
<div id="map" class="map"></div>
|
||
<script type="text/javascript">
|
||
var vectorSource = new ol.source.Vector({
|
||
format: new ol.format.GeoJSON(),
|
||
loader: function(extent, resolution, projection) {
|
||
var proj = projection.getCode();
|
||
var url = 'http://localhost:8080/geoserver/wfs?service=WFS&' +
|
||
'version=1.1.0&request=GetFeature&typename=test:tiger_roads&' +
|
||
'outputFormat=application/json&srsname='+proj+'&' +
|
||
'bbox=' + extent.join(',') + ',' +proj;
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('GET', url);
|
||
var onError = function() {
|
||
vectorSource.removeLoadedExtent(extent);
|
||
}
|
||
xhr.onerror = onError;
|
||
xhr.onload = function() {
|
||
if (xhr.status == 200) {
|
||
vectorSource.addFeatures(
|
||
vectorSource.getFormat().readFeatures(xhr.responseText));
|
||
} else {
|
||
onError();
|
||
}
|
||
}
|
||
xhr.send();
|
||
},
|
||
strategy: ol.loadingstrategy.bbox
|
||
});
|
||
var nyc = [-73.92722,40.774221];
|
||
var map = new ol.Map({
|
||
layers: [
|
||
// new ol.layer.Tile({
|
||
// source: new ol.source.OSM()
|
||
// }),
|
||
new ol.layer.Vector({
|
||
source: vectorSource
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new ol.View({
|
||
center:ol.proj.fromLonLat(nyc),
|
||
zoom: 11
|
||
})
|
||
})
|
||
map.on("click",function (e) {
|
||
var point = e.coordinate;
|
||
console.log("x:"+point[0]+",y:"+point[1]);
|
||
});
|
||
|
||
//Transaction Insert
|
||
var insertGeo = new ol.Feature({
|
||
// gid:10006,//无效,服务会自动生成gid
|
||
cfcc:"A95",
|
||
name:"测试Insert4",
|
||
geom: new ol.geom.MultiLineString([
|
||
[
|
||
[-8235005.193364706,4986963.973958403],
|
||
[-8238062.674496112,4982377.752261292]
|
||
]
|
||
])
|
||
});
|
||
insertGeo.setGeometryName('geom');
|
||
|
||
var wfsUrl = "http://localhost:8080/geoserver/wfs";
|
||
var wfsFormat = new ol.format.WFS();
|
||
var session = wfsFormat.writeTransaction([insertGeo],null,null,{
|
||
featureNS:"http://localhost:8080/test",
|
||
featurePrefix:"test",
|
||
featureType:"tiger_roads",
|
||
srsName:"EPSG:3857"
|
||
});
|
||
$.ajax({
|
||
url:wfsUrl,
|
||
type:"post",
|
||
contentType:"application/xml",
|
||
processData:false,
|
||
data:new XMLSerializer().serializeToString(session),
|
||
success:function (result) {
|
||
var responseText = wfsFormat.readTransactionResponse(result);
|
||
console.log(responseText)
|
||
},
|
||
error:function(e){
|
||
console.log("error:" ,e)
|
||
}
|
||
})
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
|
||
|
||
#### 2.3 Update
|
||
|
||
`<update>`标签用于修改单个Feature要素或要素集合,多个`<update>`标签可以出现在同一个`Transaction`事务里面。`<update>`标签里面包含一个或多个用于指定要修改的属性的`<Property>`标签和一个用于筛选要素的`<Filter>`标签,对于没有使用`<Property`属性列出来的属性将不会改变,但如果只指定了属性名没有给属性值,则该属性值会被设置为null。
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:Transaction
|
||
version="1.1.0"
|
||
service="WFS"
|
||
xmlns="http://www.someserver.com/myns"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.someserver.com/myns
|
||
http://www.someserver.com/wfs/cwwfs.cgi?
|
||
http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd">
|
||
<wfs:Update typeName="tiger_roads">
|
||
<wfs:Property>
|
||
<wfs:Name>name</wfs:Name>
|
||
<wfs:Value>测试Insert412</wfs:Value>
|
||
</wfs:Property>
|
||
<ogc:Filter>
|
||
<ogc:PropertyIsLike wildCard="*" singleChar="." escape="!">
|
||
<ogc:PropertyName>test:name</ogc:PropertyName>
|
||
<ogc:Literal>测试Insert4*</ogc:Literal>
|
||
</ogc:PropertyIsLike>
|
||
</ogc:Filter>
|
||
</wfs:Update>
|
||
</wfs:Transaction>
|
||
```
|
||
|
||
从上面的示例中可以看出,发送Transaction事务的XML文本可以实现类似于SQL语句一样的`Update`操作,但在`writeTransaction`方法中并没有提供类似`Filter`过滤的参数,而是直接将需要修改的Feature要素作为输入,进行修改。通常的作法是:
|
||
|
||
1. 先加载WFS服务;
|
||
2. 在通过`ol.interaction.Select`和`ol.interaction.Modify`控件选择WFS服务的要素,并对其进行修改,监听修改完的事件,获取要素修改后的`geometry`及其属性;
|
||
3. 还可以提供一个表单或弹出层界面来修改属性值;
|
||
4. 将最终修改得到的要素传入`writeTransaction`方法创建事务的XML文本,发送请求提交。
|
||
|
||
```html
|
||
<!doctype html>
|
||
<html>
|
||
<head>
|
||
<link rel="stylesheet" href="css/ol.css" type="text/css">
|
||
<link rel="stylesheet" href="css/layui.css" type="text/css">
|
||
<style>
|
||
.map {
|
||
height: 85vh;
|
||
width: 100%;
|
||
}
|
||
</style>
|
||
<script src="lib/jquery-3.1.1.js"></script>
|
||
<script src="lib/layer.js"></script>
|
||
<script src="lib/ol.js"></script>
|
||
|
||
<title>OpenLayers example</title>
|
||
<meta charset="UTF-8">
|
||
</head>
|
||
<body>
|
||
<h2>OGC WFS服务:Transaction Update</h2>
|
||
<div id="map" class="map"></div>
|
||
<script type="text/javascript">
|
||
var vectorSource = new ol.source.Vector({
|
||
format: new ol.format.GeoJSON({geometryName:"geom"}),
|
||
loader: function (extent, resolution, projection) {
|
||
var proj = projection.getCode();
|
||
var url = 'http://localhost:8080/geoserver/wfs?service=WFS&' +
|
||
'version=1.1.0&request=GetFeature&typename=test:tiger_roads&' +
|
||
'outputFormat=application/json&srsname=' + proj + '&' +
|
||
'bbox=' + extent.join(',') + ',' + proj;
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('GET', url);
|
||
var onError = function () {
|
||
vectorSource.removeLoadedExtent(extent);
|
||
}
|
||
xhr.onerror = onError;
|
||
xhr.onload = function () {
|
||
if (xhr.status == 200) {
|
||
vectorSource.addFeatures(
|
||
vectorSource.getFormat().readFeatures(xhr.responseText));
|
||
} else {
|
||
onError();
|
||
}
|
||
}
|
||
xhr.send();
|
||
},
|
||
strategy: ol.loadingstrategy.bbox
|
||
});
|
||
var nyc = [-73.92722, 40.774221];
|
||
var map = new ol.Map({
|
||
layers: [
|
||
// new ol.layer.Tile({
|
||
// source: new ol.source.OSM()
|
||
// }),
|
||
new ol.layer.Vector({
|
||
source: vectorSource
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new ol.View({
|
||
center: ol.proj.fromLonLat(nyc),
|
||
zoom: 11
|
||
})
|
||
})
|
||
map.on("click", function (e) {
|
||
var point = e.coordinate;
|
||
console.log("x:" + point[0] + ",y:" + point[1]);
|
||
});
|
||
|
||
//Transaction update
|
||
|
||
var modfeatureCollection = null;
|
||
var select = new ol.interaction.Select({
|
||
//点击选择要素的容差,单位px
|
||
hitTolerance: 5,
|
||
//设置select选择或释放触发的切换函数
|
||
toggleCondition: function (e) {
|
||
if (modfeatureCollection&&modfeatureCollection.getLength()) {
|
||
var modFeature = modfeatureCollection.item(0);
|
||
showProperty(modFeature);
|
||
}
|
||
}
|
||
});
|
||
var modify = new ol.interaction.Modify({
|
||
features: select.getFeatures()
|
||
});
|
||
//每增加或移动要素的一个节点都会触发
|
||
modify.on('modifyend', function (e) {
|
||
modfeatureCollection = e.features;
|
||
});
|
||
map.addInteraction(select);
|
||
map.addInteraction(modify);
|
||
|
||
function showProperty(feature) {
|
||
var text = createForm(feature);
|
||
layer.open({
|
||
title: '属性编辑'
|
||
, content: text
|
||
, type: 1
|
||
, btn: ['提交']
|
||
, yes: function (index, layero) {
|
||
var property = feature.values_;
|
||
var geometryName = feature.getGeometryName();
|
||
for(var key in property){
|
||
if(key != geometryName){
|
||
var newVal = document.getElementById(key).value;
|
||
property[key] = newVal;
|
||
}
|
||
}
|
||
updateFeature(feature);
|
||
layer.close(index);
|
||
}
|
||
})
|
||
}
|
||
|
||
function createForm(feature) {
|
||
var divStr = '<div class="layui-form">';
|
||
var property = feature.values_;
|
||
var geometryName = feature.getGeometryName();
|
||
for(var key in property){
|
||
if(key != geometryName){
|
||
divStr += '<div class="layui-form-item">'+
|
||
'<label class="layui-form-label">'+ key+'</label>'+
|
||
'<div class="layui-input-block">'+
|
||
'<input type="text" id="'+ key+'" value="'+property[key]+'" class="layui-input">'+
|
||
'</div>'+
|
||
'</div>';
|
||
}
|
||
}
|
||
divStr += '</div>';
|
||
return divStr
|
||
}
|
||
|
||
function updateFeature(feature) {
|
||
var wfsUrl = "http://localhost:8080/geoserver/wfs";
|
||
var geometryName = feature.getGeometryName();
|
||
var wfsFormat = new ol.format.WFS({geometryName:geometryName});
|
||
var transactionXML = wfsFormat.writeTransaction(null,[feature],null,{
|
||
featureNS:"http://localhost:8080/test",
|
||
featurePrefix:"test",
|
||
featureType:"tiger_roads",
|
||
srsName:"EPSG:3857"
|
||
});
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('POST', wfsUrl);
|
||
xhr.onerror = function(e){
|
||
console.log("修改失败!",e);
|
||
};
|
||
xhr.onload = function() {
|
||
if (xhr.status == 200) {
|
||
var result = wfsFormat.readTransactionResponse(xhr.responseText);
|
||
console.log(result);
|
||
}else{
|
||
console.log("修改失败!",xhr.responseText);
|
||
}
|
||
}
|
||
xhr.setRequestHeader("Content-Type","application/xml");
|
||
xhr.send(new XMLSerializer().serializeToString(transactionXML));
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
修改的要素必须要有id,因为最终发送的Transaction的XML文本中,是通过`GmlObjectId`作为过滤表达式Filter筛选要素的。
|
||
|
||
> 修改操作需要注意,字段的类型。如果所给的属性值于字段类型不匹配或长度越界了,将会修改失败。
|
||
|
||
|
||
|
||
#### 2.4 Delete
|
||
|
||
`<Delete>`用于删除一个或多个要素,跟`<Insert>`、`<Update>`标签一样通过`<Filter>`标签筛选要操作的要素。如果没有使用`<Filter>`标签对要素进行筛选,则该事务中的删除操作将无效。
|
||
|
||
```xml
|
||
<Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<Delete typeName="test:tiger_roads" xmlns:test="http://localhost:8080/test">
|
||
<Filter xmlns="http://www.opengis.net/ogc">
|
||
<FeatureId fid="tiger_roads.8339"/>
|
||
</Filter>
|
||
</Delete>
|
||
</Transaction>
|
||
```
|
||
|
||
删除操作和更新操作一样也是根据Feature的id来进行操作的。这里我们使用`ol.interaction.Select`控件来选择要删除的要素,在确定删除操作成功后,从矢量数据源中移除被删除的要素和清空在`Select`控件中已选要素的集合。
|
||
|
||
```html
|
||
<!doctype html>
|
||
<html>
|
||
<head>
|
||
<link rel="stylesheet" href="css/ol.css" type="text/css">
|
||
<link rel="stylesheet" href="css/layui.css" type="text/css">
|
||
<style>
|
||
.map {
|
||
height: 85vh;
|
||
width: 100%;
|
||
}
|
||
</style>
|
||
<script src="lib/jquery-3.1.1.js"></script>
|
||
<script src="lib/layer.js"></script>
|
||
<script src="lib/ol.js"></script>
|
||
|
||
<title>OpenLayers example</title>
|
||
<meta charset="UTF-8">
|
||
</head>
|
||
<body>
|
||
<h2>OGC WFS服务:Transaction Delete</h2>
|
||
<div id="map" class="map"></div>
|
||
<script type="text/javascript">
|
||
var vectorSource = new ol.source.Vector({
|
||
format: new ol.format.GeoJSON({geometryName:"geom"}),
|
||
loader: function (extent, resolution, projection) {
|
||
var proj = projection.getCode();
|
||
var url = 'http://localhost:8080/geoserver/wfs?service=WFS&' +
|
||
'version=1.1.0&request=GetFeature&typename=test:tiger_roads&' +
|
||
'outputFormat=application/json&srsname=' + proj + '&' +
|
||
'bbox=' + extent.join(',') + ',' + proj;
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('GET', url);
|
||
var onError = function () {
|
||
vectorSource.removeLoadedExtent(extent);
|
||
}
|
||
xhr.onerror = onError;
|
||
xhr.onload = function () {
|
||
if (xhr.status == 200) {
|
||
vectorSource.addFeatures(
|
||
vectorSource.getFormat().readFeatures(xhr.responseText));
|
||
} else {
|
||
onError();
|
||
}
|
||
}
|
||
xhr.send();
|
||
},
|
||
strategy: ol.loadingstrategy.bbox
|
||
});
|
||
var nyc = [-73.92722, 40.774221];
|
||
var map = new ol.Map({
|
||
layers: [
|
||
// new ol.layer.Tile({
|
||
// source: new ol.source.OSM()
|
||
// }),
|
||
new ol.layer.Vector({
|
||
source: vectorSource
|
||
})
|
||
],
|
||
target: 'map',
|
||
view: new ol.View({
|
||
center: ol.proj.fromLonLat(nyc),
|
||
zoom: 11
|
||
})
|
||
})
|
||
|
||
//Transaction update
|
||
var select = new ol.interaction.Select({
|
||
//点击选择要素的容差,单位px
|
||
hitTolerance: 5
|
||
});
|
||
|
||
map.addInteraction(select);
|
||
select.on("select",function(e){
|
||
//获取当前所选的要素集
|
||
var selectFeatures = e.selected;
|
||
if(selectFeatures.length){
|
||
layer.open({
|
||
title:"提示"
|
||
,content:"确定删除【"+selectFeatures[0].getProperties().name+"】!"
|
||
,btn:["确定"]
|
||
, yes: function (index, layero) {
|
||
deleteFeatures(selectFeatures);
|
||
layer.close(index);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
function deleteFeatures(features) {
|
||
var wfsUrl = "http://localhost:8080/geoserver/wfs";
|
||
var geometryName = features[0].getGeometryName();
|
||
var wfsFormat = new ol.format.WFS({geometryName:geometryName});
|
||
var transactionXML = wfsFormat.writeTransaction(null,null,features,{
|
||
featureNS:"http://localhost:8080/test",
|
||
featurePrefix:"test",
|
||
featureType:"tiger_roads",
|
||
srsName:"EPSG:3857"
|
||
});
|
||
var xhr = new XMLHttpRequest();
|
||
xhr.open('POST', wfsUrl);
|
||
xhr.onerror = function(e){
|
||
console.log("删除失败!",e);
|
||
};
|
||
xhr.onload = function() {
|
||
if (xhr.status == 200) {
|
||
var result = wfsFormat.readTransactionResponse(xhr.responseText);
|
||
console.log(result);
|
||
vectorSource.removeFeature(features[0]);
|
||
select.getFeatures().clear()
|
||
}else{
|
||
console.log("删除失败!",xhr.responseText);
|
||
}
|
||
}
|
||
xhr.setRequestHeader("Content-Type","application/xml");
|
||
xhr.send(new XMLSerializer().serializeToString(transactionXML));
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
|
||
|
||
|
||
|
||
### 3 WFS运算示例
|
||
|
||
> WFS版本使用1.1.0
|
||
|
||
#### 3.1 简单查询
|
||
|
||
1. 查询该服务(图层)的所有要素
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states"></wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
2. 指定返回的结果集中要素的属性(属性名称需要大写,XML是大小写敏感的,且需要添加工作空间)
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<wfs:PropertyName>topp:STATE_NAME</wfs:PropertyName>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
3. 指定响应数据的格式
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<wfs:PropertyName>topp:STATE_NAME</wfs:PropertyName>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
4. 查询多个服务(图层)
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states"></wfs:Query>
|
||
<wfs:Query typeName="tiger:tiger_roads"></wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
#### 3.2 比较运算
|
||
|
||
比较运算符可以说是表达式,应该放在Filter标签里面
|
||
|
||
1. 查找哪个州的总人口person等于3145585.0
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<ogc:Filter>
|
||
<ogc:PropertyIsEqualTo>
|
||
<ogc:PropertyName>topp:PERSONS</ogc:PropertyName>
|
||
<ogc:Literal>3145585.0</ogc:Literal>
|
||
</ogc:PropertyIsEqualTo>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
2. 模糊匹配,州名称以W开头的
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<ogc:Filter>
|
||
<ogc:PropertyIsLike wildCard="*" singleChar="." escape="!">
|
||
<ogc:PropertyName>topp:STATE_NAME</ogc:PropertyName>
|
||
<ogc:Literal>W*</ogc:Literal>
|
||
</ogc:PropertyIsLike>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
wildCard :指定匹配零个或多个字符串字符的任何序列的模式字符
|
||
singleChar :指定匹配任何单个字符串字符的模式字符
|
||
escapeChar :指定可用于转义模式字符的转义字符
|
||
|
||
3. 查询state_name属性为null的记录
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:topp="http://www.openplans.org/topp"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="topp:states">
|
||
<ogc:Filter>
|
||
<ogc:PropertyIsNull>
|
||
<ogc:PropertyName>topp:STATE_NAME</ogc:PropertyName>
|
||
</ogc:PropertyIsNull>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
4. 查询人口总数在[2477574,4781468]之间的州,并根据总人口persons属性倒序排序
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="test:states">
|
||
<wfs:PropertyName>test:persons</wfs:PropertyName>
|
||
<ogc:Filter>
|
||
<ogc:PropertyIsBetween>
|
||
<ogc:PropertyName>test:persons</ogc:PropertyName>
|
||
<ogc:LowerBoundary><ogc:Literal>2477574</ogc:Literal></ogc:LowerBoundary>
|
||
<ogc:UpperBoundary><ogc:Literal>4781468</ogc:Literal></ogc:UpperBoundary>
|
||
</ogc:PropertyIsBetween>
|
||
</ogc:Filter>
|
||
<ogc:SortBy>
|
||
<ogc:SortProperty>
|
||
<ogc:PropertyName>test:persons</ogc:PropertyName>
|
||
<ogc:SortOrder>DESC</ogc:SortOrder>
|
||
</ogc:SortProperty>
|
||
</ogc:SortBy>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
注意:
|
||
|
||
- 需要将state的shapefile文件导入postgresql中,发布postgis表的数据图层,否则将会因为无法序列化,而不能排序
|
||
- 入库后,postgresql表中的属性字段是默认小写的,所以PropertyName标签中的属性值应小写
|
||
- 用于排序的字段必须是结果集中存在的字段,即存在标签\<wfs:PropertyName>值为排序属性
|
||
|
||
#### 3.3空间运算
|
||
|
||
1. Intersects:相交
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="test:tiger_roads">
|
||
<wfs:PropertyName>test:cfcc</wfs:PropertyName>
|
||
<wfs:PropertyName>test:name</wfs:PropertyName>
|
||
<ogc:Filter>
|
||
<Intersects>
|
||
<PropertyName>geom</PropertyName>
|
||
<gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/3857">
|
||
<gml:lowerCorner>-8236751.648901709 4974597.071767016</gml:lowerCorner>
|
||
<gml:upperCorner>-8235757.967534002 4975476.097592296</gml:upperCorner>
|
||
</gml:Envelope>
|
||
</Intersects>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||

|
||
|
||
2. Disjoint:不相交。下面将逻辑运算和空间运算结合(取不相交的非,得到与上面1一样的结果)
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="test:tiger_roads">
|
||
<wfs:PropertyName>test:cfcc</wfs:PropertyName>
|
||
<wfs:PropertyName>test:name</wfs:PropertyName>
|
||
<ogc:Filter>
|
||
<Not>
|
||
<Disjoint>
|
||
<PropertyName>geom</PropertyName>
|
||
<gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/3857">
|
||
<gml:lowerCorner>-8236751.648901709 4974597.071767016</gml:lowerCorner>
|
||
<gml:upperCorner>-8235757.967534002 4975476.097592296</gml:upperCorner>
|
||
</gml:Envelope>
|
||
</Disjoint>
|
||
</Not>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
3. Contains:判断几何对象是否包含另一个几何(几何属性的要素是否包含所给的几何对象)
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="test:tiger_roads">
|
||
<wfs:PropertyName>test:cfcc</wfs:PropertyName>
|
||
<wfs:PropertyName>test:name</wfs:PropertyName>
|
||
<ogc:Filter>
|
||
<Intersects>
|
||
<PropertyName>geom</PropertyName>
|
||
<gml:Point srsName="http://www.opengis.net/def/crs/EPSG/0/3857">
|
||
<gml:pos>-8234663.297809127 4976806.185109221</gml:pos>
|
||
</gml:Point>
|
||
</Intersects>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||
常见的包含关系存在于线包含点,面包含线。
|
||
|
||
4. Within:判断几何属性字段中的几何要素是否被给定的另一个几何对象包含
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:GetFeature service="WFS" version="1.1.0"
|
||
outputFormat="application/json"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs
|
||
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
|
||
<wfs:Query typeName="test:tiger_roads">
|
||
<wfs:PropertyName>test:cfcc</wfs:PropertyName>
|
||
<wfs:PropertyName>test:name</wfs:PropertyName>
|
||
<ogc:Filter>
|
||
<Within>
|
||
<PropertyName>geom</PropertyName>
|
||
<gml:Polygon srsName="http://www.opengis.net/def/crs/EPSG/0/3857">
|
||
<gml:exterior>
|
||
<gml:LinearRing>
|
||
<gml:posList srsDimension="2">-8236070.085302306 4974636.883205217 -8234716.512732034 4974464.899891576 -8234716.512732034 4973573.134464388 -8236391.757990729 4973614.537951903 -8236070.085302306 4974636.883205217</gml:posList>
|
||
</gml:LinearRing>
|
||
</gml:exterior>
|
||
</gml:Polygon>
|
||
</Within>
|
||
</ogc:Filter>
|
||
</wfs:Query>
|
||
</wfs:GetFeature>
|
||
```
|
||
|
||

|
||
|
||
|
||
#### 3.4 Transaction
|
||
|
||
1. Insert
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:Transaction
|
||
version="1.1.0"
|
||
service="WFS"
|
||
xmlns="http://www.someserver.com/myns"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.someserver.com/myns
|
||
http://www.someserver.com/wfs/cwwfs.cgi?
|
||
http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd">
|
||
<wfs:Insert inputFormat="text/xml;subtype=2.1.2" idgen="UseExisting">
|
||
<test:tiger_roads gml:id="10002">
|
||
<cfcc>A94</cfcc>
|
||
<name>测试</name>
|
||
<geom>
|
||
<MultiLineString srsName="EPSG:3857">
|
||
<lineStringMember>
|
||
<LineString>
|
||
<coordinates>-8237795.685217111,4980323.905513588 -8238827.585098961,4978584.963120101</coordinates>
|
||
</LineString>
|
||
</lineStringMember>
|
||
</MultiLineString>
|
||
</geom>
|
||
</test:tiger_roads>
|
||
</wfs:Insert>
|
||
</wfs:Transaction>
|
||
```
|
||
|
||
2. update
|
||
|
||
```xml
|
||
<?xml version="1.0"?>
|
||
<wfs:Transaction
|
||
version="1.1.0"
|
||
service="WFS"
|
||
xmlns="http://www.someserver.com/myns"
|
||
xmlns:gml="http://www.opengis.net/gml"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:test="http://localhost:8080/test"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.someserver.com/myns
|
||
http://www.someserver.com/wfs/cwwfs.cgi?
|
||
http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd">
|
||
<wfs:Update typeName="tiger_roads">
|
||
<wfs:Property>
|
||
<wfs:Name>name</wfs:Name>
|
||
<wfs:Value>测试Insert312</wfs:Value>
|
||
</wfs:Property>
|
||
<ogc:Filter>
|
||
<ogc:GmlObjectId gml:id="tiger_roads.8338"/>
|
||
</ogc:Filter>
|
||
</wfs:Update>
|
||
</wfs:Transaction>
|
||
```
|
||
|
||
|
||
|
||
3. delete
|
||
|
||
```xml
|
||
<?xml version="1.0" ?>
|
||
<wfs:Transaction
|
||
version="1.1.0"
|
||
service="WFS"
|
||
xmlns="http://www.someserver.com/myns"
|
||
xmlns:ogc="http://www.opengis.net/ogc"
|
||
xmlns:wfs="http://www.opengis.net/wfs"
|
||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||
xsi:schemaLocation="http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd">
|
||
<wfs:Delete typeName="tiger_roads">
|
||
<ogc:Filter>
|
||
<ogc:GmlObjectId gml:id="tiger_roads.8337"/>
|
||
</ogc:Filter>
|
||
</wfs:Delete>
|
||
</wfs:Transaction>
|
||
```
|
||
|
||
|
||
|
||
### 参考文章
|
||
|
||
[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`
|
||
|
||
|
||
|
||
|
||
|