42#include <QRegularExpression> 
   49    struct createFeatureParams
 
   72    QString createFeatureGeoJSON( 
const QgsFeature &feature, 
const createFeatureParams ¶ms, 
const QgsAttributeList &pkAttributes );
 
   74    QDomElement createFieldElement( 
const QgsField &field, 
const QVariant &value, QDomDocument &doc );
 
   78    QDomElement createFeatureGML2( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes );
 
   80    QDomElement createFeatureGML3( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes );
 
   91    QgsWfsParameters mWfsParameters;
 
  102    mWfsParameters.dump();
 
  108    if ( doc.setContent( request.
data(), 
true, &errorMsg ) )
 
  110      QDomElement docElem = doc.documentElement();
 
  119    QStringList typeNameList;
 
  122    bool onlyOneLayer = ( aRequest.
queries.size() == 1 );
 
  125    int requestPrecision = 6;
 
  129    QList<getFeatureQuery>::iterator qIt = aRequest.
queries.begin();
 
  130    for ( ; qIt != aRequest.
queries.end(); ++qIt )
 
  132      typeNameList << ( *qIt ).typeName;
 
  138    QMap<QString, QgsMapLayer *> mapLayerMap;
 
  139    for ( 
int i = 0; i < wfsLayerIds.size(); ++i )
 
  153      if ( typeNameList.contains( name ) )
 
  156        mapLayerMap[name] = layer;
 
  160          requestRect = layer->
extent();
 
  161          requestCrs = layer->
crs();
 
  180            requestRect = 
QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
 
  187    for ( 
const QString &
typeName : typeNameList )
 
  189      if ( !mapLayerMap.contains( 
typeName ) )
 
  195#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  199    auto filterRestorer = std::make_unique<QgsOWSServerFilterRestorer>();
 
  201    ( void ) serverIface;
 
  205    long sentFeatures = 0;
 
  206    long iteratedFeatures = 0;
 
  209    qIt = aRequest.
queries.begin();
 
  210    for ( ; qIt != aRequest.
queries.end(); ++qIt )
 
  216#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  234#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  241      QMap<int, QString> layerAliasInfo;
 
  243      QgsStringMap::const_iterator aliasIt = aliasMap.constBegin();
 
  244      for ( ; aliasIt != aliasMap.constEnd(); ++aliasIt )
 
  247        if ( attrIndex != -1 )
 
  249          layerAliasInfo.insert( attrIndex, aliasIt.value() );
 
  260      if ( !propertyList.isEmpty() && propertyList.first() != QLatin1String( 
"*" ) )
 
  263        QStringList::const_iterator plstIt;
 
  266        QList<QString> propertynames;
 
  267        QList<QString> fieldnames;
 
  268        for ( 
const QgsField &field : fields )
 
  270          fieldnames.
append( field.name() );
 
  271          const thread_local QRegularExpression sCleanTagNameRegExp( QStringLiteral( 
"[^\\w\\.-_]" ), QRegularExpression::PatternOption::UseUnicodePropertiesOption );
 
  272          propertynames.append( field.name().replace( 
' ', 
'_' ).replace( sCleanTagNameRegExp, QString() ) );
 
  275        for ( plstIt = propertyList.constBegin(); plstIt != propertyList.constEnd(); ++plstIt )
 
  278          int fieldNameIdx = propertynames.indexOf( fieldName );
 
  279          if ( fieldNameIdx == -1 )
 
  281            fieldNameIdx = fieldnames.indexOf( fieldName );
 
  283          if ( fieldNameIdx > -1 )
 
  285            idxList.append( fieldNameIdx );
 
  287          else if ( fieldName == QLatin1String( 
"geometry" ) )
 
  292        if ( !idxList.isEmpty() )
 
  294          attrIndexes = idxList;
 
  299      if ( !attrIndexes.isEmpty() )
 
  301        for ( 
const QgsField &field : fields )
 
  305            int fieldNameIdx = fields.
indexOf( field.name() );
 
  306            if ( fieldNameIdx > -1 && attrIndexes.contains( fieldNameIdx ) )
 
  308              attrIndexes.removeOne( fieldNameIdx );
 
  341#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  362        QStringList attributes = QStringList();
 
  363        for ( 
int idx : std::as_const( attrIndexes ) )
 
  377      if ( !pkAttributes.isEmpty() )
 
  380        for ( 
int idx : pkAttributes )
 
  382          if ( !subsetOfAttrs.contains( idx ) )
 
  384            subsetOfAttrs.prepend( idx );
 
  419      QString outputSrsName;
 
  420      if ( !query.
srsName.isEmpty() )
 
  424      else if ( !requestSrsName.isEmpty() )
 
  426        outputSrsName = requestSrsName;
 
  468          if ( iteratedFeatures >= aRequest.
startIndex )
 
  491          if ( iteratedFeatures == aRequest.
startIndex )
 
  492            startGetFeature( request, response, project, aRequest.
outputFormat, requestPrecision, requestCrs, &requestRect, typeNameList, serverIface->
serverSettings() );
 
  494          if ( iteratedFeatures >= aRequest.
startIndex )
 
  504#ifdef HAVE_SERVER_PYTHON_PLUGINS 
  506    filterRestorer.reset();
 
  511      hitGetFeature( request, response, project, aRequest.
outputFormat, sentFeatures, typeNameList, serverIface->
serverSettings() );
 
  516      if ( iteratedFeatures <= aRequest.
startIndex )
 
  517        startGetFeature( request, response, project, aRequest.
outputFormat, requestPrecision, requestCrs, &requestRect, typeNameList, serverIface->
serverSettings() );
 
 
  525    request.
maxFeatures = mWfsParameters.maxFeaturesAsInt();
 
  526    request.
startIndex = mWfsParameters.startIndexAsInt();
 
  530    QStringList fidList = mWfsParameters.featureIds();
 
  531    bool paramContainsFeatureIds = !fidList.isEmpty();
 
  532    QStringList filterList = mWfsParameters.filters();
 
  533    bool paramContainsFilters = !filterList.isEmpty();
 
  534    QString bbox = mWfsParameters.bbox();
 
  535    bool paramContainsBbox = !bbox.isEmpty();
 
  536    if ( ( paramContainsFeatureIds
 
  537           && ( paramContainsFilters || paramContainsBbox ) )
 
  538         || ( paramContainsFilters && ( paramContainsFeatureIds || paramContainsBbox ) )
 
  539         || ( paramContainsBbox && ( paramContainsFeatureIds || paramContainsFilters ) ) )
 
  545    QStringList propertyNameList = mWfsParameters.propertyNames();
 
  548    request.
geometryName = mWfsParameters.geometryNameAsString().toUpper();
 
  550    QStringList typeNameList;
 
  552    if ( paramContainsFeatureIds )
 
  555      if ( !propertyNameList.isEmpty() && propertyNameList.size() != fidList.size() )
 
  559      if ( propertyNameList.isEmpty() )
 
  561        for ( 
int i = 0; i < fidList.size(); ++i )
 
  563          propertyNameList << QStringLiteral( 
"*" );
 
  567      QMap<QString, QStringList> fidsMap;
 
  569      QStringList::const_iterator fidIt = fidList.constBegin();
 
  570      QStringList::const_iterator propertyNameIt = propertyNameList.constBegin();
 
  571      for ( ; fidIt != fidList.constEnd(); ++fidIt )
 
  574        QString fid = *fidIt;
 
  577        QString propertyName;
 
  578        if ( propertyNameIt != propertyNameList.constEnd() )
 
  580          propertyName = *propertyNameIt;
 
  583        if ( !fid.contains( 
'.' ) )
 
  588        QString 
typeName = fid.section( 
'.', 0, 0 );
 
  589        fid = fid.section( 
'.', 1, 1 );
 
  590        if ( !typeNameList.contains( 
typeName ) )
 
  598        const QString key = QStringLiteral( 
"%1:%2" ).arg( 
typeName, propertyName );
 
  600        if ( fidsMap.contains( key ) )
 
  602          fids = fidsMap.value( key );
 
  605        fidsMap.insert( key, fids );
 
  607        if ( propertyNameIt != propertyNameList.constEnd() )
 
  613      QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
 
  614      while ( fidsMapIt != fidsMap.constEnd() )
 
  616        QString key = fidsMapIt.key();
 
  620        const QString 
typeName = key.section( 
':', 0, 0 );
 
  621        const QString propertyName = key.section( 
':', 1, 1 );
 
  625        query.
srsName = mWfsParameters.srsName();
 
  628        if ( propertyName != QLatin1String( 
"*" ) )
 
  630          QStringList propertyList;
 
  632          const QStringList attrList = propertyName.split( 
',' );
 
  633          QStringList::const_iterator alstIt;
 
  634          for ( alstIt = attrList.constBegin(); alstIt != attrList.constEnd(); ++alstIt )
 
  636            QString fieldName = *alstIt;
 
  637            fieldName = fieldName.trimmed();
 
  638            if ( fieldName.contains( 
':' ) )
 
  640              fieldName = fieldName.section( 
':', 1, 1 );
 
  642            if ( fieldName.contains( 
'/' ) )
 
  644              if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  648              fieldName = fieldName.section( 
'/', 1, 1 );
 
  650            propertyList.append( fieldName );
 
  659        request.
queries.append( query );
 
  665    if ( !mRequestParameters.contains( QStringLiteral( 
"TYPENAME" ) ) )
 
  670    typeNameList = mWfsParameters.typeNames();
 
  672    if ( !propertyNameList.isEmpty() && typeNameList.size() != propertyNameList.size() )
 
  676    if ( propertyNameList.isEmpty() )
 
  678      for ( 
int i = 0; i < typeNameList.size(); ++i )
 
  680        propertyNameList << QStringLiteral( 
"*" );
 
  685    QStringList::const_iterator typeNameIt = typeNameList.constBegin();
 
  686    QStringList::const_iterator propertyNameIt = propertyNameList.constBegin();
 
  687    for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
 
  692      QString propertyName;
 
  693      if ( propertyNameIt != propertyNameList.constEnd() )
 
  695        propertyName = *propertyNameIt;
 
  700      query.
srsName = mWfsParameters.srsName();
 
  703      if ( propertyName != QLatin1String( 
"*" ) )
 
  705        QStringList propertyList;
 
  707        const QStringList attrList = propertyName.split( 
',' );
 
  708        QStringList::const_iterator alstIt;
 
  709        for ( alstIt = attrList.constBegin(); alstIt != attrList.constEnd(); ++alstIt )
 
  711          QString fieldName = *alstIt;
 
  712          fieldName = fieldName.trimmed();
 
  713          if ( fieldName.contains( 
':' ) )
 
  715            fieldName = fieldName.section( 
':', 1, 1 );
 
  717          if ( fieldName.contains( 
'/' ) )
 
  719            if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  723            fieldName = fieldName.section( 
'/', 1, 1 );
 
  725          propertyList.append( fieldName );
 
  730      request.
queries.append( query );
 
  732      if ( propertyNameIt != propertyNameList.constEnd() )
 
  739    QStringList expFilterList = mWfsParameters.expFilters();
 
  740    if ( !expFilterList.isEmpty() )
 
  743      if ( request.
queries.size() == expFilterList.size() )
 
  746        QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  747        QStringList::const_iterator expFilterIt = expFilterList.constBegin();
 
  748        for ( ; qIt != request.
queries.end(); ++qIt )
 
  752          const QString expFilter = *expFilterIt++;
 
  753          std::shared_ptr<QgsExpression> filter( 
new QgsExpression( expFilter ) );
 
  756            if ( filter->hasParserError() )
 
  760            if ( filter->needsGeometry() )
 
  774    if ( paramContainsBbox )
 
  779      QString extentSrsName { mWfsParameters.srsName() };
 
  782      if ( mWfsParameters.bbox().split( 
',' ).size() == 5 && !mWfsParameters.srsName().isEmpty() )
 
  784        QString 
crs( mWfsParameters.bbox().split( 
',' )[4] );
 
  785        if ( 
crs != mWfsParameters.srsName() )
 
  815      if ( extentCrs.
isValid() && extentCrs.
hasAxisInverted() && !extentSrsName.startsWith( QLatin1String( 
"EPSG:" ) ) )
 
  819        extent = geom.boundingBox();
 
  823      QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  824      for ( ; qIt != request.
queries.end(); ++qIt )
 
  831    else if ( paramContainsFilters )
 
  834      if ( request.
queries.size() != filterList.size() )
 
  840      QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  841      QStringList::const_iterator filterIt = filterList.constBegin();
 
  842      for ( ; qIt != request.
queries.end(); ++qIt )
 
  847        if ( filterIt != filterList.constEnd() )
 
  850          if ( !filter.setContent( *filterIt, 
true, &errorMsg ) )
 
  856        QDomElement filterElem = filter.firstChildElement();
 
  857        QStringList serverFids;
 
  861        if ( filterIt != filterList.constEnd() )
 
  869    QStringList sortByList = mWfsParameters.sortBy();
 
  870    if ( !sortByList.isEmpty() && request.
queries.size() == sortByList.size() )
 
  873      QList<getFeatureQuery>::iterator qIt = request.
queries.begin();
 
  874      QStringList::const_iterator sortByIt = sortByList.constBegin();
 
  875      for ( ; qIt != request.
queries.end(); ++qIt )
 
  880        if ( sortByIt != sortByList.constEnd() )
 
  884        for ( 
const QString &attribute : sortBy.split( 
',' ) )
 
  886          if ( attribute.endsWith( QLatin1String( 
" D" ) ) || attribute.endsWith( QLatin1String( 
"+D" ) ) )
 
  890          else if ( attribute.endsWith( QLatin1String( 
" DESC" ) ) || attribute.endsWith( QLatin1String( 
"+DESC" ) ) )
 
  894          else if ( attribute.endsWith( QLatin1String( 
" A" ) ) || attribute.endsWith( QLatin1String( 
"+A" ) ) )
 
  898          else if ( attribute.endsWith( QLatin1String( 
" ASC" ) ) || attribute.endsWith( QLatin1String( 
"+ASC" ) ) )
 
 
  916    request.
maxFeatures = mWfsParameters.maxFeaturesAsInt();
 
  917    request.
startIndex = mWfsParameters.startIndexAsInt();
 
  920    QDomNodeList queryNodes = docElem.elementsByTagName( QStringLiteral( 
"Query" ) );
 
  921    QDomElement queryElem;
 
  922    for ( 
int i = 0; i < queryNodes.size(); i++ )
 
  924      queryElem = queryNodes.at( i ).toElement();
 
  926      request.
queries.append( query );
 
 
  933    QDomNodeList sortByNodes = sortByElem.childNodes();
 
  934    if ( sortByNodes.size() )
 
  936      for ( 
int i = 0; i < sortByNodes.size(); i++ )
 
  938        QDomElement sortPropElem = sortByNodes.at( i ).toElement();
 
  939        QDomNodeList sortPropChildNodes = sortPropElem.childNodes();
 
  940        if ( sortPropChildNodes.size() )
 
  943          bool ascending = 
true;
 
  944          for ( 
int j = 0; j < sortPropChildNodes.size(); j++ )
 
  946            QDomElement sortPropChildElem = sortPropChildNodes.at( j ).toElement();
 
  947            if ( sortPropChildElem.tagName() == QLatin1String( 
"PropertyName" ) )
 
  949              fieldName = sortPropChildElem.text().trimmed();
 
  951            else if ( sortPropChildElem.tagName() == QLatin1String( 
"SortOrder" ) )
 
  953              QString sortOrder = sortPropChildElem.text().trimmed().toUpper();
 
  954              if ( sortOrder == QLatin1String( 
"DESC" ) || sortOrder == QLatin1String( 
"D" ) )
 
  959          if ( fieldName.contains( 
':' ) )
 
  961            fieldName = fieldName.section( 
':', 1, 1 );
 
  963          if ( fieldName.contains( 
'/' ) )
 
  965            if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
  969            fieldName = fieldName.section( 
'/', 1, 1 );
 
  972          if ( !fieldName.isEmpty() )
 
  973            featureRequest.
addOrderBy( fieldName, ascending );
 
 
  981    QString 
typeName = queryElem.attribute( QStringLiteral( 
"typeName" ), QString() );
 
  988    QStringList serverFids;
 
  989    QStringList propertyList;
 
  990    QDomNodeList queryChildNodes = queryElem.childNodes();
 
  991    if ( queryChildNodes.size() )
 
  993      QDomElement sortByElem;
 
  994      for ( 
int q = 0; q < queryChildNodes.size(); q++ )
 
  996        QDomElement queryChildElem = queryChildNodes.at( q ).toElement();
 
  997        if ( queryChildElem.tagName() == QLatin1String( 
"PropertyName" ) )
 
  999          QString fieldName = queryChildElem.text().trimmed();
 
 1000          if ( fieldName.contains( 
':' ) )
 
 1002            fieldName = fieldName.section( 
':', 1, 1 );
 
 1004          if ( fieldName.contains( 
'/' ) )
 
 1006            if ( fieldName.section( 
'/', 0, 0 ) != 
typeName )
 
 1010            fieldName = fieldName.section( 
'/', 1, 1 );
 
 1012          propertyList.append( fieldName );
 
 1014        else if ( queryChildElem.tagName() == QLatin1String( 
"Filter" ) )
 
 1018        else if ( queryChildElem.tagName() == QLatin1String( 
"SortBy" ) )
 
 1020          sortByElem = queryChildElem;
 
 1027    QString 
srsName = queryElem.attribute( QStringLiteral( 
"srsName" ), QString() );
 
 
 1040    static QSet<QString> sParamFilter {
 
 1041      QStringLiteral( 
"REQUEST" ),
 
 1042      QStringLiteral( 
"FORMAT" ),
 
 1043      QStringLiteral( 
"OUTPUTFORMAT" ),
 
 1044      QStringLiteral( 
"BBOX" ),
 
 1045      QStringLiteral( 
"FEATUREID" ),
 
 1046      QStringLiteral( 
"TYPENAME" ),
 
 1047      QStringLiteral( 
"FILTER" ),
 
 1048      QStringLiteral( 
"EXP_FILTER" ),
 
 1049      QStringLiteral( 
"MAXFEATURES" ),
 
 1050      QStringLiteral( 
"STARTINDEX" ),
 
 1051      QStringLiteral( 
"PROPERTYNAME" ),
 
 1052      QStringLiteral( 
"_DC" )
 
 1058      QDateTime now = QDateTime::currentDateTime();
 
 1063        response.
setHeader( 
"Content-Type", 
"application/vnd.geo+json; charset=utf-8" );
 
 1064        fcString = QStringLiteral( 
"{\"type\": \"FeatureCollection\",\n" );
 
 1065        fcString += QStringLiteral( 
" \"timeStamp\": \"%1\",\n" ).arg( now.toString( Qt::ISODate ) );
 
 1066        fcString += QStringLiteral( 
" \"numberOfFeatures\": %1\n" ).arg( QString::number( numberOfFeatures ) );
 
 1067        fcString += QLatin1Char( 
'}' );
 
 1072          response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/2.1.2; charset=utf-8" );
 
 1074          response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/3.1.1; charset=utf-8" );
 
 1077        QString hrefString = 
serviceUrl( request, project, *settings );
 
 1079        QUrl mapUrl( hrefString );
 
 1081        QUrlQuery query( mapUrl );
 
 1082        query.addQueryItem( QStringLiteral( 
"SERVICE" ), QStringLiteral( 
"WFS" ) );
 
 1084        if ( mWfsParameters.version().isEmpty() )
 
 1087          query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.1.0" ) );
 
 1089          query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.0.0" ) );
 
 1091        const auto constItems { query.queryItems() };
 
 1092        for ( 
const auto ¶m : std::as_const( constItems ) )
 
 1094          if ( sParamFilter.contains( param.first.toUpper() ) )
 
 1095            query.removeAllQueryItems( param.first );
 
 1098        query.addQueryItem( QStringLiteral( 
"REQUEST" ), QStringLiteral( 
"DescribeFeatureType" ) );
 
 1099        query.addQueryItem( QStringLiteral( 
"TYPENAME" ), typeNames.join( 
',' ) );
 
 1103            query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/2.1.2" ) );
 
 1105            query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/3.1.1" ) );
 
 1108          query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"XMLSCHEMA" ) );
 
 1110        mapUrl.setQuery( query );
 
 1112        hrefString = mapUrl.toString();
 
 1115        if ( mWfsParameters.version().isEmpty() || mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) )
 
 1116          wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
 
 1118          wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
 
 1121        fcString = QStringLiteral( 
"<wfs:FeatureCollection" );
 
 1125        fcString += QLatin1String( 
" xmlns:ows=\"http://www.opengis.net/ows\"" );
 
 1126        fcString += QLatin1String( 
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" );
 
 1128        fcString += QLatin1String( 
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" );
 
 1129        fcString += 
" xsi:schemaLocation=\"" + 
WFS_NAMESPACE + 
" " + wfsSchema + 
" " + 
QGS_NAMESPACE + 
" " + hrefString.replace( QLatin1String( 
"&" ), QLatin1String( 
"&" ) ) + 
"\"";
 
 1130        fcString += 
"\n timeStamp=\"" + now.toString( Qt::ISODate ) + 
"\"";
 
 1131        fcString += 
"\n numberOfFeatures=\"" + QString::number( numberOfFeatures ) + 
"\"";
 
 1132        fcString += QLatin1String( 
">\n" );
 
 1133        fcString += QLatin1String( 
"</wfs:FeatureCollection>" );
 
 1136      response.
write( fcString.toUtf8() );
 
 1144      std::unique_ptr<QgsRectangle> transformedRect;
 
 1148        response.
setHeader( 
"Content-Type", 
"application/vnd.geo+json; charset=utf-8" );
 
 1161              rect = transformedRect.get();
 
 1172        fcString = QStringLiteral( 
"{\"type\": \"FeatureCollection\",\n" );
 
 1177        if ( !destinationCrs.isValid() )
 
 1179          throw QgsRequestNotWellFormedException( QStringLiteral( 
"srsName error: '%1' is not valid." ).arg( 
srsName ) );
 
 1184        for ( 
const auto &it : value.items() )
 
 1186          fcString += 
" \"" + QString::fromStdString( it.key() ) + 
"\": " + QString::fromStdString( it.value().dump() ) + 
",\n";
 
 1189        fcString += QLatin1String( 
" \"features\": [\n" );
 
 1190        response.
write( fcString.toUtf8() );
 
 1195          response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/2.1.2; charset=utf-8" );
 
 1197          response.
setHeader( 
"Content-Type", 
"text/xml; subtype=gml/3.1.1; charset=utf-8" );
 
 1200        QString hrefString = 
serviceUrl( request, project, *settings );
 
 1202        QUrl mapUrl( hrefString );
 
 1204        QUrlQuery query( mapUrl );
 
 1205        query.addQueryItem( QStringLiteral( 
"SERVICE" ), QStringLiteral( 
"WFS" ) );
 
 1207        if ( mWfsParameters.version().isEmpty() )
 
 1210          query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.1.0" ) );
 
 1212          query.addQueryItem( QStringLiteral( 
"VERSION" ), QStringLiteral( 
"1.0.0" ) );
 
 1214        const auto queryItems { query.queryItems() };
 
 1215        for ( 
auto param : std::as_const( queryItems ) )
 
 1217          if ( sParamFilter.contains( param.first.toUpper() ) )
 
 1218            query.removeAllQueryItems( param.first );
 
 1221        query.addQueryItem( QStringLiteral( 
"REQUEST" ), QStringLiteral( 
"DescribeFeatureType" ) );
 
 1222        query.addQueryItem( QStringLiteral( 
"TYPENAME" ), typeNames.join( 
',' ) );
 
 1226            query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/2.1.2" ) );
 
 1228            query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"text/xml; subtype=gml/3.1.1" ) );
 
 1231          query.addQueryItem( QStringLiteral( 
"OUTPUTFORMAT" ), QStringLiteral( 
"XMLSCHEMA" ) );
 
 1233        mapUrl.setQuery( query );
 
 1235        hrefString = mapUrl.toString();
 
 1238        if ( mWfsParameters.version().isEmpty() || mWfsParameters.versionAsNumber() >= 
QgsProjectVersion( 1, 1, 0 ) )
 
 1239          wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
 
 1241          wfsSchema = QStringLiteral( 
"http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
 
 1244        fcString = QStringLiteral( 
"<wfs:FeatureCollection" );
 
 1248        fcString += QLatin1String( 
" xmlns:ows=\"http://www.opengis.net/ows\"" );
 
 1249        fcString += QLatin1String( 
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"" );
 
 1251        fcString += QLatin1String( 
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" );
 
 1252        fcString += 
" xsi:schemaLocation=\"" + 
WFS_NAMESPACE + 
" " + wfsSchema + 
" " + 
QGS_NAMESPACE + 
" " + hrefString.replace( QLatin1String( 
"&" ), QLatin1String( 
"&" ) ) + 
"\"";
 
 1253        fcString += QLatin1String( 
">\n" );
 
 1255        response.
write( fcString.toUtf8() );
 
 1259        QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1264          const QString outputSrsName = !requestSrsName.isEmpty() ? requestSrsName : 
crs.
authid();
 
 1290          if ( !envElem.isNull() )
 
 1292            if ( 
crs.
isValid() && outputSrsName.isEmpty() )
 
 1294              envElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1296            bbElem.appendChild( envElem );
 
 1297            doc.appendChild( bbElem );
 
 1303          if ( !boxElem.isNull() )
 
 1307              boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1309            bbElem.appendChild( boxElem );
 
 1310            doc.appendChild( bbElem );
 
 1313        response.
write( doc.toByteArray() );
 
 1327          fcString += QLatin1String( 
"  " );
 
 1329          fcString += QLatin1String( 
" ," );
 
 1332        if ( !destinationCrs.isValid() )
 
 1334          throw QgsRequestNotWellFormedException( QStringLiteral( 
"srsName error: '%1' is not valid." ).arg( params.srsName ) );
 
 1337        mJsonExporter.setDestinationCrs( destinationCrs );
 
 1338        mJsonExporter.setTransformGeometries( 
true );
 
 1339        mJsonExporter.setSourceCrs( params.crs );
 
 1340        mJsonExporter.setIncludeGeometry( 
false );
 
 1341        mJsonExporter.setIncludeAttributes( !params.attributeIndexes.isEmpty() );
 
 1342        mJsonExporter.setAttributes( params.attributeIndexes );
 
 1343        fcString += createFeatureGeoJSON( feature, params, pkAttributes );
 
 1344        fcString += QLatin1String( 
"\n" );
 
 1346        response.
write( fcString.toUtf8() );
 
 1350        QDomDocument gmlDoc;
 
 1351        QDomElement featureElement;
 
 1354          featureElement = createFeatureGML3( feature, gmlDoc, params, project, pkAttributes );
 
 1355          gmlDoc.appendChild( featureElement );
 
 1359          featureElement = createFeatureGML2( feature, gmlDoc, params, project, pkAttributes );
 
 1360          gmlDoc.appendChild( featureElement );
 
 1362        response.
write( gmlDoc.toByteArray() );
 
 1374        fcString += QLatin1String( 
" ]\n" );
 
 1375        fcString += QLatin1Char( 
'}' );
 
 1379        fcString = QStringLiteral( 
"</wfs:FeatureCollection>\n" );
 
 1381      response.
write( fcString.toUtf8() );
 
 1385    QString createFeatureGeoJSON( 
const QgsFeature &feature, 
const createFeatureParams ¶ms, 
const QgsAttributeList &pkAttributes )
 
 1395      if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1397        mJsonExporter.setIncludeGeometry( 
true );
 
 1398        if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1403        else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1409      return mJsonExporter.exportFeature( f, QVariantMap(), 
id );
 
 1413    QDomElement createFeatureGML2( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes )
 
 1416      QDomElement featureElement = doc.createElement( QStringLiteral( 
"gml:featureMember" )  );
 
 1419      QDomElement typeNameElement = doc.createElement( 
"qgs:" + params.typeName  );
 
 1421      typeNameElement.setAttribute( QStringLiteral( 
"fid" ), 
id );
 
 1422      featureElement.appendChild( typeNameElement );
 
 1426      if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1428        int prec = params.precision;
 
 1437            crs = params.outputCrs;
 
 1439              prec = std::min( params.precision + 3, 6 );
 
 1447        QDomElement geomElem = doc.createElement( QStringLiteral( 
"qgs:geometry" ) );
 
 1448        QDomElement gmlElem;
 
 1450        if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1454        else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1465          gmlElem = abstractGeom->
asGml2( doc, prec, 
"http://www.opengis.net/gml" );
 
 1468        if ( !gmlElem.isNull() )
 
 1471          QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1476            boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1477            gmlElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1480          bbElem.appendChild( boxElem );
 
 1481          typeNameElement.appendChild( bbElem );
 
 1483          geomElem.appendChild( gmlElem );
 
 1484          typeNameElement.appendChild( geomElem );
 
 1491      for ( 
int i = 0; i < params.attributeIndexes.count(); ++i )
 
 1493        int idx = params.attributeIndexes[i];
 
 1499        const QDomElement fieldElem = createFieldElement( fields.
at( idx ), featureAttributes[idx], doc );
 
 1500        typeNameElement.appendChild( fieldElem );
 
 1503      return featureElement;
 
 1506    QDomElement createFeatureGML3( 
const QgsFeature &feature, QDomDocument &doc, 
const createFeatureParams ¶ms, 
const QgsProject *project, 
const QgsAttributeList &pkAttributes )
 
 1509      QDomElement featureElement = doc.createElement( QStringLiteral( 
"gml:featureMember" )  );
 
 1512      QDomElement typeNameElement = doc.createElement( QStringLiteral( 
"qgs:" ) + params.typeName  );
 
 1514      typeNameElement.setAttribute( QStringLiteral( 
"gml:id" ), 
id );
 
 1515      featureElement.appendChild( typeNameElement );
 
 1519      if ( !geom.
isNull() && params.withGeom && params.geometryName != QLatin1String( 
"NONE" ) )
 
 1521        int prec = params.precision;
 
 1530            crs = params.outputCrs;
 
 1532              prec = std::min( params.precision + 3, 6 );
 
 1540        QDomElement geomElem = doc.createElement( QStringLiteral( 
"qgs:geometry" ) );
 
 1541        QDomElement gmlElem;
 
 1543        if ( params.geometryName == QLatin1String( 
"EXTENT" ) )
 
 1547        else if ( params.geometryName == QLatin1String( 
"CENTROID" ) )
 
 1561        if ( !gmlElem.isNull() )
 
 1564          QDomElement bbElem = doc.createElement( QStringLiteral( 
"gml:boundedBy" ) );
 
 1567          if ( 
crs.
isValid() && params.srsName.isEmpty() )
 
 1569            boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1570            gmlElem.setAttribute( QStringLiteral( 
"srsName" ), 
crs.
authid() );
 
 1572          else if ( !params.srsName.isEmpty() )
 
 1574            gmlElem.setAttribute( QStringLiteral( 
"srsName" ), params.srsName );
 
 1577          bbElem.appendChild( boxElem );
 
 1578          typeNameElement.appendChild( bbElem );
 
 1580          geomElem.appendChild( gmlElem );
 
 1581          typeNameElement.appendChild( geomElem );
 
 1588      for ( 
int i = 0; i < params.attributeIndexes.count(); ++i )
 
 1590        int idx = params.attributeIndexes[i];
 
 1596        const QDomElement fieldElem = createFieldElement( fields.
at( idx ), featureAttributes[idx], doc );
 
 1597        typeNameElement.appendChild( fieldElem );
 
 1600      return featureElement;
 
 1603    QDomElement createFieldElement( 
const QgsField &field, 
const QVariant &value, QDomDocument &doc )
 
 1606      const thread_local QRegularExpression sCleanTagNameRegExp( QStringLiteral( 
"[^\\w\\.-_]" ), QRegularExpression::PatternOption::UseUnicodePropertiesOption );
 
 1607      const QString attributeName = field.
name().replace( 
' ', 
'_' ).replace( sCleanTagNameRegExp, QString() );
 
 1608      QDomElement fieldElem = doc.createElement( QStringLiteral( 
"qgs:" ) + attributeName );
 
 1611        fieldElem.setAttribute( QStringLiteral( 
"xsi:nil" ), QStringLiteral( 
"true" ) );
 
 1615        const QString fieldText = encodeValueToText( value, setup );
 
 1617        if ( fieldText.indexOf( 
'<' ) != -1 || fieldText.indexOf( 
'&' ) != -1 )
 
 1619          fieldElem.appendChild( doc.createCDATASection( fieldText ) );
 
 1623          fieldElem.appendChild( doc.createTextNode( fieldText ) );
 
 1634      if ( setup.
type() == QLatin1String( 
"DateTime" ) )
 
 1637        if ( value.userType() == QMetaType::Type::QTime )
 
 1643        const QVariantMap config = setup.
config();
 
 1649        QDateTime date = value.toDateTime();
 
 1651        if ( !date.isValid() )
 
 1653          date = QDateTime::fromString( value.toString(), fieldFormat );
 
 1656        if ( date.isValid() )
 
 1658          return date.toString( fieldFormat );
 
 1661        return value.toString();
 
 1663      else if ( setup.
type() == QLatin1String( 
"Range" ) )
 
 1665        const QVariantMap config = setup.
config();
 
 1666        if ( config.contains( QStringLiteral( 
"Precision" ) ) )
 
 1670          int precision( config[QStringLiteral( 
"Precision" )].toInt( &ok ) );
 
 1672            return QString::number( value.toDouble(), 
'f', 
precision );
 
 1676      switch ( value.userType() )
 
 1678        case QMetaType::Type::Int:
 
 1679        case QMetaType::Type::UInt:
 
 1680        case QMetaType::Type::LongLong:
 
 1681        case QMetaType::Type::ULongLong:
 
 1682        case QMetaType::Type::Double:
 
 1683          return value.toString();
 
 1685        case QMetaType::Type::Bool:
 
 1686          return value.toBool() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" );
 
 1688        case QMetaType::Type::QStringList:
 
 1689        case QMetaType::Type::QVariantList:
 
 1690        case QMetaType::Type::QVariantMap:
 
 1694        case QMetaType::Type::QString:
 
 1695          return value.toString();
 
@ Success
Operation succeeded.
 
@ Fid
Filter using feature ID.
 
@ Fids
Filter using feature IDs.
 
@ NoFilter
No filter is applied.
 
@ 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.
 
@ NoFlags
No flags are set.
 
@ HideFromWfs
Field is not available if layer is served as WFS from QGIS server.
 
Abstract base class for all geometries.
 
@ YX
Y comes before X (or lat before lon)
 
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.
 
Represents a coordinate reference system (CRS).
 
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.
 
bool hasAxisInverted() const
Returns whether the axis order is inverted for the CRS compared to the order east/north (longitude/la...
 
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...
 
Handles 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)
Fetch next feature and stores in f, returns true on success.
 
Wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
 
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 & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
 
Qgis::FeatureRequestFilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
 
Qgis::FeatureRequestFlags 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.
 
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
 
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
 
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.
 
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
 
Container of fields for a vector layer.
 
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
 
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
 
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).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
A geometry is the spatial representation of a feature.
 
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
 
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
 
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
 
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.
 
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
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...
 
static void addCrsInfo(json &value, const QgsCoordinateReferenceSystem &crs)
Add crs information entry in json object regarding old GeoJSON specification format if it differs fro...
 
Base class for all map layer types.
 
virtual QgsRectangle extent() const
Returns the extent of the layer.
 
QgsCoordinateReferenceSystem crs
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
static void applyAccessControlLayerFilters(const QgsAccessControl *accessControl, QgsMapLayer *mapLayer, QHash< QgsMapLayer *, QString > &originalLayerFilters)
Apply filter from AccessControl.
 
static QDomElement rectangleToGMLEnvelope(const QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
 
static QDomElement rectangleToGMLBox(const QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
 
Describes 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.
 
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
 
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
 
static QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys.
 
static QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys.
 
Defines 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.
 
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
 
static int wfsLayerPrecision(const QgsProject &project, const QString &layerId)
Returns the Layer precision defined in a QGIS project for the WFS GetFeature.
 
Defines requests passed to QgsService classes.
 
QgsServerParameters serverParameters() const
Returns parameters.
 
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
 
QUrl url() const
Returns the request URL as seen by QGIS server.
 
QMap< QString, QString > Parameters
 
virtual QByteArray data() const
Returns post/put data Check for QByteArray::isNull() to check if data is available.
 
Defines the response interface passed to QgsService.
 
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()
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,...
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
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 dataset.
 
Q_INVOKABLE QgsAttributeList attributeList() const
Returns list of attribute indexes.
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
 
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
 
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 Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
 
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.
 
#define Q_NOWARN_DEPRECATED_POP
 
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
 
#define Q_NOWARN_DEPRECATED_PUSH
 
QMap< QString, QString > QgsStringMap
 
QList< int > QgsAttributeList
 
const QString & geometryName
 
const QgsCoordinateReferenceSystem & outputCrs
 
const QgsCoordinateReferenceSystem & crs
 
const QgsAttributeList & attributeIndexes
 
QgsFeatureRequest featureRequest
 
QList< getFeatureQuery > queries
 
QgsWfsParameters::Format outputFormat