Skip to content

Commit 1e09a27

Browse files
klavspcrouault
authored andcommittedMay 25, 2019
[WFS provider] Improve handling of NAMESPACE(S) (github #9849)
Modified by E. Rouault
1 parent 31c25e4 commit 1e09a27

9 files changed

+84
-27
lines changed
 

‎src/providers/wfs/qgswfscapabilities.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,32 @@ QString QgsWfsCapabilities::Capabilities::addPrefixIfNeeded( const QString &name
8888
return mapUnprefixedTypenameToPrefixedTypename[name];
8989
}
9090

91+
QString QgsWfsCapabilities::Capabilities::getNamespaceForTypename( const QString &name ) const
92+
{
93+
Q_FOREACH ( const QgsWfsCapabilities::FeatureType &f, featureTypes )
94+
{
95+
if ( f.name == name )
96+
{
97+
return f.nameSpace;
98+
}
99+
}
100+
return "";
101+
}
102+
103+
QString QgsWfsCapabilities::Capabilities::getNamespaceParameterValue( const QString &WFSVersion, const QString &typeName ) const
104+
{
105+
QString namespaces = getNamespaceForTypename( typeName );
106+
bool tryNameSpacing = ( !namespaces.isEmpty() && typeName.contains( ':' ) );
107+
if ( tryNameSpacing )
108+
{
109+
QString prefixOfTypename = typeName.section( ':', 0, 0 );
110+
return "xmlns(" + prefixOfTypename +
111+
( WFSVersion.startsWith( QLatin1String( "2.0" ) ) ? "," : "=" ) +
112+
namespaces + ")";
113+
}
114+
return QString();
115+
}
116+
91117
class CPLXMLTreeUniquePointer
92118
{
93119
public:
@@ -405,6 +431,14 @@ void QgsWfsCapabilities::capabilitiesReplyFinished()
405431
if ( psFeatureTypeIter )
406432
{
407433
featureType.nameSpace = CPLGetXMLValue( psFeatureTypeIter, ( "xmlns:" + prefixOfTypename ).toUtf8().constData(), "" );
434+
if ( featureType.nameSpace.isEmpty() )
435+
{
436+
//Try to look for namespace in Name tag (Seen in GO Publisher)
437+
//<wfs:FeatureType>
438+
// <wfs:Name xmlns:dagi="http://data.gov.dk/schemas/dagi/2/gml3sfp">dagi:Menighedsraadsafstemningsomraade</wfs:Name>
439+
// <wfs:Title>Menighedsraadsafstemningsomraade</wfs:Title>
440+
featureType.nameSpace = CPLGetXMLValue( psFeatureTypeIter, ( "wfs:Name.xmlns:" + prefixOfTypename ).toUtf8().constData(), "" );
441+
}
408442
}
409443
}
410444
}
@@ -809,3 +843,4 @@ QString QgsWfsCapabilities::errorMessageWithReason( const QString &reason )
809843
{
810844
return tr( "Download of capabilities failed: %1" ).arg( reason );
811845
}
846+

‎src/providers/wfs/qgswfscapabilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class QgsWfsCapabilities : public QgsWfsRequest
108108

109109
void clear();
110110
QString addPrefixIfNeeded( const QString &name ) const;
111+
QString getNamespaceForTypename( const QString &name ) const;
112+
QString getNamespaceParameterValue( const QString &WFSVersion, const QString &typeName ) const;
111113
};
112114

113115
//! Returns parsed capabilities - requestCapabilities() must be called before

‎src/providers/wfs/qgswfsdescribefeaturetype.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,27 @@
1414
***************************************************************************/
1515

1616
#include "qgswfsdescribefeaturetype.h"
17+
#include "qgsmessagelog.h"
1718

1819
QgsWFSDescribeFeatureType::QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri )
1920
: QgsWfsRequest( uri )
2021
{
2122
}
2223

2324
bool QgsWFSDescribeFeatureType::requestFeatureType( const QString &WFSVersion,
24-
const QString &typeName, bool bUsePlural )
25+
const QString &typeName, const QgsWfsCapabilities::Capabilities &caps, bool bUsePlural )
2526
{
2627
QUrl url( mUri.requestUrl( QStringLiteral( "DescribeFeatureType" ) ) );
2728
url.addQueryItem( QStringLiteral( "VERSION" ), WFSVersion );
29+
2830
url.addQueryItem( bUsePlural ?
2931
QStringLiteral( "TYPENAMES" ) : QStringLiteral( "TYPENAME" ), typeName );
32+
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
33+
if ( !namespaceValue.isEmpty() )
34+
{
35+
url.addQueryItem( bUsePlural ?
36+
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
37+
}
3038

3139
return sendGET( url, true, false );
3240
}

‎src/providers/wfs/qgswfsdescribefeaturetype.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define QGSWFSDESCRIBEFEATURETYPE_H
1717

1818
#include "qgswfsrequest.h"
19+
#include "qgswfscapabilities.h"
1920

2021
//! Manages the DescribeFeatureType request
2122
class QgsWFSDescribeFeatureType : public QgsWfsRequest
@@ -25,7 +26,10 @@ class QgsWFSDescribeFeatureType : public QgsWfsRequest
2526
explicit QgsWFSDescribeFeatureType( QgsWFSDataSourceURI &uri );
2627

2728
//! Issue the request
28-
bool requestFeatureType( const QString &WFSVersion, const QString &typeName, bool bUsePlural );
29+
bool requestFeatureType( const QString &WFSVersion,
30+
const QString &typeName,
31+
const QgsWfsCapabilities::Capabilities &caps,
32+
bool bUsePlural );
2933

3034
protected:
3135
QString errorMessageWithReason( const QString &reason ) override;

‎src/providers/wfs/qgswfsfeatureiterator.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -222,22 +222,7 @@ QUrl QgsWFSFeatureDownloader::buildURL( qint64 startIndex, int maxFeatures, bool
222222
if ( mShared->mLayerPropertiesList.isEmpty() )
223223
{
224224
typenames = mShared->mURI.typeName();
225-
226-
// Add NAMESPACES parameter for server that declare a namespace in the FeatureType of GetCapabilities response
227-
// See https://issues.qgis.org/issues/14685
228-
Q_FOREACH ( const QgsWfsCapabilities::FeatureType &f, mShared->mCaps.featureTypes )
229-
{
230-
if ( f.name == typenames )
231-
{
232-
if ( !f.nameSpace.isEmpty() && f.name.contains( ':' ) )
233-
{
234-
QString prefixOfTypename = f.name.section( ':', 0, 0 );
235-
namespaces = "xmlns(" + prefixOfTypename + "," + f.nameSpace + ")";
236-
}
237-
break;
238-
}
239-
}
240-
225+
namespaces = mShared->mCaps.getNamespaceParameterValue( mShared->mWFSVersion, typenames );
241226
}
242227
else
243228
{

‎src/providers/wfs/qgswfsprovider.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ bool QgsWFSProvider::processSQL( const QString &sqlString, QString &errorMsg, QS
430430
for ( int i = 0; i < 2; i++ )
431431
{
432432
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
433-
concatenatedTypenames, bUsePlural ) )
433+
concatenatedTypenames, mShared->mCaps, bUsePlural ) )
434434
{
435435
errorMsg = tr( "DescribeFeatureType failed for url %1: %2" ).
436436
arg( dataSourceUri(), describeFeatureType.errorMessage() );
@@ -1285,12 +1285,14 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
12851285
fields.clear();
12861286

12871287
QgsWFSDescribeFeatureType describeFeatureType( mShared->mURI );
1288+
12881289
bool bUsePlural = false;
12891290
QByteArray response;
1291+
12901292
for ( int i = 0; i < 2; i++ )
12911293
{
12921294
if ( !describeFeatureType.requestFeatureType( mShared->mWFSVersion,
1293-
mShared->mURI.typeName(), bUsePlural ) )
1295+
mShared->mURI.typeName(), mShared->mCaps, bUsePlural ) )
12941296
{
12951297
QgsMessageLog::logMessage( tr( "DescribeFeatureType network request failed for url %1: %2" ).
12961298
arg( dataSourceUri(), describeFeatureType.errorMessage() ), tr( "WFS" ) );

‎src/providers/wfs/qgswfsshareddata.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,8 +1274,7 @@ int QgsWFSSharedData::getFeatureCount( bool issueRequestIfNeeded )
12741274
{
12751275
mGetFeatureHitsIssued = true;
12761276
QgsWFSFeatureHitsRequest request( mURI );
1277-
int featureCount = request.getFeatureCount( mWFSVersion, mWFSFilter );
1278-
1277+
int featureCount = request.getFeatureCount( mWFSVersion, mWFSFilter, mCaps );
12791278
{
12801279
QMutexLocker locker( &mMutex );
12811280
// Check the return value. Might be -1 in case of error, or might be
@@ -1347,14 +1346,28 @@ QgsWFSFeatureHitsRequest::QgsWFSFeatureHitsRequest( QgsWFSDataSourceURI &uri )
13471346
}
13481347

13491348
int QgsWFSFeatureHitsRequest::getFeatureCount( const QString &WFSVersion,
1350-
const QString &filter )
1349+
const QString &filter, const QgsWfsCapabilities::Capabilities &caps )
13511350
{
1351+
QString typeName = mUri.typeName();
1352+
13521353
QUrl getFeatureUrl( mUri.requestUrl( QStringLiteral( "GetFeature" ) ) );
13531354
getFeatureUrl.addQueryItem( QStringLiteral( "VERSION" ), WFSVersion );
13541355
if ( WFSVersion.startsWith( QLatin1String( "2.0" ) ) )
1355-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), mUri.typeName() );
1356+
{
1357+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), typeName );
1358+
}
13561359
else
1357-
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
1360+
{
1361+
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), typeName );
1362+
}
1363+
1364+
QString namespaceValue( caps.getNamespaceParameterValue( WFSVersion, typeName ) );
1365+
if ( !namespaceValue.isEmpty() )
1366+
{
1367+
getFeatureUrl.addQueryItem( WFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1368+
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1369+
}
1370+
13581371
if ( !filter.isEmpty() )
13591372
{
13601373
getFeatureUrl.addQueryItem( QStringLiteral( "FILTER" ), filter );
@@ -1415,6 +1428,14 @@ QgsRectangle QgsWFSSingleFeatureRequest::getExtent()
14151428
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAMES" ), mUri.typeName() );
14161429
else
14171430
getFeatureUrl.addQueryItem( QStringLiteral( "TYPENAME" ), mUri.typeName() );
1431+
1432+
QString namespaceValue( mShared->mCaps.getNamespaceParameterValue( mShared->mWFSVersion, mUri.typeName() ) );
1433+
if ( !namespaceValue.isEmpty() )
1434+
{
1435+
getFeatureUrl.addQueryItem( mShared->mWFSVersion.startsWith( QLatin1String( "2.0" ) ) ?
1436+
QStringLiteral( "NAMESPACES" ) : QStringLiteral( "NAMESPACE" ), namespaceValue );
1437+
}
1438+
14181439
if ( mShared->mWFSVersion .startsWith( QLatin1String( "2.0" ) ) )
14191440
getFeatureUrl.addQueryItem( QStringLiteral( "COUNT" ), QString::number( 1 ) );
14201441
else

‎src/providers/wfs/qgswfsshareddata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ class QgsWFSFeatureHitsRequest: public QgsWfsRequest
289289
explicit QgsWFSFeatureHitsRequest( QgsWFSDataSourceURI &uri );
290290

291291
//! Returns the feature count, or -1 in case of error
292-
int getFeatureCount( const QString &WFSVersion, const QString &filter );
292+
int getFeatureCount( const QString &WFSVersion, const QString &filter, const QgsWfsCapabilities::Capabilities &caps );
293293

294294
protected:
295295
QString errorMessageWithReason( const QString &reason ) override;

‎tests/src/python/test_provider_wfs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2984,7 +2984,7 @@ def testGetFeatureWithNamespaces(self):
29842984
</wfs:FeatureTypeList>
29852985
</wfs:WFS_Capabilities>""".encode('UTF-8'))
29862986

2987-
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
2987+
with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename&NAMESPACE=xmlns(my,http://my)'), 'wb') as f:
29882988
f.write("""
29892989
<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">
29902990
<xsd:import namespace="http://www.opengis.net/gml"/>

0 commit comments

Comments
 (0)
Please sign in to comment.