Server WFS 1.1: honor srsName and axis order

Fixes #45216
This commit is contained in:
Alessandro Pasotti 2021-09-27 14:50:17 +02:00
parent 5b68dc587e
commit 8acfeca8f7
3 changed files with 68 additions and 8 deletions

View File

@ -61,6 +61,10 @@ namespace QgsWfs
const QgsCoordinateReferenceSystem &outputCrs;
bool forceGeomToMulti;
const QString &srsName;
bool hasAxisInverted;
};
QString createFeatureGeoJSON( const QgsFeature &feature, const createFeatureParams &params, const QgsAttributeList &pkAttributes );
@ -424,6 +428,13 @@ namespace QgsWfs
}
else
{
// For WFS 1.1 we honor requested CRS and axis order
const QString srsName {request.serverParameters().value( QStringLiteral( "SRSNAME" ) )};
const bool invertAxis { mWfsParameters.versionAsNumber() >= QgsProjectVersion( 1, 1, 0 ) &&
outputCrs.hasAxisInverted() &&
! srsName.startsWith( QLatin1String( "EPSG:" ) ) };
const createFeatureParams cfp = { layerPrecision,
layerCrs,
attrIndexes,
@ -431,7 +442,9 @@ namespace QgsWfs
withGeom,
geometryName,
outputCrs,
forceGeomToMulti
forceGeomToMulti,
srsName,
invertAxis
};
while ( fit.nextFeature( feature ) && ( aRequest.maxFeatures == -1 || sentFeatures < aRequest.maxFeatures ) )
{
@ -1156,7 +1169,8 @@ namespace QgsWfs
else
query.addQueryItem( QStringLiteral( "VERSION" ), QStringLiteral( "1.0.0" ) );
for ( auto param : query.queryItems() )
const auto queryItems {query.queryItems()};
for ( auto param : std::as_const( queryItems ) )
{
if ( sParamFilter.contains( param.first.toUpper() ) )
query.removeAllQueryItems( param.first );
@ -1203,12 +1217,24 @@ namespace QgsWfs
QDomElement bbElem = doc.createElement( QStringLiteral( "gml:boundedBy" ) );
if ( format == QgsWfsParameters::Format::GML3 )
{
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc, prec );
// For WFS 1.1 we honor requested CRS and axis order
const QString srsName {request.serverParameters().value( QStringLiteral( "SRSNAME" ) )};
const bool invertAxis { mWfsParameters.versionAsNumber() >= QgsProjectVersion( 1, 1, 0 ) &&
crs.hasAxisInverted() &&
! srsName.startsWith( QLatin1String( "EPSG:" ) ) };
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc, srsName, invertAxis, prec );
if ( !envElem.isNull() )
{
if ( crs.isValid() )
{
envElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
if ( mWfsParameters.versionAsNumber() >= QgsProjectVersion( 1, 1, 0 ) )
{
envElem.setAttribute( QStringLiteral( "srsName" ), srsName );
}
else
{
envElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
}
}
bbElem.appendChild( envElem );
doc.appendChild( bbElem );
@ -1473,19 +1499,19 @@ namespace QgsWfs
const QgsAbstractGeometry *abstractGeom = cloneGeom.constGet();
if ( abstractGeom )
{
gmlElem = abstractGeom->asGml3( doc, prec, "http://www.opengis.net/gml" );
gmlElem = abstractGeom->asGml3( doc, prec, "http://www.opengis.net/gml", params.hasAxisInverted ? QgsAbstractGeometry::AxisOrder::YX : QgsAbstractGeometry::AxisOrder::XY );
}
if ( !gmlElem.isNull() )
{
QgsRectangle box = geom.boundingBox();
QDomElement bbElem = doc.createElement( QStringLiteral( "gml:boundedBy" ) );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, prec );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, params.srsName, params.hasAxisInverted, prec );
if ( crs.isValid() )
{
boxElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
gmlElem.setAttribute( QStringLiteral( "srsName" ), crs.authid() );
boxElem.setAttribute( QStringLiteral( "srsName" ), params.srsName );
gmlElem.setAttribute( QStringLiteral( "srsName" ), params.srsName );
}
bbElem.appendChild( boxElem );

View File

@ -506,6 +506,12 @@ class TestQgsServerWFS(QgsServerTestBase):
self.wfs_request_compare(
"GetFeature", '1.0.0', "SRSNAME=EPSG:4326&TYPENAME=testlayer&FEATUREID=testlayer.0", 'wfs_getFeature_1_0_0_featureid_0')
def test_getFeatureFeature11urn(self):
"""Test GetFeature with SRSNAME urn:ogc:def:crs:EPSG::4326"""
self.wfs_request_compare(
"GetFeature", '1.1.0', "SRSNAME=urn:ogc:def:crs:EPSG::4326&TYPENAME=testlayer&FEATUREID=testlayer.0", 'wfs_getFeature_1_1_0_featureid_0_1_1_0')
def test_getFeature_EXP_FILTER_regression_20927(self):
"""Test expressions with EXP_FILTER"""

View File

@ -0,0 +1,28 @@
Content-Type: text/xml; subtype=gml/3.1.1; charset=utf-8
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:qgs="http://www.qgis.org/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 http://www.qgis.org/gml ?MAP=/home/ale/dev/QGIS/tests/testdata/qgis_server/test_project_wfs.qgs&amp;SERVICE=WFS&amp;VERSION=1.1.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=testlayer&amp;OUTPUTFORMAT=text/xml; subtype%3Dgml/3.1.1">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326">
<gml:lowerCorner>44.90139484 8.20345931</gml:lowerCorner>
<gml:upperCorner>44.90148253 8.20354699</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<gml:featureMember>
<qgs:testlayer gml:id="testlayer.0">
<gml:boundedBy>
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326">
<gml:lowerCorner>44.90148253 8.20349634</gml:lowerCorner>
<gml:upperCorner>44.90148253 8.20349634</gml:upperCorner>
</gml:Envelope>
</gml:boundedBy>
<qgs:geometry>
<Point xmlns="http://www.opengis.net/gml" srsName="urn:ogc:def:crs:EPSG::4326">
<pos xmlns="http://www.opengis.net/gml" srsDimension="2">44.90148253 8.20349634</pos>
</Point>
</qgs:geometry>
<qgs:id>1</qgs:id>
<qgs:name>one</qgs:name>
<qgs:utf8nameè>one èé</qgs:utf8nameè>
</qgs:testlayer>
</gml:featureMember>
</wfs:FeatureCollection>