@@ -919,7 +919,7 @@ bool QgsWFSProvider::deleteFeatures( const QgsFeatureIds &id )
919
919
transactionDoc.appendChild ( transactionElem );
920
920
// delete element
921
921
QDomElement deleteElem = transactionDoc.createElementNS ( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral ( " Delete" ) );
922
- deleteElem.setAttribute ( QStringLiteral ( " typeName " ), tname );
922
+ deleteElem.setAttribute ( QgsWFSUtils::typeNameParameterForVersion ( mShared -> mWFSVersion ), tname );
923
923
QDomElement filterElem = transactionDoc.createElementNS ( QgsWFSConstants::OGC_NAMESPACE, QStringLiteral ( " Filter" ) );
924
924
925
925
@@ -984,7 +984,7 @@ bool QgsWFSProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
984
984
continue ;
985
985
}
986
986
QDomElement updateElem = transactionDoc.createElementNS ( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral ( " Update" ) );
987
- updateElem.setAttribute ( QStringLiteral ( " typeName " ), tname );
987
+ updateElem.setAttribute ( QgsWFSUtils::typeNameParameterForVersion ( mShared -> mWFSVersion ), tname );
988
988
// Property
989
989
QDomElement propertyElem = transactionDoc.createElementNS ( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral ( " Property" ) );
990
990
QDomElement nameElem = transactionDoc.createElementNS ( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral ( " Name" ) );
@@ -1040,6 +1040,7 @@ QString QgsWFSProvider::convertToXML( const QVariant &value )
1040
1040
return valueStr;
1041
1041
}
1042
1042
1043
+
1043
1044
bool QgsWFSProvider::changeAttributeValues ( const QgsChangedAttributesMap &attr_map )
1044
1045
{
1045
1046
// find out typename from uri and strip namespace prefix
@@ -1065,7 +1066,7 @@ bool QgsWFSProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_
1065
1066
}
1066
1067
1067
1068
QDomElement updateElem = transactionDoc.createElementNS ( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral ( " Update" ) );
1068
- updateElem.setAttribute ( QStringLiteral ( " typeName " ), tname );
1069
+ updateElem.setAttribute ( QgsWFSUtils::typeNameParameterForVersion ( mShared -> mWFSVersion ), tname );
1069
1070
1070
1071
QgsAttributeMap::const_iterator attMapIt = attIt.value ().constBegin ();
1071
1072
for ( ; attMapIt != attIt.value ().constEnd (); ++attMapIt )
@@ -1158,17 +1159,20 @@ QString QgsWFSProvider::translateMetadataValue( const QString &mdKey, const QVar
1158
1159
{
1159
1160
return value.toString ();
1160
1161
}
1161
- };
1162
+ }
1162
1163
1163
- bool QgsWFSProvider::describeFeatureType ( QString &geometryAttribute, QgsFields &fields, QgsWkbTypes::Type &geomType )
1164
+ bool QgsWFSProvider::describeFeatureType ( QString &geometryAttribute,
1165
+ QgsFields &fields,
1166
+ QgsWkbTypes::Type &geomType,
1167
+ bool forceSingularTypeNames )
1164
1168
{
1165
1169
fields.clear ();
1166
1170
1167
1171
QgsWFSDescribeFeatureType describeFeatureType ( mShared ->mURI .uri () );
1168
1172
if ( !describeFeatureType.requestFeatureType ( mShared ->mWFSVersion ,
1169
- mShared ->mURI .typeName () ) )
1173
+ mShared ->mURI .typeName (), forceSingularTypeNames ) )
1170
1174
{
1171
- QgsMessageLog::logMessage ( tr ( " DescribeFeatureType failed for url %1: %2" ).
1175
+ QgsMessageLog::logMessage ( tr ( " DescribeFeatureType network request failed for url %1: %2" ).
1172
1176
arg ( dataSourceUri (), describeFeatureType.errorMessage () ), tr ( " WFS" ) );
1173
1177
return false ;
1174
1178
}
@@ -1180,7 +1184,7 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
1180
1184
if ( !describeFeatureDocument.setContent ( response, true , &errorMsg ) )
1181
1185
{
1182
1186
QgsDebugMsg ( response );
1183
- QgsMessageLog::logMessage ( tr ( " DescribeFeatureType failed for url %1: %2" ).
1187
+ QgsMessageLog::logMessage ( tr ( " DescribeFeatureType XML parse failed for url %1: %2" ).
1184
1188
arg ( dataSourceUri (), errorMsg ), tr ( " WFS" ) );
1185
1189
return false ;
1186
1190
}
@@ -1189,11 +1193,19 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
1189
1193
mShared ->mURI .typeName (),
1190
1194
geometryAttribute, fields, geomType, errorMsg ) )
1191
1195
{
1196
+ // If 2.0.0, let's assume it was a server that only accepted TYPENAME singular form
1197
+ // and try with that ...
1198
+ if ( ! forceSingularTypeNames && mShared ->mWFSVersion .startsWith ( ' 2' ) )
1199
+ {
1200
+ return QgsWFSProvider::describeFeatureType ( geometryAttribute,
1201
+ fields,
1202
+ geomType,
1203
+ true );
1204
+ }
1192
1205
QgsMessageLog::logMessage ( tr ( " Analysis of DescribeFeatureType response failed for url %1: %2" ).
1193
1206
arg ( dataSourceUri (), errorMsg ), tr ( " WFS" ) );
1194
1207
return false ;
1195
1208
}
1196
-
1197
1209
return true ;
1198
1210
}
1199
1211
@@ -1241,6 +1253,20 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument &schemaDoc,
1241
1253
}
1242
1254
elementElement = elementElement.nextSiblingElement ( QStringLiteral ( " element" ) );
1243
1255
}
1256
+ // Try to get a complex type whose name contains the unprefixed typename
1257
+ if ( elementTypeString.isEmpty () && complexTypeElement.isNull () )
1258
+ {
1259
+ const QDomNodeList complexElements = schemaElement.elementsByTagName ( QStringLiteral ( " complexType" ) );
1260
+ for ( int i = 0 ; i < complexElements.size (); i++ )
1261
+ {
1262
+ if ( complexElements.at ( i ).toElement ().attribute ( QStringLiteral ( " name" ) ).contains ( unprefixedTypename ) )
1263
+ {
1264
+ complexTypeElement = complexElements.at ( i ).toElement ();
1265
+ break ;
1266
+ }
1267
+ }
1268
+ }
1269
+ // Give up :(
1244
1270
if ( elementTypeString.isEmpty () && complexTypeElement.isNull () )
1245
1271
{
1246
1272
// "http://demo.deegree.org/inspire-workspace/services/wfs?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=ad:Address"
@@ -1266,7 +1292,6 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument &schemaDoc,
1266
1292
{
1267
1293
errorMsg = tr ( " Cannot find element '%1'" ).arg ( unprefixedTypename );
1268
1294
}
1269
-
1270
1295
return false ;
1271
1296
}
1272
1297
@@ -1337,29 +1362,33 @@ bool QgsWFSProvider::readAttributesFromSchema( QDomDocument &schemaDoc,
1337
1362
QRegExp gmlRefProperty ( " gml:(.*)Property" );
1338
1363
1339
1364
// gmgml: is Geomedia Web Server
1340
- if ( type == QLatin1String ( " gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType" ) )
1365
+ if ( ! foundGeometryAttribute && type == QLatin1String ( " gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType" ) )
1341
1366
{
1342
1367
foundGeometryAttribute = true ;
1343
1368
geometryAttribute = name;
1344
1369
geomType = QgsWkbTypes::MultiPolygon;
1345
1370
}
1346
- else if ( type == QLatin1String ( " gmgml:LineString_Curve_MultiCurve_CompositeCurvePropertyType" ) )
1371
+ else if ( ! foundGeometryAttribute && type == QLatin1String ( " gmgml:LineString_Curve_MultiCurve_CompositeCurvePropertyType" ) )
1347
1372
{
1348
1373
foundGeometryAttribute = true ;
1349
1374
geometryAttribute = name;
1350
1375
geomType = QgsWkbTypes::MultiLineString;
1351
1376
}
1352
1377
// is it a geometry attribute?
1353
1378
// the GeometryAssociationType has been seen in #11785
1354
- else if ( type.indexOf ( gmlPT ) == 0 || type == QLatin1String ( " gml:GeometryAssociationType" ) )
1379
+ else if ( ! foundGeometryAttribute && ( type.indexOf ( gmlPT ) == 0 || type == QLatin1String ( " gml:GeometryAssociationType" ) ) )
1355
1380
{
1356
1381
foundGeometryAttribute = true ;
1357
1382
geometryAttribute = name;
1358
- geomType = geomTypeFromPropertyType ( geometryAttribute, gmlPT.cap ( 1 ) );
1383
+ // We have a choice parent element we cannot assume any valid information over the geometry type
1384
+ if ( attributeElement.parentNode ().nodeName () == QStringLiteral ( " choice" ) && ! attributeElement.nextSibling ().isNull () )
1385
+ geomType = QgsWkbTypes::Unknown;
1386
+ else
1387
+ geomType = geomTypeFromPropertyType ( geometryAttribute, gmlPT.cap ( 1 ) );
1359
1388
}
1360
1389
// MH 090428: sometimes the <element> tags for geometry attributes have only attribute ref="gml:polygonProperty"
1361
1390
// Note: this was deprecated with GML3.
1362
- else if ( ref.indexOf ( gmlRefProperty ) == 0 )
1391
+ else if ( ! foundGeometryAttribute && ref.indexOf ( gmlRefProperty ) == 0 )
1363
1392
{
1364
1393
foundGeometryAttribute = true ;
1365
1394
geometryAttribute = ref.mid ( 4 ); // Strip gml: prefix
@@ -1441,7 +1470,8 @@ QDomElement QgsWFSProvider::createTransactionElement( QDomDocument &doc ) const
1441
1470
describeFeatureTypeURL = QUrl ( QStringLiteral ( " http://fake_qgis_http_endpoint" ) );
1442
1471
describeFeatureTypeURL.addQueryItem ( QStringLiteral ( " REQUEST" ), QStringLiteral ( " DescribeFeatureType" ) );
1443
1472
describeFeatureTypeURL.addQueryItem ( QStringLiteral ( " VERSION" ), QStringLiteral ( " 1.0.0" ) );
1444
- describeFeatureTypeURL.addQueryItem ( QStringLiteral ( " TYPENAME" ), mShared ->mURI .typeName () );
1473
+ // TODO: proper support of 2.0.0, for now hardcoded
1474
+ describeFeatureTypeURL.addQueryItem ( QgsWFSUtils::typeNameParameterForVersion ( WfsVersion ).toUpper (), mShared ->mURI .typeName () );
1445
1475
1446
1476
transactionElem.setAttribute ( QStringLiteral ( " xsi:schemaLocation" ), mApplicationNamespace + ' '
1447
1477
+ describeFeatureTypeURL.toEncoded () );
6 commit comments
palmerj commentedon Apr 30, 2018
@elpaso Did you test this with geoserver instances? See https://issues.qgis.org/issues/18882
elpaso commentedon Apr 30, 2018
Yes: I think I did.
palmerj commentedon Apr 30, 2018
Seems that on the Geoserver instances we are running TYPENAMES doesn't work for the DescribeFeatureType request. Instead it just ignores TYPENAMES and returns schemas for the entire catalogue. Our catalogue is very big.
@rouault Do you have any thoughts about this?
rouault commentedon Apr 30, 2018
I don't understand the commit message "TYPENAME form still works with old 2.0.0". From what I see in http://docs.opengeospatial.org/is/09-025r2/09-025r2.html#142 , TYPENAME is the official parameter name for DescribeFeatureType. So servers requiring TYPENAMES are "buggy" (even if the OGC folks got crazy in changing in GetFeatureType from TYPENAME to TYPENAMES and not doing the same for DescribeFeatureType)
So the logic should be trying first TYPENAME and then TYPENAMES. But as @palmerj underlines a server that ignores a parameter could send the whole catalog. So basically there's no good solution except asking servers to fix their implementation to accept TYPENAME. Or providing a manual switch that knowleadgable users could enable.
palmerj commentedon Apr 30, 2018
Thanks @rouault thanks great information.
So we need to revert this change, then possibly implementing a new advanced switch that provides an override for buggy servers.
palmerj commentedon Apr 30, 2018
@elpaso are you able to comment?