大赵传奇

GIS解决方案,webgis , 桌面、数据、服务--QQ276605216

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

geoserver 2.20.4

postgis: SELECT PostGIS_full_version();

POSTGIS="3.2.0 3.2.0" [EXTENSION] PGSQL="130" GEOS="3.10.1-CAPI-1.16.0" PROJ="7.2.1" LIBXML="2.9.9" LIBJSON="0.12" LIBPROTOBUF="1.2.1" WAGYU="0.5.0 (Internal)"

postgresql: SELECT version();

PostgreSQL 13.5, compiled by Visual C++ build 1914, 64-bit

openlayers: "ol": "^9.1.0",

参考9.2.24 api:

OpenLayers v9.2.4 API - Class: WFS

先测试一下。使用qgis 画一个面,在dbeaver中复制出来,在geoserver 演示这里编辑,点击提交之后是这样

 geom里的字段要和postgis里的一致,像这样:如果写不一样,如the_geom, 插入的记录就会geom是空的

 完整xml:

<wfs:Transaction service="WFS" version="1.0.0"
    xmlns:wfs="http://www.opengis.net/wfs"
    xmlns:gml="http://www.opengis.net/gml"
    xmlns:ysc="ysc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd
                        ysc http://192.168.9.158:9092/geoserver/project01/wfs/DescribeFeatureType?typename=project01:sheng">
    <wfs:Insert>
        <ysc:sheng>
            <ysc:geom>
                <gml:MultiPolygon srsName="EPSG:4326">
                    <gml:polygonMember>
                        <gml:Polygon>
                            <gml:outerBoundaryIs>
                                <gml:LinearRing>
                                    <gml:coordinates decimal="." cs="," ts=" ">
                                        117.24109987655501,32.97967999727664 
                                        118.04820218611013,33.00850507976075 
                                        118.05396720260696,32.633779007467304 
                                        117.25839492604548,32.63954402396413 
                                        117.24109987655501,32.97967999727664
                                    </gml:coordinates>
                                </gml:LinearRing>
                            </gml:outerBoundaryIs>
                        </gml:Polygon>
                    </gml:polygonMember>
                </gml:MultiPolygon>
            </ysc:geom>
            <ysc:TYPE>alley</ysc:TYPE>
        </ysc:sheng>
    </wfs:Insert>
</wfs:Transaction>

注意我这里的命名空间没写规范,但也通过了

 如果命名空间写得不对就报Feature type 'sheng' is not available:

 如果命名空间不写,就报error on line 7 at column 22: Encoding error, 其实根本找不出line7 哪里错误

 坐标的注意点:小数点用decimal="." 经纬度之间用cs="," 坐标之间用空格ts=" " 要仔细看坐标后是不是带了空格

<gml:coordinates decimal="." cs="," ts=" ">
   117.24109987655501,32.97967999727664 
   118.04820218611013,33.00850507976075 
   118.05396720260696,32.633779007467304 
   117.25839492604548,32.63954402396413 
   117.24109987655501,32.97967999727664 
</gml:coordinates>

空格多一个也是允许的:

 使用openlayers提交

//创建feature
    var newFeature = new Feature();
    newFeature.setGeometryName('geom'); //关键,这里必须要和postgis库里的图形字段名geom 一致
    newFeature.setGeometry(new MultiPolygon([[[  //GeoServer 的 WFS 1.1.0 默认遵循 OGC 标准,即 EPSG:4326 的坐标顺序是 [纬度, 经度]
        //WFS 1.0.0 更灵活,可以支持 [经度, 纬度]。
      [32.97967999727664, 117.24109987655501],
      [33.00850507976075, 118.04820218611013],
      [32.633779007467304, 118.05396720260696],
      [32.63954402396413, 117.25839492604548],
      [32.97967999727664, 117.24109987655501]
    ]]]));
    newFeature.set('gml_id','999-1');  //设置属性字段gml_id

    const featureRequest = new WFS().writeTransaction([newFeature], null, null, {
      featureNS: "ysc",
      featureType: 'sheng',  // 注意:这里应该是字符串,不能用数组
      srsName: "EPSG:4326",
    })

    let str = new XMLSerializer().serializeToString(featureRequest)
    axios.post('http://192.168.9.158:9092/geoserver/project01/wfs', str, {
      headers: {'Content-Type': 'text/xml'},
    }).then((res)=>{
      console.log('响应:', res.data);
    }).catch((err) => {
      console.error('错误:', err.response ? err.response.data : err.message);
    })

 

 

这里的str 默认生成的是 1.1.0标准:

"
<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">
    <Insert>
        <sheng
            xmlns="ysc">
            <geom>
                <MultiPolygon
                    xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
                    <polygonMember>
                        <Polygon srsName="EPSG:4326">
                            <exterior>
                                <LinearRing srsName="EPSG:4326">
                                    <posList srsDimension="2">117.24109987655501 32.97967999727664 118.04820218611013 33.00850507976075 118.05396720260696 32.633779007467304 117.25839492604548 32.63954402396413 117.24109987655501 32.97967999727664</posList>
                                </LinearRing>
                            </exterior>
                        </Polygon>
                    </polygonMember>
                </MultiPolygon>
            </geom>
            <gml_id>999-1</gml_id>
        </sheng>
    </Insert>
</Transaction>"

强制替换为 格式:

//创建feature
    var newFeature = new Feature();
    newFeature.setGeometryName('geom'); //关键,这里必须要和postgis库里的图形字段名geom 一致
    newFeature.setGeometry(new MultiPolygon([[[  //GeoServer 的 WFS 1.1.0 默认遵循 OGC 标准,即 EPSG:4326 的坐标顺序是 [纬度, 经度]
        //WFS 1.0.0 更灵活,可以支持 [经度, 纬度]。
      [32.97967999727664, 117.24109987655501],
      [33.00850507976075, 118.04820218611013],
      [32.633779007467304, 118.05396720260696],
      [32.63954402396413, 117.25839492604548],
      [32.97967999727664, 117.24109987655501]
    ]]]));
    newFeature.set('gml_id','999-1');  //设置属性字段gml_id

    const featureRequest = new WFS().writeTransaction([newFeature], null, null, {
      featureNS: "ysc",
      featureType: 'sheng',  // 注意:这里应该是字符串,不能用数组
      srsName: "EPSG:4326",
    })

    let str = new XMLSerializer().serializeToString(featureRequest)
    // 替换posList为coordinates(如果需要)
    str = str.replace(/<posList[^>]*>([^<]*)<\/posList>/g, function(match, coords) {
      return `<coordinates decimal="." cs="," ts=",">${coords.replace(/ /g, ',')}</coordinates>`;
    });

    axios.post('http://192.168.9.158:9092/geoserver/project01/wfs', str, {
      headers: {'Content-Type': 'text/xml'},
    }).then((res)=>{
      console.log('响应:', res.data);
    }).catch((err) => {
      console.error('错误:', err.response ? err.response.data : err.message);
    })

 

"
<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">
    <Insert>
        <sheng
            xmlns="ysc">
            <geom>
                <MultiPolygon
                    xmlns="http://www.opengis.net/gml" srsName="EPSG:4326">
                    <polygonMember>
                        <Polygon srsName="EPSG:4326">
                            <exterior>
                                <LinearRing srsName="EPSG:4326">
                                    <coordinates decimal="." cs="," ts=",">117.24109987655501,32.97967999727664,118.04820218611013,33.00850507976075,118.05396720260696,32.633779007467304,117.25839492604548,32.63954402396413,117.24109987655501,32.97967999727664</coordinates>
                                </LinearRing>
                            </exterior>
                        </Polygon>
                    </polygonMember>
                </MultiPolygon>
            </geom>
            <gml_id>999-1</gml_id>
        </sheng>
    </Insert>
</Transaction>"

如果指定 1.0.0版本:

 默认或指定 1.1.0版本:

 如果是openlayers 代码画

    createPolygonDraw(callback){
        let polygonDraw = new Draw({
            source: this.GetLayerByTitle('画笔').getSource(),
            type: 'MultiPolygon',
            //geometryName:"geom",//关键点
            style: {
                'circle-radius': 5,
                'circle-fill-color': '#52c41a',
                'stroke-color': '#52c41a',
                'stroke-width': 2,
                'fill-color': 'rgba(82, 196, 26,0.4)',
            }
        });
        polygonDraw.on("drawend", event => {
            if(callback) callback(event)
        })
        ol.Inst().GetMap().addInteraction(polygonDraw)
    }



function draw_polygon_save(){
  ol.Inst().createPolygonDraw((e)=>{
    console.log('event',e)

var newFeature = new Feature(); newFeature.setGeometryName('geom'); newFeature.setGeometry(e.feature.getGeometry()) newFeature.set('gml_id','999-2');

const featureRequest = new WFS().writeTransaction([newFeature], null, null, { featureNS: "ysc", featureType: 'sheng', // 注意:这里应该是字符串,不能用数组 srsName: "EPSG:4326", version: "1.1.0", }) let str = new XMLSerializer().serializeToString(featureRequest) str = str.replace(/<posList[^>]*>([^<]*)<\/posList>/g, (match, coords) => { // 1. 将空格分隔的字符串拆分为数组 const numbers = coords.trim().split(/\s+/); // 2. 检查坐标数量是否为偶数(必须是纬度、经度成对出现) if (numbers.length % 2 !== 0) { console.error("坐标数量不是偶数!", numbers); return match; // 返回原始内容避免破坏XML } // 3. 交换每对值的位置(从 "lon lat" 改为 "lat lon") const swapped = []; for (let i = 0; i < numbers.length; i += 2) { swapped.push(numbers[i + 1], numbers[i]); // 经度 ↔ 纬度 } // 4. 重新组合为空格分隔的字符串 return `<posList srsDimension="2">${swapped.join(" ")}</posList>`; }); axios.post('http://192.168.9.158:9092/geoserver/project01/wfs', str, { headers: {'Content-Type': 'text/xml'}, }).then((res)=>{ console.log('响应:', res.data); }).catch((err) => { console.error('错误:', err.response ? err.response.data : err.message); }) }) }

坐标反转没有好的办法,我使用的版本不同 ?

 

posted on 2025-05-01 04:30  赵长青  阅读(105)  评论(0)    收藏  举报