Skip to content

Commit

Permalink
[WFS provider] Do not emit initial COUNT=1 GetFeature request if Desc…
Browse files Browse the repository at this point in the history
…ribeFeatureType advertizes gmlId, gmlName and gmlDescription fields
  • Loading branch information
rouault committed Jan 3, 2023
1 parent 0175806 commit acd7d02
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -245,10 +245,17 @@ void QgsWFSProvider::issueInitialGetFeature()
}
// For WFS >= 1.1, by default, issue a GetFeature on one feature to check
// if gml:description, gml:identifier, gml:name attributes are
// present (unless mShared->mURI.skipInitialGetFeature() returns false)
// present (unless mShared->mURI.skipInitialGetFeature() returns false),
// unless gmlId, gmlName, gmlDescription fields are found (some servers use
// that hack since gml:description/identifier/name attributes might be
// missed by clients...).
// Another reason to issue it if we do not known the exact geometry type
// from describeFeatureType()
else if ( !mShared->mWFSVersion.startsWith( QLatin1String( "1.0" ) ) )
else if ( !mShared->mWFSVersion.startsWith( QLatin1String( "1.0" ) ) &&
( mShared->mWKBType == QgsWkbTypes::Unknown ||
mShared->mFields.indexOf( QLatin1String( "gmlId" ) ) < 0 ||
mShared->mFields.indexOf( QLatin1String( "gmlName" ) ) < 0 ||
mShared->mFields.indexOf( QLatin1String( "gmlDescription" ) ) < 0 ) )
{
// Try to see if gml:description, gml:identifier, gml:name attributes are
// present. So insert them temporarily in mShared->mFields so that the
Expand Down
71 changes: 71 additions & 0 deletions tests/src/python/test_provider_wfs.py
Expand Up @@ -5638,6 +5638,77 @@ def testLayerWithFieldsInGMLNamespace(self):
values = [f['intfield'] for f in vl.getFeatures()]
self.assertEqual(values, [1])

def testLayerWith_gmlId_gmlName_gmlDescription_fields(self):
""" https://github.com/qgis/QGIS/pull/51144#issuecomment-1350590774 """

endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_layer_with_gmlId_gmlName_gmlDescription_fields'

with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=2.0.0'), 'wb') as f:
f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0">
<FeatureTypeList>
<FeatureType>
<Name>my:typename</Name>
<Title>Title</Title>
<Abstract>Abstract</Abstract>
<DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
<WGS84BoundingBox>
<LowerCorner>-71.123 66.33</LowerCorner>
<UpperCorner>-65.32 78.3</UpperCorner>
</WGS84BoundingBox>
</FeatureType>
</FeatureTypeList>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

with open(sanitize(endpoint,
'?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAMES=my:typename&TYPENAME=my:typename'),
'wb') as f:
f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
<xsd:import namespace="http://www.opengis.net/gml"/>
<xsd:complexType name="typenameType">
<xsd:complexContent>
<xsd:extension base="gml:AbstractFeatureType">
<xsd:sequence>
<xsd:element name="gmlId" type="xsd:string"/>
<xsd:element name="gmlName" minOccurs="0" type="xsd:string"/>
<xsd:element name="gmlDescription" minOccurs="0" type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
<xsd:element maxOccurs="1" minOccurs="0" name="geometry" nillable="true" type="gml:PointPropertyType"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""".encode('UTF-8'))

with open(sanitize(endpoint,
"""?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326"""),
'wb') as f:
f.write("""
<wfs:FeatureCollection
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:my="http://my">
<wfs:member>
<my:typename gml:id="typename.0">
<!-- test that this request is *not* emitted ! If it was emitted then we would get 7 fields -->
<gml:description>gml_description</gml:description>
<gml:identifier>gml_identifier</gml:identifier>
<gml:name>gml_name</gml:name>
<my:intfield>1</my:intfield>
<my:geometry><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>78.3 -65.32</gml:pos></gml:Point></my:geometry>
</my:typename>
</wfs:member>
</wfs:FeatureCollection>""".encode('UTF-8'))

vl = QgsVectorLayer(
"url='http://" + endpoint + "' typename='my:typename' version='2.0.0'",
'test', 'WFS')
self.assertTrue(vl.isValid())
self.assertEqual(len(vl.fields()), 4)

def _createBaseFilesForTestsDeegreeServerWithUnknownGeometryType(self, endpoint):

# Cf https://xplanung.freiburg.de/xplansyn-wfs/services/xplansynwfs?SERVICE=WFS&REQUEST=GetCapabilities&VERSION=2.0.0
Expand Down

0 comments on commit acd7d02

Please sign in to comment.