47     struct createFeatureParams
 
   70     QString createFeatureGeoJSON( 
const QgsFeature &feature, 
const createFeatureParams ¶ms, 
const QgsAttributeList &pkAttributes );
 
   74     QDomElement createFeatureGML2( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes );
 
   76     QDomElement createFeatureGML3( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes );
 
   91     QgsWfsParameters mWfsParameters;
 
  104     mWfsParameters.dump();
 
  110     if ( doc.setContent( request.
data(), 
true, &errorMsg ) )
 
  112       QDomElement docElem = doc.documentElement();
 
  121     QStringList typeNameList;
 
  124     bool onlyOneLayer = ( aRequest.
queries.size() == 1 );
 
  127     int requestPrecision = 6;
 
  131     QList<getFeatureQuery>::iterator qIt = aRequest.
queries.begin();
 
  132     for ( ; qIt != aRequest.
queries.end(); ++qIt )
 
  134       typeNameList << ( *qIt ).typeName;
 
  140     QMap<QString, QgsMapLayer *> mapLayerMap;
 
  155       if ( typeNameList.contains( name ) )
 
  158         mapLayerMap[name] = layer;
 
  162           requestRect = layer->
extent();
 
  163           requestCrs = layer->
crs();
 
  182             requestRect = 
QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
 
  188 #ifdef HAVE_SERVER_PYTHON_PLUGINS 
  198     long sentFeatures = 0;
 
  199     long iteratedFeatures = 0;
 
  202     qIt = aRequest.
queries.begin();
 
  203     for ( ; qIt != aRequest.
queries.end(); ++qIt )
 
  208       if ( !mapLayerMap.contains( 
typeName ) )
 
  214 #ifdef HAVE_SERVER_PYTHON_PLUGINS 
  232 #ifdef HAVE_SERVER_PYTHON_PLUGINS 
  239       QMap< int, QString > layerAliasInfo;
 
  241       QgsStringMap::const_iterator aliasIt = aliasMap.constBegin();
 
  242       for ( ; aliasIt != aliasMap.constEnd(); ++aliasIt )
 
  245         if ( attrIndex != -1 )
 
  247           layerAliasInfo.insert( attrIndex, aliasIt.value() );
 
  258       if ( !propertyList.isEmpty() && propertyList.first() != QLatin1String( 
"*" ) )
 
  261         QStringList::const_iterator plstIt;
 
  264         QList<QString> propertynames;
 
  265         QList<QString> fieldnames;
 
  272         for ( plstIt = propertyList.constBegin(); plstIt != propertyList.constEnd(); ++plstIt )
 
  275           int fieldNameIdx = propertynames.indexOf( fieldName );
 
  276           if ( fieldNameIdx == -1 )
 
  278             fieldNameIdx = fieldnames.indexOf( fieldName );
 
  280           if ( fieldNameIdx > -1 )
 
  282             idxList.append( fieldNameIdx );
 
  284           else if ( fieldName == QLatin1String( 
"geometry" ) )
 
  289         if ( !idxList.isEmpty() )
 
  291           attrIndexes = idxList;
 
  296       if ( !attrIndexes.isEmpty() )
 
  302             int fieldNameIdx = fields.indexOf( 
field.
name() );
 
  303             if ( fieldNameIdx > -1 && attrIndexes.contains( fieldNameIdx ) )
 
  305               attrIndexes.removeOne( fieldNameIdx );
 
  334 #ifdef HAVE_SERVER_PYTHON_PLUGINS 
  339         QStringList attributes = QStringList();
 
  340         for ( 
int idx : std::as_const( attrIndexes ) )
 
  353       if ( !pkAttributes.isEmpty() )
 
  356         for ( 
int idx : pkAttributes )
 
  358           if ( !subsetOfAttrs.contains( idx ) )
 
  360             subsetOfAttrs.prepend( idx );
 
  391       if ( !query.
srsName.isEmpty() )
 
  418       if ( mWfsParameters.resultType() == QgsWfsParameters::ResultType::HITS )
 
  422           if ( iteratedFeatures >= aRequest.
startIndex )
 
  434         const bool invertAxis { mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) &&
 
  436                                 ! 
srsName.startsWith( QLatin1String( 
"EPSG:" ) ) };
 
  438         const createFeatureParams cfp = { layerPrecision,
 
  451           if ( iteratedFeatures == aRequest.
startIndex )
 
  452             startGetFeature( request, response, project, aRequest.
outputFormat, requestPrecision, requestCrs, &requestRect, typeNameList, serverIface->
serverSettings() );
 
  454           if ( iteratedFeatures >= aRequest.
startIndex )
 
  464 #ifdef HAVE_SERVER_PYTHON_PLUGINS 
  466     filterRestorer.reset();
 
  469     if ( mWfsParameters.resultType() == QgsWfsParameters::ResultType::HITS )
 
  471       hitGetFeature( request, response, project, aRequest.
outputFormat, sentFeatures, typeNameList, serverIface->
serverSettings() );
 
  476       if ( iteratedFeatures <= aRequest.
startIndex )
 
  477         startGetFeature( request, response, project, aRequest.
outputFormat, requestPrecision, requestCrs, &requestRect, typeNameList, serverIface->
serverSettings() );
 
  486     request.
maxFeatures = mWfsParameters.maxFeaturesAsInt();
 
  487     request.
startIndex = mWfsParameters.startIndexAsInt();
 
  491     QStringList fidList = mWfsParameters.featureIds();
 
  492     bool paramContainsFeatureIds = !fidList.isEmpty();
 
  493     QStringList filterList = mWfsParameters.filters();
 
  494     bool paramContainsFilters = !filterList.isEmpty();
 
  495     QString bbox = mWfsParameters.bbox();
 
  496     bool paramContainsBbox = !bbox.isEmpty();
 
  497     if ( ( paramContainsFeatureIds
 
  498            && ( paramContainsFilters || paramContainsBbox ) )
 
  499          || ( paramContainsFilters
 
  500               && ( paramContainsFeatureIds || paramContainsBbox ) )
 
  501          || ( paramContainsBbox
 
  502               && ( paramContainsFeatureIds || paramContainsFilters ) )
 
  509     QStringList propertyNameList = mWfsParameters.propertyNames();
 
  512     request.
geometryName = mWfsParameters.geometryNameAsString().toUpper();
 
  514     QStringList typeNameList;
 
  516     if ( paramContainsFeatureIds )
 
  519       if ( !propertyNameList.isEmpty() && propertyNameList.size() != fidList.size() )
 
  523       if ( propertyNameList.isEmpty() )
 
  525         for ( 
int i = 0; i < fidList.size(); ++i )
 
  527           propertyNameList << QStringLiteral( 
"*" );
 
  531       QMap<QString, QStringList> fidsMap;
 
  533       QStringList::const_iterator fidIt = fidList.constBegin();
 
  534       QStringList::const_iterator propertyNameIt = propertyNameList.constBegin();
 
  535       for ( ; fidIt != fidList.constEnd(); ++fidIt )
 
  538         QString fid = *fidIt;
 
  541         QString propertyName;
 
  542         if ( propertyNameIt != propertyNameList.constEnd() )
 
  544           propertyName = *propertyNameIt;
 
  547         if ( !fid.contains( 
'.' ) )
 
  552         QString 
typeName = fid.section( 
'.', 0, 0 );
 
  553         fid = fid.section( 
'.', 1, 1 );
 
  554         if ( !typeNameList.contains( 
typeName ) )
 
  560         QString key = QStringLiteral( 
"%1(%2)" ).arg( 
typeName, propertyName );
 
  562         if ( fidsMap.contains( key ) )
 
  564           fids = fidsMap.value( key );
 
  567         fidsMap.insert( key, fids );
 
  569         if ( propertyNameIt != propertyNameList.constEnd() )
 
  575       QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
 
  576       while ( fidsMapIt != fidsMap.constEnd() )
 
  578         QString key = fidsMapIt.key();
 
  581         QRegExp rx( 
"([^()]+)\\(([^()]+)\\)" );
 
  582         if ( rx.indexIn( key, 0 ) == -1 )
 
  587         QString propertyName = rx.cap( 2 );
 
  591         query.
srsName = mWfsParameters.srsName();
 
  594         if ( propertyName != QLatin1String( 
"*" ) )
 
  596           QStringList propertyList;
 
  598           const QStringList attrList = propertyName.split( 
',' );
 
  599           QStringList::const_iterator alstIt;
 
  600           for ( alstIt = attrList.constBegin(); alstIt != attrList.constEnd(); ++alstIt )
 
  602             QString fieldName = *alstIt;
 
  603             fieldName = fieldName.trimmed();
 
  604             if ( fieldName.contains( 
':' ) )
 
  606               fieldName = fieldName.section( 
':', 1, 1 );
 
  608             if ( fieldName.contains( 
'/' ) )
 
  610               if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  614               fieldName = fieldName.section( 
'/', 1, 1 );
 
  616             propertyList.append( fieldName );
 
  625         request.
queries.append( query );
 
  631     if ( !mRequestParameters.contains( QStringLiteral( 
"TYPENAME" ) ) )
 
  636     typeNameList = mWfsParameters.typeNames();
 
  638     if ( !propertyNameList.isEmpty() && typeNameList.size() != propertyNameList.size() )
 
  642     if ( propertyNameList.isEmpty() )
 
  644       for ( 
int i = 0; i < typeNameList.size(); ++i )
 
  646         propertyNameList << QStringLiteral( 
"*" );
 
  651     QStringList::const_iterator typeNameIt = typeNameList.constBegin();
 
  652     QStringList::const_iterator propertyNameIt = propertyNameList.constBegin();
 
  653     for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
 
  658       QString propertyName;
 
  659       if ( propertyNameIt != propertyNameList.constEnd() )
 
  661         propertyName = *propertyNameIt;
 
  666       query.
srsName = mWfsParameters.srsName();
 
  669       if ( propertyName != QLatin1String( 
"*" ) )
 
  671         QStringList propertyList;
 
  673         const QStringList attrList = propertyName.split( 
',' );
 
  674         QStringList::const_iterator alstIt;
 
  675         for ( alstIt = attrList.constBegin(); alstIt != attrList.constEnd(); ++alstIt )
 
  677           QString fieldName = *alstIt;
 
  678           fieldName = fieldName.trimmed();
 
  679           if ( fieldName.contains( 
':' ) )
 
  681             fieldName = fieldName.section( 
':', 1, 1 );
 
  683           if ( fieldName.contains( 
'/' ) )
 
  685             if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  689             fieldName = fieldName.section( 
'/', 1, 1 );
 
  691           propertyList.append( fieldName );
 
  696       request.
queries.append( query );
 
  698       if ( propertyNameIt != propertyNameList.constEnd() )
 
  705     QStringList expFilterList = mWfsParameters.expFilters();
 
  706     if ( !expFilterList.isEmpty() )
 
  709       if ( request.
queries.size() == expFilterList.size() )
 
  712         QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  713         QStringList::const_iterator expFilterIt = expFilterList.constBegin();
 
  714         for ( ; qIt != request.
queries.end(); ++qIt )
 
  719           if ( expFilterIt != expFilterList.constEnd() )
 
  721             expFilter = *expFilterIt;
 
  723           std::shared_ptr<QgsExpression> filter( 
new QgsExpression( expFilter ) );
 
  726             if ( filter->hasParserError() )
 
  730             if ( filter->needsGeometry() )
 
  744     if ( paramContainsBbox )
 
  750       QString extentSrsName { mWfsParameters.srsName() };
 
  753       if ( mWfsParameters.bbox().split( 
',' ).size() == 5 && ! mWfsParameters.srsName().isEmpty() )
 
  755         QString 
crs( mWfsParameters.bbox().split( 
',' )[4] );
 
  756         if ( 
crs != mWfsParameters.srsName() )
 
  786       if ( extentCrs.
isValid() && extentCrs.
hasAxisInverted() && ! extentSrsName.startsWith( QLatin1String( 
"EPSG:" ) ) )
 
  790         extent = geom.boundingBox();
 
  794       QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  795       for ( ; qIt != request.
queries.end(); ++qIt )
 
  802     else if ( paramContainsFilters )
 
  805       if ( request.
queries.size() != filterList.size() )
 
  811       QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  812       QStringList::const_iterator filterIt = filterList.constBegin();
 
  813       for ( ; qIt != request.
queries.end(); ++qIt )
 
  818         if ( filterIt != filterList.constEnd() )
 
  821           if ( !filter.setContent( *filterIt, 
true, &errorMsg ) )
 
  827         QDomElement filterElem = filter.firstChildElement();
 
  828         QStringList serverFids;
 
  832         if ( filterIt != filterList.constEnd() )
 
  840     QStringList sortByList = mWfsParameters.sortBy();
 
  841     if ( !sortByList.isEmpty() && request.
queries.size() == sortByList.size() )
 
  844       QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  845       QStringList::const_iterator sortByIt = sortByList.constBegin();
 
  846       for ( ; qIt != request.
queries.end(); ++qIt )
 
  851         if ( sortByIt != sortByList.constEnd() )
 
  855         for ( 
const QString &attribute : sortBy.split( 
',' ) )
 
  857           if ( attribute.endsWith( QLatin1String( 
" D" ) ) || attribute.endsWith( QLatin1String( 
"+D" ) ) )
 
  861           else if ( attribute.endsWith( QLatin1String( 
" DESC" ) ) || attribute.endsWith( QLatin1String( 
"+DESC" ) ) )
 
  865           else if ( attribute.endsWith( QLatin1String( 
" A" ) ) || attribute.endsWith( QLatin1String( 
"+A" ) ) )
 
  869           else if ( attribute.endsWith( QLatin1String( 
" ASC" ) ) || attribute.endsWith( QLatin1String( 
"+ASC" ) ) )
 
  887     request.
maxFeatures = mWfsParameters.maxFeaturesAsInt();
 
  888     request.
startIndex = mWfsParameters.startIndexAsInt();
 
  891     QDomNodeList queryNodes = docElem.elementsByTagName( QStringLiteral( 
"Query" ) );
 
  892     QDomElement queryElem;
 
  893     for ( 
int i = 0; i < queryNodes.size(); i++ )
 
  895       queryElem = queryNodes.at( i ).toElement();
 
  897       request.
queries.append( query );
 
  904     QDomNodeList sortByNodes = sortByElem.childNodes();
 
  905     if ( sortByNodes.size() )
 
  907       for ( 
int i = 0; i < sortByNodes.size(); i++ )
 
  909         QDomElement sortPropElem = sortByNodes.at( i ).toElement();
 
  910         QDomNodeList sortPropChildNodes = sortPropElem.childNodes();
 
  911         if ( sortPropChildNodes.size() )
 
  914           bool ascending = 
true;
 
  915           for ( 
int j = 0; j < sortPropChildNodes.size(); j++ )
 
  917             QDomElement sortPropChildElem = sortPropChildNodes.at( j ).toElement();
 
  918             if ( sortPropChildElem.tagName() == QLatin1String( 
"PropertyName" ) )
 
  920               fieldName = sortPropChildElem.text().trimmed();
 
  922             else if ( sortPropChildElem.tagName() == QLatin1String( 
"SortOrder" ) )
 
  924               QString sortOrder = sortPropChildElem.text().trimmed().toUpper();
 
  925               if ( sortOrder == QLatin1String( 
"DESC" ) || sortOrder == QLatin1String( 
"D" ) )
 
  930           if ( fieldName.contains( 
':' ) )
 
  932             fieldName = fieldName.section( 
':', 1, 1 );
 
  934           if ( fieldName.contains( 
'/' ) )
 
  936             if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  940             fieldName = fieldName.section( 
'/', 1, 1 );
 
  943           if ( !fieldName.isEmpty() )
 
  944             featureRequest.
addOrderBy( fieldName, ascending );
 
  952     QString 
typeName = queryElem.attribute( QStringLiteral( 
"typeName" ), QString() );
 
  959     QStringList serverFids;
 
  960     QStringList propertyList;
 
  961     QDomNodeList queryChildNodes = queryElem.childNodes();
 
  962     if ( queryChildNodes.size() )
 
  964       QDomElement sortByElem;
 
  965       for ( 
int q = 0; q < queryChildNodes.size(); q++ )
 
  967         QDomElement queryChildElem = queryChildNodes.at( q ).toElement();
 
  968         if ( queryChildElem.tagName() == QLatin1String( 
"PropertyName" ) )
 
  970           QString fieldName = queryChildElem.text().trimmed();
 
  971           if ( fieldName.contains( 
':' ) )
 
  973             fieldName = fieldName.section( 
':', 1, 1 );
 
  975           if ( fieldName.contains( 
'/' ) )
 
  977             if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  981             fieldName = fieldName.section( 
'/', 1, 1 );
 
  983           propertyList.append( fieldName );
 
  985         else if ( queryChildElem.tagName() == QLatin1String( 
"Filter" ) )
 
  989         else if ( queryChildElem.tagName() == QLatin1String( 
"SortBy" ) )
 
  991           sortByElem = queryChildElem;
 
  998     QString 
srsName = queryElem.attribute( QStringLiteral( 
"srsName" ), QString() );
 
 1011     static QSet< QString > sParamFilter
 
 1013       QStringLiteral( 
"REQUEST" ),
 
 1014       QStringLiteral( 
"FORMAT" ),
 
 1015       QStringLiteral( 
"OUTPUTFORMAT" ),
 
 1016       QStringLiteral( 
"BBOX" ),
 
 1017       QStringLiteral( 
"FEATUREID" ),
 
 1018       QStringLiteral( 
"TYPENAME" ),
 
 1019       QStringLiteral( 
"FILTER" ),
 
 1020       QStringLiteral( 
"EXP_FILTER" ),
 
 1021       QStringLiteral( 
"MAXFEATURES" ),
 
 1022       QStringLiteral( 
"STARTINDEX" ),
 
 1023       QStringLiteral( 
"PROPERTYNAME" ),
 
 1024       QStringLiteral( 
"_DC" )
 
 1029                         int numberOfFeatures, 
const QStringList &typeNames, 
const QgsServerSettings *settings )
 
 1031       QDateTime now = QDateTime::currentDateTime();
 
 1034       if ( format == QgsWfsParameters::Format::GeoJSON )
 
 1036         response.
setHeader( 
"Content-Type", 
"application/vnd.geo+json; charset=utf-8" );
 
 1037         fcString = QStringLiteral( 
"{\"type\": \"FeatureCollection\",\n" );
 
 1038         fcString += QStringLiteral( 
" \"timeStamp\": \"%1\"\n" ).arg( now.toString( Qt::ISODate ) );
 
 1039         fcString += QStringLiteral( 
" \"numberOfFeatures\": %1\n" ).arg( QString::number( numberOfFeatures ) );
 
 1040         fcString += QLatin1Char( 
'}' );
 
 1044         if ( format == QgsWfsParameters::Format::GML2 )
 
 1045           response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/2.1.2; charset=utf-8" );
 
 1047           response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/3.1.1; charset=utf-8" );
 
 1050         QString hrefString = 
serviceUrl( request, project, *settings );
 
 1052         QUrl mapUrl( hrefString );
 
 1054         QUrlQuery query( mapUrl );
 
 1055         query.addQueryItem( QStringLiteral( 
"SERVICE" ), QStringLiteral( 
"WFS" ) );
 
 1057         if ( mWfsParameters.version().isEmpty() )
 
 1060           query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.1.0" ) );
 
 1062           query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.0.0" ) );
 
 1064         for ( 
auto param : query.queryItems() )
 
 1066           if ( sParamFilter.contains( param.first.toUpper() ) )
 
 1067             query.removeAllQueryItems( param.first );
 
 1070         query.addQueryItem( QStringLiteral( 
"REQUEST" ), QStringLiteral( 
"DescribeFeatureType" ) );
 
 1071         query.addQueryItem( QStringLiteral( 
"TYPENAME" ), typeNames.join( 
',' ) );
 
 1074           if ( format == QgsWfsParameters::Format::GML2 )
 
 1075             query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/2.1.2" ) );
 
 1077             query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/3.1.1" ) );
 
 1080           query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"XMLSCHEMA" ) );
 
 1082         mapUrl.setQuery( query );
 
 1084         hrefString = mapUrl.toString();
 
 1087         if ( mWfsParameters.version().isEmpty() || mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) )
 
 1088           wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
 
 1090           wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
 
 1093         fcString = QStringLiteral( 
"<wfs:FeatureCollection" );
 
 1097         fcString += QLatin1String( 
" xmlns:ows=\"http://www.opengis.net/ows\"" );
 
 1098         fcString += QLatin1String( 
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" );
 
 1100         fcString += QLatin1String( 
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" );
 
 1101         fcString += 
" xsi:schemaLocation=\"" + 
WFS_NAMESPACE + 
" " + wfsSchema + 
" " + 
QGS_NAMESPACE + 
" " + hrefString.replace( QLatin1String( 
"&" ), QLatin1String( 
"&" ) ) + 
"\"";
 
 1102         fcString += 
"\n timeStamp=\"" + now.toString( Qt::ISODate ) + 
"\"";
 
 1103         fcString += 
"\n numberOfFeatures=\"" + QString::number( numberOfFeatures ) + 
"\"";
 
 1104         fcString += QLatin1String( 
">\n" );
 
 1105         fcString += QLatin1String( 
"</wfs:FeatureCollection>" );
 
 1108       response.
write( fcString.toUtf8() );
 
 1117       std::unique_ptr< QgsRectangle > transformedRect;
 
 1119       if ( format == QgsWfsParameters::Format::GeoJSON )
 
 1121         response.
setHeader( 
"Content-Type", 
"application/vnd.geo+json; charset=utf-8" );
 
 1134               rect = transformedRect.get();
 
 1145         fcString = QStringLiteral( 
"{\"type\": \"FeatureCollection\",\n" );
 
 1147         fcString += QLatin1String( 
" \"features\": [\n" );
 
 1148         response.
write( fcString.toUtf8() );
 
 1152         if ( format == QgsWfsParameters::Format::GML2 )
 
 1153           response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/2.1.2; charset=utf-8" );
 
 1155           response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/3.1.1; charset=utf-8" );
 
 1158         QString hrefString = 
serviceUrl( request, project, *settings );
 
 1160         QUrl mapUrl( hrefString );
 
 1162         QUrlQuery query( mapUrl );
 
 1163         query.addQueryItem( QStringLiteral( 
"SERVICE" ), QStringLiteral( 
"WFS" ) );
 
 1165         if ( mWfsParameters.version().isEmpty() )
 
 1168           query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.1.0" ) );
 
 1170           query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.0.0" ) );
 
 1172         const auto queryItems {query.queryItems()};
 
 1173         for ( 
auto param : std::as_const( queryItems ) )
 
 1175           if ( sParamFilter.contains( param.first.toUpper() ) )
 
 1176             query.removeAllQueryItems( param.first );
 
 1179         query.addQueryItem( QStringLiteral( 
"REQUEST" ), QStringLiteral( 
"DescribeFeatureType" ) );
 
 1180         query.addQueryItem( QStringLiteral( 
"TYPENAME" ), typeNames.join( 
',' ) );
 
 1183           if ( format == QgsWfsParameters::Format::GML2 )
 
 1184             query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/2.1.2" ) );
 
 1186             query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/3.1.1" ) );
 
 1189           query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"XMLSCHEMA" ) );
 
 1191         mapUrl.setQuery( query );
 
 1193         hrefString = mapUrl.toString();
 
 1196         if ( mWfsParameters.version().isEmpty() || mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) )
 
 1197           wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
 
 1199           wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
 
 1202         fcString = QStringLiteral( 
"<wfs:FeatureCollection" );
 
 1206         fcString += QLatin1String( 
" xmlns:ows=\"http://www.opengis.net/ows\"" );
 
 1207         fcString += QLatin1String( 
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" );
 
 1209         fcString += QLatin1String( 
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" );
 
 1210         fcString += 
" xsi:schemaLocation=\"" + 
WFS_NAMESPACE + 
" " + wfsSchema + 
" " + 
QGS_NAMESPACE + 
" " + hrefString.replace( QLatin1String( 
"&" ), QLatin1String( 
"&" ) ) + 
"\"";
 
 1211         fcString += QLatin1String( 
">\n" );
 
 1213         response.
write( fcString.toUtf8() );
 
 1217         QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1218         if ( format == QgsWfsParameters::Format::GML3 )
 
 1222           const bool invertAxis { mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) &&
 
 1224                                   ! 
srsName.startsWith( QLatin1String( 
"EPSG:" ) ) };
 
 1226           if ( !envElem.isNull() )
 
 1232                 envElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1236                 envElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1239             bbElem.appendChild( envElem );
 
 1240             doc.appendChild( bbElem );
 
 1246           if ( !boxElem.isNull() )
 
 1250               boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1252             bbElem.appendChild( boxElem );
 
 1253             doc.appendChild( bbElem );
 
 1256         response.
write( doc.toByteArray() );
 
 1267       if ( format == QgsWfsParameters::Format::GeoJSON )
 
 1271           fcString += QLatin1String( 
"  " );
 
 1273           fcString += QLatin1String( 
" ," );
 
 1274         mJsonExporter.setSourceCrs( params.crs );
 
 1275         mJsonExporter.setIncludeGeometry( 
false );
 
 1276         mJsonExporter.setIncludeAttributes( !params.attributeIndexes.isEmpty() );
 
 1277         mJsonExporter.setAttributes( params.attributeIndexes );
 
 1278         fcString += createFeatureGeoJSON( feature, params, pkAttributes );
 
 1279         fcString += QLatin1String( 
"\n" );
 
 1281         response.
write( fcString.toUtf8() );
 
 1285         QDomDocument gmlDoc;
 
 1286         QDomElement featureElement;
 
 1287         if ( format == QgsWfsParameters::Format::GML3 )
 
 1289           featureElement = createFeatureGML3( feature, gmlDoc, params, project, pkAttributes );
 
 1290           gmlDoc.appendChild( featureElement );
 
 1294           featureElement = createFeatureGML2( feature, gmlDoc, params, project, pkAttributes );
 
 1295           gmlDoc.appendChild( featureElement );
 
 1297         response.
write( gmlDoc.toByteArray() );
 
 1307       if ( format == QgsWfsParameters::Format::GeoJSON )
 
 1309         fcString += QLatin1String( 
" ]\n" );
 
 1310         fcString += QLatin1Char( 
'}' );
 
 1314         fcString = QStringLiteral( 
"</wfs:FeatureCollection>\n" );
 
 1316       response.
write( fcString.toUtf8() );
 
 1320     QString createFeatureGeoJSON( 
const QgsFeature &feature, 
const createFeatureParams ¶ms, 
const QgsAttributeList &pkAttributes )
 
 1330       if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1332         mJsonExporter.setIncludeGeometry( 
true );
 
 1333         if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1338         else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1344       return mJsonExporter.exportFeature( f, QVariantMap(), 
id );
 
 1348     QDomElement createFeatureGML2( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes )
 
 1351       QDomElement featureElement = doc.createElement( QStringLiteral( 
"gml:featureMember" ) );
 
 1354       QDomElement typeNameElement = doc.createElement( 
"qgs:" + params.typeName  );
 
 1356       typeNameElement.setAttribute( QStringLiteral( 
"fid" ), 
id );
 
 1357       featureElement.appendChild( typeNameElement );
 
 1361       if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1363         int prec = params.precision;
 
 1372             crs = params.outputCrs;
 
 1374               prec = std::min( params.precision + 3, 6 );
 
 1382         QDomElement geomElem = doc.createElement( QStringLiteral( 
"qgs:geometry" ) );
 
 1383         QDomElement gmlElem;
 
 1385         if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1389         else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1400           gmlElem = abstractGeom->
asGml2( doc, prec, 
"http://www.opengis.net/gml" );
 
 1403         if ( !gmlElem.isNull() )
 
 1406           QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1411             boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1412             gmlElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1415           bbElem.appendChild( boxElem );
 
 1416           typeNameElement.appendChild( bbElem );
 
 1418           geomElem.appendChild( gmlElem );
 
 1419           typeNameElement.appendChild( geomElem );
 
 1426       for ( 
int i = 0; i < params.attributeIndexes.count(); ++i )
 
 1428         int idx = params.attributeIndexes[i];
 
 1429         if ( idx >= fields.
count() )
 
 1437         QDomElement fieldElem = doc.createElement( 
"qgs:" + attributeName.replace( 
' ', 
'_' ).replace( 
cleanTagNameRegExp, QString() ) );
 
 1438         QDomText fieldText = doc.createTextNode( encodeValueToText( featureAttributes[idx], setup ) );
 
 1439         if ( featureAttributes[idx].isNull() )
 
 1441           fieldElem.setAttribute( QStringLiteral( 
"xsi:nil" ), QStringLiteral( 
"true" ) );
 
 1443         fieldElem.appendChild( fieldText );
 
 1444         typeNameElement.appendChild( fieldElem );
 
 1447       return featureElement;
 
 1450     QDomElement createFeatureGML3( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes )
 
 1453       QDomElement featureElement = doc.createElement( QStringLiteral( 
"gml:featureMember" ) );
 
 1456       QDomElement typeNameElement = doc.createElement( 
"qgs:" + params.typeName  );
 
 1458       typeNameElement.setAttribute( QStringLiteral( 
"gml:id" ), 
id );
 
 1459       featureElement.appendChild( typeNameElement );
 
 1463       if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1465         int prec = params.precision;
 
 1474             crs = params.outputCrs;
 
 1476               prec = std::min( params.precision + 3, 6 );
 
 1484         QDomElement geomElem = doc.createElement( QStringLiteral( 
"qgs:geometry" ) );
 
 1485         QDomElement gmlElem;
 
 1487         if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1491         else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1502           gmlElem = abstractGeom->
asGml3( doc, prec, 
"http://www.opengis.net/gml", params.hasAxisInverted ? QgsAbstractGeometry::AxisOrder::YX : QgsAbstractGeometry::AxisOrder::XY );
 
 1505         if ( !gmlElem.isNull() )
 
 1508           QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1513             boxElem.setAttribute( QStringLiteral( 
"srsName" ), params.srsName );
 
 1514             gmlElem.setAttribute( QStringLiteral( 
"srsName" ), params.srsName );
 
 1517           bbElem.appendChild( boxElem );
 
 1518           typeNameElement.appendChild( bbElem );
 
 1520           geomElem.appendChild( gmlElem );
 
 1521           typeNameElement.appendChild( geomElem );
 
 1528       for ( 
int i = 0; i < params.attributeIndexes.count(); ++i )
 
 1530         int idx = params.attributeIndexes[i];
 
 1531         if ( idx >= fields.
count() )
 
 1541         QDomElement fieldElem = doc.createElement( 
"qgs:" + attributeName.replace( 
' ', 
'_' ).replace( 
cleanTagNameRegExp, QString() ) );
 
 1542         QDomText fieldText = doc.createTextNode( encodeValueToText( featureAttributes[idx], setup ) );
 
 1543         if ( featureAttributes[idx].isNull() )
 
 1545           fieldElem.setAttribute( QStringLiteral( 
"xsi:nil" ), QStringLiteral( 
"true" ) );
 
 1547         fieldElem.appendChild( fieldText );
 
 1548         typeNameElement.appendChild( fieldElem );
 
 1551       return featureElement;
 
 1556       if ( value.isNull() )
 
 1559       if ( setup.
type() ==  QStringLiteral( 
"DateTime" ) )
 
 1562         const QVariantMap config = setup.
config();
 
 1563         const QString fieldFormat = config.value( QStringLiteral( 
"field_format" ), fieldFormatter.
defaultFormat( value.type() ) ).toString();
 
 1564         QDateTime date = value.toDateTime();
 
 1566         if ( date.isValid() )
 
 1568           return date.toString( fieldFormat );
 
 1571       else if ( setup.
type() ==  QStringLiteral( 
"Range" ) )
 
 1573         const QVariantMap config = setup.
config();
 
 1574         if ( config.contains( QStringLiteral( 
"Precision" ) ) )
 
 1578           int precision( config[ QStringLiteral( 
"Precision" ) ].toInt( &ok ) );
 
 1580             return QString::number( value.toDouble(), 
'f', 
precision );
 
 1584       switch ( value.type() )
 
 1587         case QVariant::UInt:
 
 1588         case QVariant::LongLong:
 
 1589         case QVariant::ULongLong:
 
 1590         case QVariant::Double:
 
 1591           return value.toString();
 
 1593         case QVariant::Bool:
 
 1594           return value.toBool() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" );
 
 1596         case QVariant::StringList:
 
 1597         case QVariant::List:
 
 1603           if ( v.indexOf( 
'<' ) != -1 || v.indexOf( 
'&' ) != -1 )
 
 1604             v.prepend( QStringLiteral( 
"<![CDATA[" ) ).append( QStringLiteral( 
"]]>" ) );
 
 1610         case QVariant::String:
 
 1612           QString v = value.toString();
 
 1615           if ( v.indexOf( 
'<' ) != -1 || v.indexOf( 
'&' ) != -1 )
 
 1616             v.prepend( QStringLiteral( 
"<![CDATA[" ) ).append( QStringLiteral( 
"]]>" ) );
 
@ Success
Operation succeeded.
Abstract base class for all geometries.
virtual QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML2 representation of the geometry.
virtual void swapXy()=0
Swaps the x and y coordinates from the geometry.
virtual QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const =0
Returns a GML3 representation of the geometry.
A helper class that centralizes restrictions given by all the access control filter plugins.
QStringList layerAttributes(const QgsVectorLayer *layer, const QStringList &attributes) const override
Returns the authorized layer attributes.
void filterFeatures(const QgsVectorLayer *layer, QgsFeatureRequest &filterFeatures) const override
Filter the features of the layer.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
QString authid() const
Returns the authority identifier for the CRS.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
Custom exception class for Coordinate Reference System related exceptions.
Defines a QGIS exception class.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
Flags flags() const
Returns the flags which affect how features are fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsAttributeList subsetOfAttributes() const
Returns the subset of attributes which at least need to be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isValid() const
Returns the validity of this feature.
Encapsulate a field in an attribute table or data source.
ConfigurationFlags configurationFlags
@ HideFromWfs
Fields is available if layer is served as WFS from QGIS server.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
int count() const
Returns number of items.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Handles exporting QgsFeature features to GeoJSON features.
static Q_INVOKABLE QString encodeValue(const QVariant &value)
Encodes a value to a JSON string representation, adding appropriate quotations and escaping where req...
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
RAII class to restore layer filters on destruction.
static void applyAccessControlLayerFilters(const QgsAccessControl *accessControl, QgsMapLayer *mapLayer, QHash< QgsMapLayer *, QString > &originalLayerFilters)
Apply filter from AccessControl.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
A class to describe the version of a project.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
bool isEmpty() const
Returns true if the rectangle is empty.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
QString value(const QString &key) const
Returns the value of a parameter.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QgsServerParameters serverParameters() const
Returns parameters.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QString > Parameters
virtual QByteArray data() const
Returns post/put data Check for QByteArray::isNull() to check if data is available.
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void flush() SIP_THROW(QgsServerException)
Flushes the current output buffer to the network.
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
Provides a way to retrieve settings by prioritizing according to environment variables,...
This is the base class for vector data providers.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsAttributeList attributeList() const
Returns list of attribute indexes.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
Exception thrown when data access violates access controls.
Provides an interface to retrieve and manipulate WFS parameters received from the client.
Format
Output format for the response.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
SERVER_EXPORT QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys.
SERVER_EXPORT QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys.
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
SERVER_EXPORT int wfsLayerPrecision(const QgsProject &project, const QString &layerId)
Returns the Layer precision defined in a QGIS project for the WFS GetFeature.
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer.
QString implementationVersion()
Returns the highest version supported by this implementation.
QString serviceUrl(const QgsServerRequest &request, const QgsProject *project, const QgsServerSettings &settings)
Service URL string.
const QString OGC_NAMESPACE
const QString GML_NAMESPACE
const QString WFS_NAMESPACE
getFeatureRequest parseGetFeatureRequestBody(QDomElement &docElem, const QgsProject *project)
Transform RequestBody root element to getFeatureRequest.
getFeatureQuery parseQueryElement(QDomElement &queryElem, const QgsProject *project)
Transform Query element to getFeatureQuery.
const QString QGS_NAMESPACE
getFeatureRequest parseGetFeatureParameters(const QgsProject *project)
Transform parameters to getFeatureRequest.
void parseSortByElement(QDomElement &sortByElem, QgsFeatureRequest &featureRequest, const QString &typeName)
Add SortBy element to featureRequest.
void writeGetFeature(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WFS GetFeature response.
QgsFeatureRequest parseFilterElement(const QString &typeName, QDomElement &filterElem, QgsProject *project)
Transform a Filter element to a feature request.
const QRegExp cleanTagNameRegExp("(?![\\w\\d\\.-]).")
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QMap< QString, QString > QgsStringMap
QList< int > QgsAttributeList
const QString & geometryName
const QgsCoordinateReferenceSystem & outputCrs
const QgsCoordinateReferenceSystem & crs
const QgsAttributeList & attributeIndexes
QgsFeatureRequest featureRequest
QgsWfsParameters::Format outputFormat
QList< getFeatureQuery > queries