From bc49b5ea84aee01fdc7e0613595317767d58603e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 2 Jul 2017 12:57:06 +0200 Subject: [PATCH] [WFS provider] Do not be confuse by elements that have ref attribute when parsing DescribeFeatureType response; and fix support of (deprecated) ref='gml:XXXXProperty' attributes --- src/providers/wfs/qgswfsprovider.cpp | 21 ++++++-- tests/src/python/test_provider_wfs.py | 70 +++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp index 1a80f0fcc2c7..4465b9a6f7c8 100644 --- a/src/providers/wfs/qgswfsprovider.cpp +++ b/src/providers/wfs/qgswfsprovider.cpp @@ -1279,7 +1279,12 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, } } + // attribute ref + QString ref = attributeElement.attribute( QStringLiteral( "ref" ) ); + QRegExp gmlPT( "gml:(.*)PropertyType" ); + QRegExp gmlRefProperty( "gml:(.*)Property" ); + // gmgml: is Geomedia Web Server if ( type == "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType" ) { @@ -1294,15 +1299,25 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument& schemaDoc, geomType = QGis::WKBMultiLineString; } //is it a geometry attribute? - //MH 090428: sometimes the tags for geometry attributes have only attribute ref="gml:polygonProperty" and no name // the GeometryAssociationType has been seen in #11785 - else if ( type.indexOf( gmlPT ) == 0 || type == "gml:GeometryAssociationType" || name.isEmpty() ) + else if ( type.indexOf( gmlPT ) == 0 || type == "gml:GeometryAssociationType" ) { foundGeometryAttribute = true; geometryAttribute = name; geomType = geomTypeFromPropertyType( geometryAttribute, gmlPT.cap( 1 ) ); } - else //todo: distinguish between numerical and non-numerical types + //MH 090428: sometimes the tags for geometry attributes have only attribute ref="gml:polygonProperty" + //Note: this was deprecated with GML3. + else if ( ref.indexOf( gmlRefProperty ) == 0 ) + { + foundGeometryAttribute = true; + geometryAttribute = ref.mid( 4 ); // Strip gml: prefix + QString propertyType( gmlRefProperty.cap( 1 ) ); + // Set the first character in upper case + propertyType = propertyType.left( 1 ).toUpper() + propertyType.mid( 1 ); + geomType = geomTypeFromPropertyType( geometryAttribute, propertyType ); + } + else if ( !name.isEmpty() ) //todo: distinguish between numerical and non-numerical types { QVariant::Type attributeType = QVariant::String; //string is default type if ( type.contains( "double", Qt::CaseInsensitive ) || type.contains( "float", Qt::CaseInsensitive ) || type.contains( "decimal", Qt::CaseInsensitive ) ) diff --git a/tests/src/python/test_provider_wfs.py b/tests/src/python/test_provider_wfs.py index a1c50f9a9397..ffe4daa00ce2 100644 --- a/tests/src/python/test_provider_wfs.py +++ b/tests/src/python/test_provider_wfs.py @@ -118,11 +118,14 @@ def setUpClass(cls): + + + """.encode('UTF-8')) @@ -2483,6 +2486,73 @@ def testWFS20TransactionsEnabled(self): self.assertNotEqual(vl.dataProvider().capabilities() & vl.dataProvider().EditingCapabilities, 0) self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) + def testDeprecatedGML2GeometryDeclaration(self): + """Test ref="gml:pointProperty" """ + + endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_deprecated_gml2' + + with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f: + f.write(""" + + + + my:typename + Title + Abstract + EPSG:32631 + + + + +""".encode('UTF-8')) + + with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'), 'wb') as f: + f.write(""" + + + + + + + + + + + + + + +""".encode('UTF-8')) + + vl = QgsVectorLayer("url='http://" + endpoint + "' typename='my:typename' version='1.0.0'", 'test', 'WFS') + assert vl.isValid() + self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) + self.assertEqual(len(vl.fields()), 1) + + with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631'), 'wb') as f: + f.write(""" + + unknown + + + + 426858,5427937 + + 1 + + +""".encode('UTF-8')) + + values = [f['INTFIELD'] for f in vl.getFeatures()] + self.assertEqual(values, [1]) + + got_f = [f for f in vl.getFeatures()] + got = got_f[0].geometry().geometry() + self.assertEqual((got.x(), got.y()), (426858.0, 5427937.0)) + if __name__ == '__main__': unittest.main()