mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Merge pull request #39368 from elpaso/wfs-t-1.1
Fix WFS-T 1.1.0 support
This commit is contained in:
		
						commit
						a0711d710d
					
				@ -108,6 +108,7 @@ Returns the "test connection" button.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    virtual QString wfsSettingsKey( const QString &base, const QString &connectionName ) const;
 | 
			
		||||
%Docstring
 | 
			
		||||
Returns the QSettings key for WFS related settings for the connection.
 | 
			
		||||
 | 
			
		||||
@ -1173,7 +1173,8 @@ QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, QDomDocumen
 | 
			
		||||
  return geometryToGML( geometry, doc, ( format == QLatin1String( "GML2" ) ) ? GML_2_1_2 : GML_3_2_1, QString(), false, QString(), precision );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry, QDomDocument &doc,
 | 
			
		||||
QDomElement QgsOgcUtils::geometryToGML( const QgsGeometry &geometry,
 | 
			
		||||
                                        QDomDocument &doc,
 | 
			
		||||
                                        GMLVersion gmlVersion,
 | 
			
		||||
                                        const QString &srsName,
 | 
			
		||||
                                        bool invertAxisOrientation,
 | 
			
		||||
 | 
			
		||||
@ -166,6 +166,7 @@ void QgsNewHttpConnection::wfsVersionCurrentIndexChanged( int index )
 | 
			
		||||
  txtPageSize->setEnabled( cbxWfsFeaturePaging->isChecked() && ( index == WFS_VERSION_MAX || index >= WFS_VERSION_1_1 ) );
 | 
			
		||||
  cbxWfsIgnoreAxisOrientation->setEnabled( index != WFS_VERSION_1_0 && index != WFS_VERSION_API_FEATURES_1_0 );
 | 
			
		||||
  cbxWfsInvertAxisOrientation->setEnabled( index != WFS_VERSION_API_FEATURES_1_0 );
 | 
			
		||||
  wfsUseGml2EncodingForTransactions()->setEnabled( index == WFS_VERSION_1_1 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsNewHttpConnection::wfsFeaturePagingStateChanged( int state )
 | 
			
		||||
@ -256,6 +257,11 @@ QCheckBox *QgsNewHttpConnection::wfsPagingEnabledCheckBox()
 | 
			
		||||
  return cbxWfsFeaturePaging;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QCheckBox *QgsNewHttpConnection::wfsUseGml2EncodingForTransactions()
 | 
			
		||||
{
 | 
			
		||||
  return cbxWfsUseGml2EncodingForTransactions;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QLineEdit *QgsNewHttpConnection::wfsPageSizeLineEdit()
 | 
			
		||||
{
 | 
			
		||||
  return txtPageSize;
 | 
			
		||||
@ -281,6 +287,8 @@ void QgsNewHttpConnection::updateServiceSpecificSettings()
 | 
			
		||||
  cbxWmsIgnoreReportedLayerExtents->setChecked( settings.value( wmsKey + QStringLiteral( "/ignoreReportedLayerExtents" ), false ).toBool() );
 | 
			
		||||
  cbxWfsIgnoreAxisOrientation->setChecked( settings.value( wfsKey + "/ignoreAxisOrientation", false ).toBool() );
 | 
			
		||||
  cbxWfsInvertAxisOrientation->setChecked( settings.value( wfsKey + "/invertAxisOrientation", false ).toBool() );
 | 
			
		||||
  cbxWfsUseGml2EncodingForTransactions->setChecked( settings.value( wfsKey + "/preferCoordinatesForWfsT11", false ).toBool() );
 | 
			
		||||
 | 
			
		||||
  cbxWmsIgnoreAxisOrientation->setChecked( settings.value( wmsKey + "/ignoreAxisOrientation", false ).toBool() );
 | 
			
		||||
  cbxWmsInvertAxisOrientation->setChecked( settings.value( wmsKey + "/invertAxisOrientation", false ).toBool() );
 | 
			
		||||
  cbxIgnoreGetFeatureInfoURI->setChecked( settings.value( wmsKey + "/ignoreGetFeatureInfoURI", false ).toBool() );
 | 
			
		||||
@ -463,6 +471,7 @@ void QgsNewHttpConnection::accept()
 | 
			
		||||
  {
 | 
			
		||||
    settings.setValue( wfsKey + "/ignoreAxisOrientation", cbxWfsIgnoreAxisOrientation->isChecked() );
 | 
			
		||||
    settings.setValue( wfsKey + "/invertAxisOrientation", cbxWfsInvertAxisOrientation->isChecked() );
 | 
			
		||||
    settings.setValue( wfsKey + "/preferCoordinatesForWfsT11", cbxWfsUseGml2EncodingForTransactions->isChecked() );
 | 
			
		||||
  }
 | 
			
		||||
  if ( mTypes & ConnectionWms || mTypes & ConnectionWcs )
 | 
			
		||||
  {
 | 
			
		||||
 | 
			
		||||
@ -150,6 +150,12 @@ class GUI_EXPORT QgsNewHttpConnection : public QDialog, private Ui::QgsNewHttpCo
 | 
			
		||||
     */
 | 
			
		||||
    QCheckBox *wfsPagingEnabledCheckBox() SIP_SKIP;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the "Use GML2 encoding for transactions" checkbox
 | 
			
		||||
     * \since QGIS 3.16
 | 
			
		||||
     */
 | 
			
		||||
    QCheckBox *wfsUseGml2EncodingForTransactions() SIP_SKIP;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the "WFS page size" edit
 | 
			
		||||
     * \since QGIS 3.2
 | 
			
		||||
 | 
			
		||||
@ -53,6 +53,13 @@ QgsWfsConnection::QgsWfsConnection( const QString &connName )
 | 
			
		||||
                   settings.value( key + "/" + QgsWFSConstants::SETTINGS_PAGING_ENABLED, true ).toBool() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ( settings.contains( key + "/" + QgsWFSConstants::SETTINGS_WFST_1_1_PREFER_COORDINATES ) )
 | 
			
		||||
  {
 | 
			
		||||
    mUri.removeParam( QgsWFSConstants::URI_PARAM_WFST_1_1_PREFER_COORDINATES ); // setParam allow for duplicates!
 | 
			
		||||
    mUri.setParam( QgsWFSConstants::URI_PARAM_WFST_1_1_PREFER_COORDINATES,
 | 
			
		||||
                   settings.value( key + "/" + QgsWFSConstants::SETTINGS_WFST_1_1_PREFER_COORDINATES, true ).toBool() ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QgsDebugMsgLevel( QStringLiteral( "WFS full uri: '%1'." ).arg( QString( mUri.uri() ) ), 4 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ const QString QgsWFSConstants::URI_PARAM_VALIDATESQLFUNCTIONS( QStringLiteral( "
 | 
			
		||||
const QString QgsWFSConstants::URI_PARAM_HIDEDOWNLOADPROGRESSDIALOG( QStringLiteral( "hideDownloadProgressDialog" ) );
 | 
			
		||||
const QString QgsWFSConstants::URI_PARAM_PAGING_ENABLED( "pagingEnabled" );
 | 
			
		||||
const QString QgsWFSConstants::URI_PARAM_PAGE_SIZE( "pageSize" );
 | 
			
		||||
const QString QgsWFSConstants::URI_PARAM_WFST_1_1_PREFER_COORDINATES( "preferCoordinatesForWfsT11" );
 | 
			
		||||
 | 
			
		||||
const QString QgsWFSConstants::VERSION_AUTO( QStringLiteral( "auto" ) );
 | 
			
		||||
 | 
			
		||||
@ -48,3 +49,4 @@ const QString QgsWFSConstants::SETTINGS_VERSION( QStringLiteral( "version" ) );
 | 
			
		||||
const QString QgsWFSConstants::SETTINGS_MAXNUMFEATURES( QStringLiteral( "maxnumfeatures" ) );
 | 
			
		||||
const QString QgsWFSConstants::SETTINGS_PAGING_ENABLED( QStringLiteral( "pagingenabled" ) );
 | 
			
		||||
const QString QgsWFSConstants::SETTINGS_PAGE_SIZE( QStringLiteral( "pagesize" ) );
 | 
			
		||||
const QString QgsWFSConstants::SETTINGS_WFST_1_1_PREFER_COORDINATES( QStringLiteral( "preferCoordinatesForWfsT11" ) );
 | 
			
		||||
 | 
			
		||||
@ -48,6 +48,7 @@ struct QgsWFSConstants
 | 
			
		||||
  static const QString URI_PARAM_HIDEDOWNLOADPROGRESSDIALOG;
 | 
			
		||||
  static const QString URI_PARAM_PAGING_ENABLED;
 | 
			
		||||
  static const QString URI_PARAM_PAGE_SIZE;
 | 
			
		||||
  static const QString URI_PARAM_WFST_1_1_PREFER_COORDINATES;
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  static const QString VERSION_AUTO;
 | 
			
		||||
@ -58,6 +59,7 @@ struct QgsWFSConstants
 | 
			
		||||
  static const QString SETTINGS_MAXNUMFEATURES;
 | 
			
		||||
  static const QString SETTINGS_PAGING_ENABLED;
 | 
			
		||||
  static const QString SETTINGS_PAGE_SIZE;
 | 
			
		||||
  static const QString SETTINGS_WFST_1_1_PREFER_COORDINATES;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QGSWFSCONSTANTS_H
 | 
			
		||||
 | 
			
		||||
@ -373,6 +373,13 @@ bool QgsWFSDataSourceURI::hideDownloadProgressDialog() const
 | 
			
		||||
  return mURI.hasParam( QgsWFSConstants::URI_PARAM_HIDEDOWNLOADPROGRESSDIALOG );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool QgsWFSDataSourceURI::preferCoordinatesForWfst11() const
 | 
			
		||||
{
 | 
			
		||||
  return mURI.hasParam( QgsWFSConstants::URI_PARAM_WFST_1_1_PREFER_COORDINATES ) &&
 | 
			
		||||
         mURI.param( QgsWFSConstants::URI_PARAM_WFST_1_1_PREFER_COORDINATES ).toUpper() == QLatin1String( "TRUE" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString QgsWFSDataSourceURI::build( const QString &baseUri,
 | 
			
		||||
                                    const QString &typeName,
 | 
			
		||||
                                    const QString &crsString,
 | 
			
		||||
 | 
			
		||||
@ -113,6 +113,9 @@ class QgsWFSDataSourceURI
 | 
			
		||||
    //! Whether to hide download progress dialog in QGIS main app. Defaults to false
 | 
			
		||||
    bool hideDownloadProgressDialog() const;
 | 
			
		||||
 | 
			
		||||
    //! Whether to use "coordinates" instead of "pos" and "posList" for WFS-T 1.1 transactions (ESRI mapserver)
 | 
			
		||||
    bool preferCoordinatesForWfst11() const;
 | 
			
		||||
 | 
			
		||||
    //! Returns authorization parameters
 | 
			
		||||
    const QgsAuthorizationSettings &auth() const { return mAuth; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -787,6 +787,49 @@ void QgsWFSProvider::reloadProviderData()
 | 
			
		||||
  mShared->invalidateCache();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDomElement QgsWFSProvider::geometryElement( const QgsGeometry &geometry, QDomDocument &transactionDoc )
 | 
			
		||||
{
 | 
			
		||||
  QDomElement gmlElem;
 | 
			
		||||
 | 
			
		||||
  // Determine axis orientation and gml version
 | 
			
		||||
  bool applyAxisInversion;
 | 
			
		||||
  QgsOgcUtils::GMLVersion gmlVersion;
 | 
			
		||||
 | 
			
		||||
  if ( mShared->mWFSVersion.startsWith( QLatin1String( "1.1" ) ) )
 | 
			
		||||
  {
 | 
			
		||||
    // WFS 1.1.0 uses preferably GML 3, but ESRI mapserver in 2020 doesn't like it so we stick to GML2
 | 
			
		||||
    if ( ! mShared->mServerPrefersCoordinatesForTransactions_1_1 )
 | 
			
		||||
    {
 | 
			
		||||
      gmlVersion = QgsOgcUtils::GML_3_1_0;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      gmlVersion = QgsOgcUtils::GML_2_1_2;
 | 
			
		||||
    }
 | 
			
		||||
    // For servers like Geomedia and QGIS Server that advertise EPSG:XXXX in capabilities even in WFS 1.1 or 2.0
 | 
			
		||||
    // cpabilities useEPSGColumnFormat is set.
 | 
			
		||||
    // We follow GeoServer convention here which is to treat EPSG:4326 as lon/lat
 | 
			
		||||
    applyAxisInversion = ( crs().hasAxisInverted() && ! mShared->mURI.ignoreAxisOrientation() && ! mShared->mCaps.useEPSGColumnFormat )
 | 
			
		||||
                         || mShared->mURI.invertAxisOrientation();
 | 
			
		||||
  }
 | 
			
		||||
  else // 1.0
 | 
			
		||||
  {
 | 
			
		||||
    gmlVersion = QgsOgcUtils::GML_2_1_2;
 | 
			
		||||
    applyAxisInversion = mShared->mURI.invertAxisOrientation();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  gmlElem = QgsOgcUtils::geometryToGML(
 | 
			
		||||
              geometry,
 | 
			
		||||
              transactionDoc,
 | 
			
		||||
              gmlVersion,
 | 
			
		||||
              mShared->srsName(),
 | 
			
		||||
              applyAxisInversion,
 | 
			
		||||
              QString()
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
  return gmlElem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsWkbTypes::Type QgsWFSProvider::wkbType() const
 | 
			
		||||
{
 | 
			
		||||
  return mShared->mWKBType;
 | 
			
		||||
@ -877,10 +920,10 @@ bool QgsWFSProvider::addFeatures( QgsFeatureList &flist, Flags flags )
 | 
			
		||||
      {
 | 
			
		||||
        the_geom.convertToMultiType();
 | 
			
		||||
      }
 | 
			
		||||
      QDomElement gmlElem = QgsOgcUtils::geometryToGML( the_geom, transactionDoc );
 | 
			
		||||
      if ( !gmlElem.isNull() )
 | 
			
		||||
 | 
			
		||||
      const QDomElement gmlElem { geometryElement( the_geom, transactionDoc ) };
 | 
			
		||||
      if ( ! gmlElem.isNull() )
 | 
			
		||||
      {
 | 
			
		||||
        gmlElem.setAttribute( QStringLiteral( "srsName" ), crs().authid() );
 | 
			
		||||
        geomElem.appendChild( gmlElem );
 | 
			
		||||
        featureElem.appendChild( geomElem );
 | 
			
		||||
      }
 | 
			
		||||
@ -1045,9 +1088,9 @@ bool QgsWFSProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )
 | 
			
		||||
    nameElem.appendChild( nameText );
 | 
			
		||||
    propertyElem.appendChild( nameElem );
 | 
			
		||||
    QDomElement valueElem = transactionDoc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Value" ) );
 | 
			
		||||
    QDomElement gmlElem = QgsOgcUtils::geometryToGML( geomIt.value(), transactionDoc );
 | 
			
		||||
    gmlElem.setAttribute( QStringLiteral( "srsName" ), crs().authid() );
 | 
			
		||||
    valueElem.appendChild( gmlElem );
 | 
			
		||||
 | 
			
		||||
    valueElem.appendChild( geometryElement( geomIt.value(), transactionDoc ) );
 | 
			
		||||
 | 
			
		||||
    propertyElem.appendChild( valueElem );
 | 
			
		||||
    updateElem.appendChild( propertyElem );
 | 
			
		||||
 | 
			
		||||
@ -1264,6 +1307,8 @@ bool QgsWFSProvider::describeFeatureType( QString &geometryAttribute, QgsFields
 | 
			
		||||
 | 
			
		||||
  QByteArray response = describeFeatureType.response();
 | 
			
		||||
 | 
			
		||||
  QgsDebugMsgLevel( response, 4 );
 | 
			
		||||
 | 
			
		||||
  QDomDocument describeFeatureDocument;
 | 
			
		||||
  QString errorMsg;
 | 
			
		||||
  if ( !describeFeatureDocument.setContent( response, true, &errorMsg ) )
 | 
			
		||||
@ -1580,6 +1625,8 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument &doc, QDomDocum
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QgsDebugMsgLevel( doc.toString(), 4 );
 | 
			
		||||
 | 
			
		||||
  QgsWFSTransactionRequest request( mShared->mURI );
 | 
			
		||||
  return request.send( doc, serverResponse );
 | 
			
		||||
}
 | 
			
		||||
@ -1587,10 +1634,16 @@ bool QgsWFSProvider::sendTransactionDocument( const QDomDocument &doc, QDomDocum
 | 
			
		||||
QDomElement QgsWFSProvider::createTransactionElement( QDomDocument &doc ) const
 | 
			
		||||
{
 | 
			
		||||
  QDomElement transactionElem = doc.createElementNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Transaction" ) );
 | 
			
		||||
  // QString WfsVersion = mShared->mWFSVersion;
 | 
			
		||||
  // For now: hardcoded to 1.0.0
 | 
			
		||||
  QString WfsVersion = QStringLiteral( "1.0.0" );
 | 
			
		||||
  transactionElem.setAttribute( QStringLiteral( "version" ), WfsVersion );
 | 
			
		||||
  const QString WfsVersion = mShared->mWFSVersion;
 | 
			
		||||
  // only 1.1.0 and 1.0.0 are supported
 | 
			
		||||
  if ( WfsVersion == QStringLiteral( "1.1.0" ) )
 | 
			
		||||
  {
 | 
			
		||||
    transactionElem.setAttribute( QStringLiteral( "version" ), WfsVersion );
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    transactionElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
 | 
			
		||||
  }
 | 
			
		||||
  transactionElem.setAttribute( QStringLiteral( "service" ), QStringLiteral( "WFS" ) );
 | 
			
		||||
  transactionElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
 | 
			
		||||
 | 
			
		||||
@ -1634,19 +1687,70 @@ bool QgsWFSProvider::transactionSuccess( const QDomDocument &serverResponse ) co
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QDomNodeList transactionResultList = documentElem.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TransactionResult" ) );
 | 
			
		||||
  if ( transactionResultList.size() < 1 )
 | 
			
		||||
  const QString WfsVersion = mShared->mWFSVersion;
 | 
			
		||||
 | 
			
		||||
  if ( WfsVersion == QStringLiteral( "1.1.0" ) )
 | 
			
		||||
  {
 | 
			
		||||
    const QDomNodeList transactionSummaryList = documentElem.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TransactionSummary" ) );
 | 
			
		||||
    if ( transactionSummaryList.size() < 1 )
 | 
			
		||||
    {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QDomElement transactionElement { transactionSummaryList.at( 0 ).toElement() };
 | 
			
		||||
    QDomNodeList totalInserted = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "totalInserted" ) );
 | 
			
		||||
    QDomNodeList totalUpdated = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "totalUpdated" ) );
 | 
			
		||||
    QDomNodeList totalDeleted = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "totalDeleted" ) );
 | 
			
		||||
    if ( totalInserted.size() > 0 && totalInserted.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if ( totalUpdated.size() > 0 && totalUpdated.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if ( totalDeleted.size() > 0 && totalDeleted.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle wrong QGIS server response (capital initial letter)
 | 
			
		||||
    totalInserted = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TotalInserted" ) );
 | 
			
		||||
    totalUpdated = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TotalUpdated" ) );
 | 
			
		||||
    totalDeleted = transactionElement.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TotalDeleted" ) );
 | 
			
		||||
    if ( totalInserted.size() > 0 && totalInserted.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if ( totalUpdated.size() > 0 && totalUpdated.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if ( totalDeleted.size() > 0 && totalDeleted.at( 0 ).toElement().text().toInt() > 0 )
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    const QDomNodeList transactionResultList = documentElem.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "TransactionResult" ) );
 | 
			
		||||
    if ( transactionResultList.size() < 1 )
 | 
			
		||||
    {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const QDomNodeList statusList = transactionResultList.at( 0 ).toElement().elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Status" ) );
 | 
			
		||||
    if ( statusList.size() < 1 )
 | 
			
		||||
    {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return statusList.at( 0 ).firstChildElement().localName() == QLatin1String( "SUCCESS" );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QDomNodeList statusList = transactionResultList.at( 0 ).toElement().elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "Status" ) );
 | 
			
		||||
  if ( statusList.size() < 1 )
 | 
			
		||||
  {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return statusList.at( 0 ).firstChildElement().localName() == QLatin1String( "SUCCESS" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStringList QgsWFSProvider::insertedFeatureIds( const QDomDocument &serverResponse ) const
 | 
			
		||||
@ -1663,7 +1767,17 @@ QStringList QgsWFSProvider::insertedFeatureIds( const QDomDocument &serverRespon
 | 
			
		||||
    return ids;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QDomNodeList insertResultList = rootElem.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, QStringLiteral( "InsertResult" ) );
 | 
			
		||||
  // Handles WFS 1.1.0
 | 
			
		||||
  QString insertResultTagName;
 | 
			
		||||
  if ( mShared->mWFSVersion == QStringLiteral( "1.1.0" ) )
 | 
			
		||||
  {
 | 
			
		||||
    insertResultTagName = QStringLiteral( "InsertResults" );
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    insertResultTagName = QStringLiteral( "InsertResult" );
 | 
			
		||||
  }
 | 
			
		||||
  QDomNodeList insertResultList = rootElem.elementsByTagNameNS( QgsWFSConstants::WFS_NAMESPACE, insertResultTagName );
 | 
			
		||||
  for ( int i = 0; i < insertResultList.size(); ++i )
 | 
			
		||||
  {
 | 
			
		||||
    QDomNodeList featureIdList = insertResultList.at( i ).toElement().elementsByTagNameNS( QgsWFSConstants::OGC_NAMESPACE, QStringLiteral( "FeatureId" ) );
 | 
			
		||||
@ -1850,6 +1964,14 @@ void QgsWFSProvider::handleException( const QDomDocument &serverResponse )
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // WFS 1.1.0
 | 
			
		||||
  if ( exceptionElem.tagName() == QLatin1String( "TransactionResponse" ) )
 | 
			
		||||
  {
 | 
			
		||||
    pushError( tr( "Unsuccessful service response: no features were added, deleted or changed." ) );
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if ( exceptionElem.tagName() == QLatin1String( "ExceptionReport" ) )
 | 
			
		||||
  {
 | 
			
		||||
    QDomElement exception = exceptionElem.firstChildElement( QStringLiteral( "Exception" ) );
 | 
			
		||||
 | 
			
		||||
@ -140,6 +140,11 @@ class QgsWFSProvider final: public QgsVectorDataProvider
 | 
			
		||||
 | 
			
		||||
    friend class QgsWFSFeatureSource;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the geometry element
 | 
			
		||||
     */
 | 
			
		||||
    QDomElement geometryElement( const QgsGeometry &geometry, QDomDocument &transactionDoc );
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
 | 
			
		||||
    //! String used to define a subset of the layer
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ QgsWFSSharedData::QgsWFSSharedData( const QString &uri )
 | 
			
		||||
  , mURI( uri )
 | 
			
		||||
{
 | 
			
		||||
  mHideProgressDialog = mURI.hideDownloadProgressDialog();
 | 
			
		||||
  mServerPrefersCoordinatesForTransactions_1_1 = mURI.preferCoordinatesForWfst11();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsWFSSharedData::~QgsWFSSharedData()
 | 
			
		||||
 | 
			
		||||
@ -89,6 +89,11 @@ class QgsWFSSharedData : public QObject, public QgsBackgroundCachedSharedData
 | 
			
		||||
    */
 | 
			
		||||
    bool mGetFeatureEPSGDotHonoursEPSGOrder = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If the server (typically ESRI with WFS-T 1.1 in 2020) does not like "pos" and "posList", and requires "coordinates" for WFS 1.1 transactions
 | 
			
		||||
     */
 | 
			
		||||
    bool mServerPrefersCoordinatesForTransactions_1_1 = false;
 | 
			
		||||
 | 
			
		||||
    //! Geometry type of the features in this layer
 | 
			
		||||
    QgsWkbTypes::Type mWKBType = QgsWkbTypes::Unknown;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>448</width>
 | 
			
		||||
    <height>761</height>
 | 
			
		||||
    <height>815</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
@ -173,9 +173,6 @@
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="0" column="1">
 | 
			
		||||
          <widget class="QComboBox" name="cmbVersion"/>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="0" column="2">
 | 
			
		||||
          <widget class="QPushButton" name="mWfsVersionDetectButton">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
@ -183,42 +180,45 @@
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="1" column="0">
 | 
			
		||||
          <widget class="QLabel" name="lblMaxNumFeatures">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Max. number of features</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="1" column="1" colspan="2">
 | 
			
		||||
          <widget class="QLineEdit" name="txtMaxNumFeatures">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string><html><head/><body><p>Enter a number to limit the maximum number of features retrieved per feature request. If let to empty, no limit is set.</p></body></html></string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="3" column="0">
 | 
			
		||||
          <widget class="QLabel" name="lblPageSize">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Page size</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="3" column="1" colspan="2">
 | 
			
		||||
          <widget class="QLineEdit" name="txtPageSize">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string><html><head/><body><p>Enter a number to limit the maximum number of features retrieved in a single GetFeature request when paging is enabled. If let to empty, server default will apply.</p></body></html></string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="4" column="0" colspan="3">
 | 
			
		||||
         <item row="5" column="0" colspan="3">
 | 
			
		||||
          <widget class="QCheckBox" name="cbxWfsIgnoreAxisOrientation">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Ignore axis orientation (WFS 1.1/WFS 2.0)</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="2" column="0" colspan="3">
 | 
			
		||||
         <item row="2" column="0">
 | 
			
		||||
          <widget class="QLabel" name="lblMaxNumFeatures">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Max. number of features</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="0" column="1">
 | 
			
		||||
          <widget class="QComboBox" name="cmbVersion"/>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="4" column="1" colspan="2">
 | 
			
		||||
          <widget class="QLineEdit" name="txtPageSize">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string><html><head/><body><p>Enter a number to limit the maximum number of features retrieved in a single GetFeature request when paging is enabled. If let to empty, server default will apply.</p></body></html></string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="6" column="0" colspan="3">
 | 
			
		||||
          <widget class="QCheckBox" name="cbxWfsInvertAxisOrientation">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Invert axis orientation</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="4" column="0">
 | 
			
		||||
          <widget class="QLabel" name="lblPageSize">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Page size</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="3" column="0" colspan="3">
 | 
			
		||||
          <widget class="QCheckBox" name="cbxWfsFeaturePaging">
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Enable feature paging</string>
 | 
			
		||||
@ -228,10 +228,20 @@
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="5" column="0" colspan="3">
 | 
			
		||||
          <widget class="QCheckBox" name="cbxWfsInvertAxisOrientation">
 | 
			
		||||
         <item row="2" column="1" colspan="2">
 | 
			
		||||
          <widget class="QLineEdit" name="txtMaxNumFeatures">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string><html><head/><body><p>Enter a number to limit the maximum number of features retrieved per feature request. If let to empty, no limit is set.</p></body></html></string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
         <item row="7" column="0" colspan="2">
 | 
			
		||||
          <widget class="QCheckBox" name="cbxWfsUseGml2EncodingForTransactions">
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string><html><head/><body><p>This might be necessary on some <span style=" font-weight:600;">broken</span> ESRI map servers when using WFS-T 1.1.0.</p></body></html></string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="text">
 | 
			
		||||
            <string>Invert axis orientation</string>
 | 
			
		||||
            <string>Use GML2 encoding for transactions</string>
 | 
			
		||||
           </property>
 | 
			
		||||
          </widget>
 | 
			
		||||
         </item>
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,9 @@ from qgis.testing import (start_app,
 | 
			
		||||
                          unittest
 | 
			
		||||
                          )
 | 
			
		||||
from providertestbase import ProviderTestCase
 | 
			
		||||
from utilities import unitTestDataPath
 | 
			
		||||
 | 
			
		||||
TEST_DATA_DIR = unitTestDataPath()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sanitize(endpoint, x):
 | 
			
		||||
@ -4705,6 +4708,67 @@ Can't recognize service requested.
 | 
			
		||||
            self.assertEqual(len(logger.messages()), 1, logger.messages())
 | 
			
		||||
            self.assertTrue("InvalidFormat: Can't recognize service requested." in logger.messages()[0].decode('UTF-8'), logger.messages())
 | 
			
		||||
 | 
			
		||||
    def testWFST11(self):
 | 
			
		||||
        """Test WFS-T 1.1 (read-write) taken from a geoserver session"""
 | 
			
		||||
 | 
			
		||||
        endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_T_1_1_transaction'
 | 
			
		||||
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'getcapabilities.xml'), sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.1.0'))
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'describefeaturetype_polygons.xml'), sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=ws1:polygons'))
 | 
			
		||||
 | 
			
		||||
        vl = QgsVectorLayer("url='http://" + endpoint + "' typename='ws1:polygons' version='1.1.0'", 'test', 'WFS')
 | 
			
		||||
        self.assertTrue(vl.isValid())
 | 
			
		||||
        self.assertEqual(vl.featureCount(), 0)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(vl.dataProvider().capabilities(),
 | 
			
		||||
                         QgsVectorDataProvider.AddFeatures
 | 
			
		||||
                         | QgsVectorDataProvider.ChangeAttributeValues
 | 
			
		||||
                         | QgsVectorDataProvider.ChangeGeometries
 | 
			
		||||
                         | QgsVectorDataProvider.DeleteFeatures
 | 
			
		||||
                         | QgsVectorDataProvider.SelectAtId)
 | 
			
		||||
 | 
			
		||||
        # Transaction response failure (no modifications)
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'transaction_response_empty.xml'), sanitize(endpoint, '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http:__www.opengis.net_wfs" xmlns:xsi="http:__www.w3.org_2001_XMLSchema-instance" xmlns:gml="http:__www.opengis.net_gml" xmlns:ws1="ws1" xsi:schemaLocation="ws1 http:__fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS"><Insert xmlns="http:__www.opengis.net_wfs"><polygons xmlns="ws1"_><_Insert><_Transaction>'))
 | 
			
		||||
 | 
			
		||||
        (ret, _) = vl.dataProvider().addFeatures([QgsFeature()])
 | 
			
		||||
        self.assertFalse(ret)
 | 
			
		||||
        self.assertEqual(vl.featureCount(), 0)
 | 
			
		||||
 | 
			
		||||
        # Test add features for real
 | 
			
		||||
        # Transaction response with 1 feature added
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'transaction_response_feature_added.xml'), sanitize(endpoint, '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http:__www.opengis.net_wfs" xmlns:xsi="http:__www.w3.org_2001_XMLSchema-instance" xmlns:gml="http:__www.opengis.net_gml" xmlns:ws1="ws1" xsi:schemaLocation="ws1 http:__fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS"><Insert xmlns="http:__www.opengis.net_wfs"><polygons xmlns="ws1"><name xmlns="ws1">one<_name><value xmlns="ws1">1<_value><geometry xmlns="ws1"><gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"><gml:exterior><gml:LinearRing><gml:posList srsDimension="2">45 9 45 10 46 10 46 9 45 9<_gml:posList><_gml:LinearRing><_gml:exterior><_gml:Polygon><_geometry><_polygons><_Insert><_Transaction>'))
 | 
			
		||||
 | 
			
		||||
        feat = QgsFeature(vl.fields())
 | 
			
		||||
        feat.setAttribute('name', 'one')
 | 
			
		||||
        feat.setAttribute('value', 1)
 | 
			
		||||
        feat.setGeometry(QgsGeometry.fromWkt('Polygon ((9 45, 10 45, 10 46, 9 46, 9 45))'))
 | 
			
		||||
        (ret, features) = vl.dataProvider().addFeatures([feat])
 | 
			
		||||
        self.assertEqual(features[0].attributes(), ['one', 1])
 | 
			
		||||
        self.assertEqual(vl.featureCount(), 1)
 | 
			
		||||
 | 
			
		||||
        # Test change attributes
 | 
			
		||||
        # Transaction response with 1 feature changed
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'transaction_response_feature_changed.xml'), sanitize(endpoint, '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xmlns:ws1="ws1" xsi:schemaLocation="ws1 http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS"><Update xmlns="http://www.opengis.net/wfs" typeName="ws1:polygons"><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">ws1:name</Name><Value xmlns="http://www.opengis.net/wfs">one-one-one</Value></Property><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">ws1:value</Name><Value xmlns="http://www.opengis.net/wfs">111</Value></Property><Filter xmlns="http://www.opengis.net/ogc"><FeatureId xmlns="http://www.opengis.net/ogc" fid="123"/></Filter></Update></Transaction>'))
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(vl.dataProvider().changeAttributeValues({1: {0: 'one-one-one', 1: 111}}))
 | 
			
		||||
        self.assertEqual(next(vl.dataProvider().getFeatures()).attributes(), ['one-one-one', 111])
 | 
			
		||||
 | 
			
		||||
        # Test change geometry
 | 
			
		||||
        # Transaction response with 1 feature changed
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'transaction_response_feature_changed.xml'), sanitize(endpoint, '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http:__www.opengis.net_wfs" xmlns:xsi="http:__www.w3.org_2001_XMLSchema-instance" xmlns:gml="http:__www.opengis.net_gml" xmlns:ws1="ws1" xsi:schemaLocation="ws1 http:__fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS"><Update xmlns="http:__www.opengis.net_wfs" typeName="ws1:polygons"><Property xmlns="http:__www.opengis.net_wfs"><Name xmlns="http:__www.opengis.net_wfs">ws1:geometry<_Name><Value xmlns="http:__www.opengis.net_wfs"><gml:Polygon srsName="urn:ogc:def:crs:EPSG::4326"><gml:exterior><gml:LinearRing><gml:posList srsDimension="2">46 10 46 11 47 11 47 10 46 10<_gml:posList><_gml:LinearRing><_gml:exterior><_gml:Polygon><_Value><_Property><Filter xmlns="http:__www.opengis.net_ogc"><FeatureId xmlns="http:__www.opengis.net_ogc" fid="123"_><_Filter><_Update><_Transaction>'))
 | 
			
		||||
 | 
			
		||||
        new_geom = QgsGeometry.fromWkt('Polygon ((10 46, 11 46, 11 47, 10 47, 10 46))')
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(vl.dataProvider().changeGeometryValues({1: new_geom}))
 | 
			
		||||
        self.assertEqual(next(vl.dataProvider().getFeatures()).geometry().asWkt(), new_geom.asWkt())
 | 
			
		||||
 | 
			
		||||
        # Test delete feature
 | 
			
		||||
        # Transaction response with 1 feature deleted
 | 
			
		||||
        shutil.copy(os.path.join(TEST_DATA_DIR, 'provider', 'wfst-1-1', 'transaction_response_feature_deleted.xml'), sanitize(endpoint, '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xmlns:ws1="ws1" xsi:schemaLocation="ws1 http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS"><Delete xmlns="http://www.opengis.net/wfs" typeName="ws1:polygons"><Filter xmlns="http://www.opengis.net/ogc"><FeatureId xmlns="http://www.opengis.net/ogc" fid="123"/></Filter></Delete></Transaction>'))
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(vl.dataProvider().deleteFeatures([1]))
 | 
			
		||||
        self.assertEqual(vl.featureCount(), 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
@ -60,9 +60,12 @@ qgis_app = start_app()
 | 
			
		||||
 | 
			
		||||
class TestWFST(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    VERSION = '1.0.0'
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def setUpClass(cls):
 | 
			
		||||
        """Run before all tests"""
 | 
			
		||||
 | 
			
		||||
        cls.port = QGIS_SERVER_PORT
 | 
			
		||||
        # Create tmp folder
 | 
			
		||||
        cls.temp_path = tempfile.mkdtemp()
 | 
			
		||||
@ -92,11 +95,13 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        cls.port = int(re.findall(br':(\d+)', line)[0])
 | 
			
		||||
        assert cls.port != 0
 | 
			
		||||
        # Wait for the server process to start
 | 
			
		||||
        assert waitServer('http://127.0.0.1:%s' % cls.port), "Server is not responding!"
 | 
			
		||||
        assert waitServer('http://127.0.0.1:%s' %
 | 
			
		||||
                          cls.port), "Server is not responding!"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def tearDownClass(cls):
 | 
			
		||||
        """Run after all tests"""
 | 
			
		||||
 | 
			
		||||
        cls.server.terminate()
 | 
			
		||||
        cls.server.wait()
 | 
			
		||||
        del cls.server
 | 
			
		||||
@ -107,10 +112,12 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        """Run before each test."""
 | 
			
		||||
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        """Run after each test."""
 | 
			
		||||
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
@ -118,6 +125,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Delete all features from a vector layer
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        layer = cls._getLayer(layer_name)
 | 
			
		||||
        layer.startEditing()
 | 
			
		||||
        layer.deleteFeatures([f.id() for f in layer.getFeatures()])
 | 
			
		||||
@ -129,6 +137,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        OGR Layer factory
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        path = cls.testdata_path + layer_name + '.shp'
 | 
			
		||||
        layer = QgsVectorLayer(path, layer_name, "ogr")
 | 
			
		||||
        assert layer.isValid()
 | 
			
		||||
@ -139,6 +148,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        WFS layer factory
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if layer_name is None:
 | 
			
		||||
            layer_name = 'wfs_' + type_name
 | 
			
		||||
        parms = {
 | 
			
		||||
@ -146,7 +156,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
            'typename': type_name,
 | 
			
		||||
            'url': 'http://127.0.0.1:%s/?map=%s' % (cls.port,
 | 
			
		||||
                                                    cls.project_path),
 | 
			
		||||
            'version': 'auto',
 | 
			
		||||
            'version': cls.VERSION,
 | 
			
		||||
            'table': '',
 | 
			
		||||
            # 'sql': '',
 | 
			
		||||
        }
 | 
			
		||||
@ -160,6 +170,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Find the feature and return it, raise exception if not found
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        request = QgsFeatureRequest(QgsExpression("%s=%s" % (attr_name,
 | 
			
		||||
                                                             attr_value)))
 | 
			
		||||
        try:
 | 
			
		||||
@ -172,21 +183,36 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Check features were added
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        wfs_layer.dataProvider().addFeatures(features)
 | 
			
		||||
        layer = self._getLayer(layer.name())
 | 
			
		||||
        self.assertTrue(layer.isValid())
 | 
			
		||||
        self.assertEqual(layer.featureCount(), len(features))
 | 
			
		||||
        self.assertEqual(wfs_layer.dataProvider().featureCount(), len(features))
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            wfs_layer.dataProvider().featureCount(), len(features))
 | 
			
		||||
 | 
			
		||||
        ogr_features = [f for f in layer.dataProvider().getFeatures()]
 | 
			
		||||
 | 
			
		||||
        # Verify features from the layers
 | 
			
		||||
        for f in ogr_features:
 | 
			
		||||
            geom = next(wfs_layer.dataProvider().getFeatures(QgsFeatureRequest(
 | 
			
		||||
                QgsExpression('"id" = %s' % f.attribute('id'))))).geometry()
 | 
			
		||||
            self.assertEqual(geom.boundingBox(), f.geometry().boundingBox())
 | 
			
		||||
 | 
			
		||||
    def _checkUpdateFeatures(self, wfs_layer, old_features, new_features):
 | 
			
		||||
        """
 | 
			
		||||
        Check features can be updated
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        for i in range(len(old_features)):
 | 
			
		||||
            f = self._getFeatureByAttribute(wfs_layer, 'id', old_features[i]['id'])
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeGeometryValues({f.id(): new_features[i].geometry()}))
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeAttributeValues({f.id(): {0: new_features[i]['id']}}))
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeAttributeValues({f.id(): {1: new_features[i]['name']}}))
 | 
			
		||||
            f = self._getFeatureByAttribute(
 | 
			
		||||
                wfs_layer, 'id', old_features[i]['id'])
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeGeometryValues(
 | 
			
		||||
                {f.id(): new_features[i].geometry()}))
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeAttributeValues(
 | 
			
		||||
                {f.id(): {0: new_features[i]['id']}}))
 | 
			
		||||
            self.assertTrue(wfs_layer.dataProvider().changeAttributeValues(
 | 
			
		||||
                {f.id(): {1: new_features[i]['name']}}))
 | 
			
		||||
 | 
			
		||||
    def _checkMatchFeatures(self, wfs_layer, features):
 | 
			
		||||
        """
 | 
			
		||||
@ -202,6 +228,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Delete features
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        ids = []
 | 
			
		||||
        for f in features:
 | 
			
		||||
            wf = self._getFeatureByAttribute(layer, 'id', f['id'])
 | 
			
		||||
@ -212,6 +239,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Perform all test steps on the layer.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(wfs_layer.featureCount(), 0)
 | 
			
		||||
        self._checkAddFeatures(wfs_layer, layer, old_features)
 | 
			
		||||
        self._checkMatchFeatures(wfs_layer, old_features)
 | 
			
		||||
@ -226,6 +254,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Adds some points, then check and clear all
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        layer_name = 'test_point'
 | 
			
		||||
        layer = self._getLayer(layer_name)
 | 
			
		||||
        wfs_layer = self._getWFSLayer(layer_name)
 | 
			
		||||
@ -248,6 +277,7 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        Adds some points, then check.
 | 
			
		||||
        Modify 2 points, then checks and clear all
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        layer_name = 'test_point'
 | 
			
		||||
        layer = self._getLayer(layer_name)
 | 
			
		||||
        wfs_layer = self._getWFSLayer(layer_name)
 | 
			
		||||
@ -276,15 +306,18 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Adds some polygons, then check and clear all
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        layer_name = 'test_polygon'
 | 
			
		||||
        layer = self._getLayer(layer_name)
 | 
			
		||||
        wfs_layer = self._getWFSLayer(layer_name)
 | 
			
		||||
        feat1 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        feat1['id'] = 11
 | 
			
		||||
        feat1['name'] = 'name 11'
 | 
			
		||||
        feat1.setGeometry(QgsGeometry.fromRect(QgsRectangle(QgsPointXY(9, 45), QgsPointXY(10, 46))))
 | 
			
		||||
        feat1.setGeometry(QgsGeometry.fromRect(
 | 
			
		||||
            QgsRectangle(QgsPointXY(9, 45), QgsPointXY(10, 46))))
 | 
			
		||||
        feat2 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        feat2.setGeometry(QgsGeometry.fromRect(QgsRectangle(QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5))))
 | 
			
		||||
        feat2.setGeometry(QgsGeometry.fromRect(QgsRectangle(
 | 
			
		||||
            QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5))))
 | 
			
		||||
        feat2['id'] = 12
 | 
			
		||||
        feat2['name'] = 'name 12'
 | 
			
		||||
        old_features = [feat1, feat2]
 | 
			
		||||
@ -292,7 +325,8 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        new_feat1 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        new_feat1['id'] = 121
 | 
			
		||||
        new_feat1['name'] = 'name 121'
 | 
			
		||||
        new_feat1.setGeometry(QgsGeometry.fromRect(QgsRectangle(QgsPointXY(10, 46), QgsPointXY(11.5, 47.5))))
 | 
			
		||||
        new_feat1.setGeometry(QgsGeometry.fromRect(
 | 
			
		||||
            QgsRectangle(QgsPointXY(10, 46), QgsPointXY(11.5, 47.5))))
 | 
			
		||||
        new_features = [new_feat1, feat2]
 | 
			
		||||
        self._testLayer(wfs_layer, layer, old_features, new_features)
 | 
			
		||||
 | 
			
		||||
@ -300,15 +334,18 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        """
 | 
			
		||||
        Adds some lines, then check and clear all
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        layer_name = 'test_linestring'
 | 
			
		||||
        layer = self._getLayer(layer_name)
 | 
			
		||||
        wfs_layer = self._getWFSLayer(layer_name)
 | 
			
		||||
        feat1 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        feat1['id'] = 11
 | 
			
		||||
        feat1['name'] = 'name 11'
 | 
			
		||||
        feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9, 45), QgsPointXY(10, 46)]))
 | 
			
		||||
        feat1.setGeometry(QgsGeometry.fromPolylineXY(
 | 
			
		||||
            [QgsPointXY(9, 45), QgsPointXY(10, 46)]))
 | 
			
		||||
        feat2 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        feat2.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5)]))
 | 
			
		||||
        feat2.setGeometry(QgsGeometry.fromPolylineXY(
 | 
			
		||||
            [QgsPointXY(9.5, 45.5), QgsPointXY(10.5, 46.5)]))
 | 
			
		||||
        feat2['id'] = 12
 | 
			
		||||
        feat2['name'] = 'name 12'
 | 
			
		||||
        old_features = [feat1, feat2]
 | 
			
		||||
@ -316,10 +353,17 @@ class TestWFST(unittest.TestCase):
 | 
			
		||||
        new_feat1 = QgsFeature(wfs_layer.fields())
 | 
			
		||||
        new_feat1['id'] = 121
 | 
			
		||||
        new_feat1['name'] = 'name 121'
 | 
			
		||||
        new_feat1.setGeometry(QgsGeometry.fromPolylineXY([QgsPointXY(9.8, 45.8), QgsPointXY(10.8, 46.8)]))
 | 
			
		||||
        new_feat1.setGeometry(QgsGeometry.fromPolylineXY(
 | 
			
		||||
            [QgsPointXY(9.8, 45.8), QgsPointXY(10.8, 46.8)]))
 | 
			
		||||
        new_features = [new_feat1, feat2]
 | 
			
		||||
        self._testLayer(wfs_layer, layer, old_features, new_features)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestWFST11(TestWFST):
 | 
			
		||||
    """Same tests for WFS 1.1"""
 | 
			
		||||
 | 
			
		||||
    VERSION = '1.1.0'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								tests/testdata/provider/wfst-1-1/describefeaturetype_polygons.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/testdata/provider/wfst-1-1/describefeaturetype_polygons.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" xmlns:ws1="ws1" elementFormDefault="qualified" targetNamespace="ws1">
 | 
			
		||||
  <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://localhost:8600/geoserver/schemas/gml/3.1.1/base/gml.xsd"/>
 | 
			
		||||
  <xsd:complexType name="polygonsType">
 | 
			
		||||
    <xsd:complexContent>
 | 
			
		||||
      <xsd:extension base="gml:AbstractFeatureType">
 | 
			
		||||
        <xsd:sequence>
 | 
			
		||||
          <xsd:element maxOccurs="1" minOccurs="0" name="geometry" nillable="true" type="gml:SurfacePropertyType"/>
 | 
			
		||||
          <xsd:element maxOccurs="1" minOccurs="0" name="name" nillable="true" type="xsd:string"/>
 | 
			
		||||
          <xsd:element maxOccurs="1" minOccurs="0" name="value" nillable="true" type="xsd:int"/>
 | 
			
		||||
        </xsd:sequence>
 | 
			
		||||
      </xsd:extension>
 | 
			
		||||
    </xsd:complexContent>
 | 
			
		||||
  </xsd:complexType>
 | 
			
		||||
  <xsd:element name="polygons" substitutionGroup="gml:_Feature" type="ws1:polygonsType"/>
 | 
			
		||||
</xsd:schema>
 | 
			
		||||
							
								
								
									
										474
									
								
								tests/testdata/provider/wfst-1-1/getcapabilities.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										474
									
								
								tests/testdata/provider/wfst-1-1/getcapabilities.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,474 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- this is a sample response from geoserver,
 | 
			
		||||
    OperationsMetadata was commented out because of fake endpoints -->
 | 
			
		||||
<wfs:WFS_Capabilities version="1.1.0"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
    xmlns="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:wfs="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:ows="http://www.opengis.net/ows"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net/gml"
 | 
			
		||||
    xmlns:ogc="http://www.opengis.net/ogc"
 | 
			
		||||
    xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8600/geoserver/schemas/wfs/1.1.0/wfs.xsd"
 | 
			
		||||
    xmlns:ws1="ws1" updateSequence="34">
 | 
			
		||||
    <ows:ServiceIdentification>
 | 
			
		||||
        <ows:Title/>
 | 
			
		||||
        <ows:Abstract/>
 | 
			
		||||
        <ows:ServiceType>WFS</ows:ServiceType>
 | 
			
		||||
        <ows:ServiceTypeVersion>1.1.0</ows:ServiceTypeVersion>
 | 
			
		||||
        <ows:Fees/>
 | 
			
		||||
        <ows:AccessConstraints/>
 | 
			
		||||
    </ows:ServiceIdentification>
 | 
			
		||||
    <ows:ServiceProvider>
 | 
			
		||||
        <ows:ProviderName/>
 | 
			
		||||
        <ows:ServiceContact>
 | 
			
		||||
            <ows:IndividualName/>
 | 
			
		||||
            <ows:PositionName/>
 | 
			
		||||
            <ows:ContactInfo>
 | 
			
		||||
                <ows:Phone>
 | 
			
		||||
                    <ows:Voice/>
 | 
			
		||||
                    <ows:Facsimile/>
 | 
			
		||||
                </ows:Phone>
 | 
			
		||||
                <ows:Address>
 | 
			
		||||
                    <ows:DeliveryPoint/>
 | 
			
		||||
                    <ows:City/>
 | 
			
		||||
                    <ows:AdministrativeArea/>
 | 
			
		||||
                    <ows:PostalCode/>
 | 
			
		||||
                    <ows:Country/>
 | 
			
		||||
                    <ows:ElectronicMailAddress/>
 | 
			
		||||
                </ows:Address>
 | 
			
		||||
            </ows:ContactInfo>
 | 
			
		||||
        </ows:ServiceContact>
 | 
			
		||||
    </ows:ServiceProvider>
 | 
			
		||||
    <!-- commented because of fake urls
 | 
			
		||||
    <ows:OperationsMetadata>
 | 
			
		||||
        <ows:Operation name="GetCapabilities">
 | 
			
		||||
            <ows:DCP>
 | 
			
		||||
                <ows:HTTP>
 | 
			
		||||
                    <ows:Get xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                    <ows:Post xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                </ows:HTTP>
 | 
			
		||||
            </ows:DCP>
 | 
			
		||||
            <ows:Parameter name="AcceptVersions">
 | 
			
		||||
                <ows:Value>1.1.0</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Parameter name="AcceptFormats">
 | 
			
		||||
                <ows:Value>text/xml</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Parameter name="Sections">
 | 
			
		||||
                <ows:Value>ServiceIdentification</ows:Value>
 | 
			
		||||
                <ows:Value>ServiceProvider</ows:Value>
 | 
			
		||||
                <ows:Value>OperationsMetadata</ows:Value>
 | 
			
		||||
                <ows:Value>FeatureTypeList</ows:Value>
 | 
			
		||||
                <ows:Value>Filter_Capabilities</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
        </ows:Operation>
 | 
			
		||||
        <ows:Operation name="DescribeFeatureType">
 | 
			
		||||
            <ows:DCP>
 | 
			
		||||
                <ows:HTTP>
 | 
			
		||||
                    <ows:Get xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                    <ows:Post xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                </ows:HTTP>
 | 
			
		||||
            </ows:DCP>
 | 
			
		||||
            <ows:Parameter name="outputFormat">
 | 
			
		||||
                <ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
        </ows:Operation>
 | 
			
		||||
        <ows:Operation name="GetFeature">
 | 
			
		||||
            <ows:DCP>
 | 
			
		||||
                <ows:HTTP>
 | 
			
		||||
                    <ows:Get xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                    <ows:Post xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                </ows:HTTP>
 | 
			
		||||
            </ows:DCP>
 | 
			
		||||
            <ows:Parameter name="resultType">
 | 
			
		||||
                <ows:Value>results</ows:Value>
 | 
			
		||||
                <ows:Value>hits</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Parameter name="outputFormat">
 | 
			
		||||
                <ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>
 | 
			
		||||
                <ows:Value>GML2</ows:Value>
 | 
			
		||||
                <ows:Value>KML</ows:Value>
 | 
			
		||||
                <ows:Value>SHAPE-ZIP</ows:Value>
 | 
			
		||||
                <ows:Value>application/gml+xml; version=3.2</ows:Value>
 | 
			
		||||
                <ows:Value>application/json</ows:Value>
 | 
			
		||||
                <ows:Value>application/vnd.google-earth.kml xml</ows:Value>
 | 
			
		||||
                <ows:Value>application/vnd.google-earth.kml+xml</ows:Value>
 | 
			
		||||
                <ows:Value>csv</ows:Value>
 | 
			
		||||
                <ows:Value>gml3</ows:Value>
 | 
			
		||||
                <ows:Value>gml32</ows:Value>
 | 
			
		||||
                <ows:Value>json</ows:Value>
 | 
			
		||||
                <ows:Value>text/javascript</ows:Value>
 | 
			
		||||
                <ows:Value>text/xml; subtype=gml/2.1.2</ows:Value>
 | 
			
		||||
                <ows:Value>text/xml; subtype=gml/3.2</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Constraint name="LocalTraverseXLinkScope">
 | 
			
		||||
                <ows:Value>2</ows:Value>
 | 
			
		||||
            </ows:Constraint>
 | 
			
		||||
        </ows:Operation>
 | 
			
		||||
        <ows:Operation name="GetGmlObject">
 | 
			
		||||
            <ows:DCP>
 | 
			
		||||
                <ows:HTTP>
 | 
			
		||||
                    <ows:Get xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                    <ows:Post xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                </ows:HTTP>
 | 
			
		||||
            </ows:DCP>
 | 
			
		||||
        </ows:Operation>
 | 
			
		||||
        <ows:Operation name="Transaction">
 | 
			
		||||
            <ows:DCP>
 | 
			
		||||
                <ows:HTTP>
 | 
			
		||||
                    <ows:Get xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                    <ows:Post xlink:href="http://localhost:8600/geoserver/ws1/wfs"/>
 | 
			
		||||
                </ows:HTTP>
 | 
			
		||||
            </ows:DCP>
 | 
			
		||||
            <ows:Parameter name="inputFormat">
 | 
			
		||||
                <ows:Value>text/xml; subtype=gml/3.1.1</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Parameter name="idgen">
 | 
			
		||||
                <ows:Value>GenerateNew</ows:Value>
 | 
			
		||||
                <ows:Value>UseExisting</ows:Value>
 | 
			
		||||
                <ows:Value>ReplaceDuplicate</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
            <ows:Parameter name="releaseAction">
 | 
			
		||||
                <ows:Value>ALL</ows:Value>
 | 
			
		||||
                <ows:Value>SOME</ows:Value>
 | 
			
		||||
            </ows:Parameter>
 | 
			
		||||
        </ows:Operation>
 | 
			
		||||
    </ows:OperationsMetadata-->
 | 
			
		||||
    <FeatureTypeList>
 | 
			
		||||
        <Operations>
 | 
			
		||||
            <Operation>Query</Operation>
 | 
			
		||||
            <Operation>Insert</Operation>
 | 
			
		||||
            <Operation>Update</Operation>
 | 
			
		||||
            <Operation>Delete</Operation>
 | 
			
		||||
        </Operations>
 | 
			
		||||
        <FeatureType xmlns:ws1="ws1">
 | 
			
		||||
            <Name>ws1:polygons</Name>
 | 
			
		||||
            <Title>polygons</Title>
 | 
			
		||||
            <Abstract/>
 | 
			
		||||
            <ows:Keywords>
 | 
			
		||||
                <ows:Keyword>features</ows:Keyword>
 | 
			
		||||
                <ows:Keyword>polygons</ows:Keyword>
 | 
			
		||||
            </ows:Keywords>
 | 
			
		||||
            <DefaultSRS>urn:x-ogc:def:crs:EPSG:4326</DefaultSRS>
 | 
			
		||||
            <ows:WGS84BoundingBox>
 | 
			
		||||
                <ows:LowerCorner>-180.0 -90.0</ows:LowerCorner>
 | 
			
		||||
                <ows:UpperCorner>180.0 90.0</ows:UpperCorner>
 | 
			
		||||
            </ows:WGS84BoundingBox>
 | 
			
		||||
        </FeatureType>
 | 
			
		||||
    </FeatureTypeList>
 | 
			
		||||
    <ogc:Filter_Capabilities>
 | 
			
		||||
        <ogc:Spatial_Capabilities>
 | 
			
		||||
            <ogc:GeometryOperands>
 | 
			
		||||
                <ogc:GeometryOperand>gml:Envelope</ogc:GeometryOperand>
 | 
			
		||||
                <ogc:GeometryOperand>gml:Point</ogc:GeometryOperand>
 | 
			
		||||
                <ogc:GeometryOperand>gml:LineString</ogc:GeometryOperand>
 | 
			
		||||
                <ogc:GeometryOperand>gml:Polygon</ogc:GeometryOperand>
 | 
			
		||||
            </ogc:GeometryOperands>
 | 
			
		||||
            <ogc:SpatialOperators>
 | 
			
		||||
                <ogc:SpatialOperator name="Disjoint"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Equals"/>
 | 
			
		||||
                <ogc:SpatialOperator name="DWithin"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Beyond"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Intersects"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Touches"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Crosses"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Within"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Contains"/>
 | 
			
		||||
                <ogc:SpatialOperator name="Overlaps"/>
 | 
			
		||||
                <ogc:SpatialOperator name="BBOX"/>
 | 
			
		||||
            </ogc:SpatialOperators>
 | 
			
		||||
        </ogc:Spatial_Capabilities>
 | 
			
		||||
        <ogc:Scalar_Capabilities>
 | 
			
		||||
            <ogc:LogicalOperators/>
 | 
			
		||||
            <ogc:ComparisonOperators>
 | 
			
		||||
                <ogc:ComparisonOperator>LessThan</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>GreaterThan</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>LessThanEqualTo</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>GreaterThanEqualTo</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>EqualTo</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>NotEqualTo</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>Like</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>Between</ogc:ComparisonOperator>
 | 
			
		||||
                <ogc:ComparisonOperator>NullCheck</ogc:ComparisonOperator>
 | 
			
		||||
            </ogc:ComparisonOperators>
 | 
			
		||||
            <ogc:ArithmeticOperators>
 | 
			
		||||
                <ogc:SimpleArithmetic/>
 | 
			
		||||
                <ogc:Functions>
 | 
			
		||||
                    <ogc:FunctionNames>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">abs</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">abs_2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">abs_3</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">abs_4</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">acos</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">AddCoverages</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">Affine</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">Aggregate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">area</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">area2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">AreaGrid</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">asin</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">atan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">atan2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">attributeCount</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">BandMerge</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">BandSelect</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-6">BarnesSurface</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">between</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">boundary</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">boundaryDimension</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">boundedBy</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Bounds</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">buffer</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">BufferFeatureCollection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">bufferWithSegments</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="7">Categorize</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">ceil</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">centroid</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">classify</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">ClassifyByRange</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">Clip</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">CollectGeometries</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Average</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Bounds</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Count</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Max</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Median</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Min</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Nearest</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Sum</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Collection_Unique</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">Concatenate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">contains</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">Contour</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">contrast</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">convert</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">convexHull</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">ConvolveCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">cos</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">Count</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">CoverageClassStats</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">CropCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">crosses</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">darken</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">dateDifference</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">dateFormat</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">dateParse</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">densify</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">desaturate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">difference</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">dimension</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">disjoint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">disjoint3D</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">distance</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">distance3D</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">double2bool</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">endAngle</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">endPoint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">env</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">envelope</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">EqualArea</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">EqualInterval</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">equalsExact</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">equalsExactTolerance</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">equalTo</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">exp</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">exteriorRing</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">Feature</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">FeatureClassStats</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">floor</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">geometry</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">geometryType</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">geomFromWKT</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">geomLength</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-3">GeorectifyCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">GetFullCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">getGeometryN</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">getX</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">getY</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">getz</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">grayscale</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">greaterEqualThan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">greaterThan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-3">Grid</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-5">Heatmap</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">hsl</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">id</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">IEEEremainder</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">if_then_else</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">Import</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">in</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="11">in10</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">in2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="4">in3</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="5">in4</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="6">in5</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="7">in6</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="8">in7</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="9">in8</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="10">in9</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">inArray</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">InclusionFeatureCollection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">int2bbool</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">int2ddouble</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">interiorPoint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">interiorRingN</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-5">Interpolate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">intersection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">IntersectionFeatureCollection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">intersects</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">intersects3D</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isClosed</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">isCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isEmpty</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isInstanceOf</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">isLike</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isNull</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">isometric</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isRing</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isSimple</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">isValid</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">isWithinDistance</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">isWithinDistance3D</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">Jenks</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">Jiffle</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">jsonPointer</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">labelPoint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">lapply</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">length</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">lessEqualThan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">lessThan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">lighten</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">list</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">listMultiply</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">litem</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">literate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">log</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="4">LRSGeocode</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-4">LRSMeasure</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="5">LRSSegment</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">max</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">max_2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">max_3</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">max_4</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">min</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">min_2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">min_3</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">min_4</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">mincircle</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">minimumdiameter</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">minrectangle</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">mix</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">modulo</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">MultiplyCoverages</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">Nearest</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">NormalizeCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">not</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">notEqualTo</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">numberFormat</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="5">numberFormat2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">numGeometries</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">numInteriorRing</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">numPoints</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">octagonalenvelope</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">offset</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">overlaps</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">PagedUnique</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">parameter</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">parseBoolean</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">parseDouble</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">parseInt</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">parseLong</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">pgNearest</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">pi</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">PointBuffers</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">pointN</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-7">PointStacker</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">PolygonExtraction</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">polygonize</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">PolyLabeller</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">pow</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">property</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">PropertyExists</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">Quantile</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">Query</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="0">random</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">RangeLookup</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">RasterAsPointCollection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">RasterZonalStatistics</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-6">RasterZonalStatistics2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="5">Recode</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">RectangularClip</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">relate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">relatePattern</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">reproject</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">ReprojectGeometry</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-3">rescaleToPixels</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">rint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">round</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">round_2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">roundDouble</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">saturate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-5">ScaleCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">setCRS</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">shade</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">simplify</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">sin</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">size</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">Snap</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">spin</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">splitPolygon</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">sqrt</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">StandardDeviation</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">startAngle</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">startPoint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">StoreCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="4">strAbbreviate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strCapitalize</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strConcat</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strDefaultIfBlank</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strEndsWith</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strEqualsIgnoreCase</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strIndexOf</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="4">stringTemplate</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strLastIndexOf</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strLength</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strMatches</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">strPosition</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="4">strReplace</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strStartsWith</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strStripAccents</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">strSubstring</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">strSubstringStart</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strToLowerCase</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strToUpperCase</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">strTrim</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">strTrim2</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-1">strURLEncode</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">StyleCoverage</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">symDifference</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">tan</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">tint</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">toDegrees</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">toRadians</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">touches</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">toWKT</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">Transform</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">TransparencyFill</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-2">union</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">UnionFeatureCollection</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">Unique</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">UniqueInterval</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="-4">VectorToRaster</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="3">VectorZonalStatistics</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="1">vertices</ogc:FunctionName>
 | 
			
		||||
                        <ogc:FunctionName nArgs="2">within</ogc:FunctionName>
 | 
			
		||||
                    </ogc:FunctionNames>
 | 
			
		||||
                </ogc:Functions>
 | 
			
		||||
            </ogc:ArithmeticOperators>
 | 
			
		||||
        </ogc:Scalar_Capabilities>
 | 
			
		||||
        <ogc:Id_Capabilities>
 | 
			
		||||
            <ogc:FID/>
 | 
			
		||||
            <ogc:EID/>
 | 
			
		||||
        </ogc:Id_Capabilities>
 | 
			
		||||
    </ogc:Filter_Capabilities>
 | 
			
		||||
</wfs:WFS_Capabilities>
 | 
			
		||||
							
								
								
									
										8
									
								
								tests/testdata/provider/wfst-1-1/transaction_add_features_polygons_empty.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								tests/testdata/provider/wfst-1-1/transaction_add_features_polygons_empty.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
<Transaction xmlns="http://www.opengis.net_wfs"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org_2001_XMLSchema-instance"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net_gml"
 | 
			
		||||
    xmlns:ws1="ws1" xsi:schemaLocation="ws1 http://localhost:8600_geoserver_ws1_wfs?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=ws1:polygons" version="1.1.0" service="WFS">
 | 
			
		||||
    <Insert xmlns="http:__www.opengis.net_wfs">
 | 
			
		||||
        <polygons xmlns="ws1"/>
 | 
			
		||||
    </Insert>
 | 
			
		||||
</Transaction>
 | 
			
		||||
							
								
								
									
										19
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_empty.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_empty.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema"
 | 
			
		||||
    xmlns:wfs="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net/gml"
 | 
			
		||||
    xmlns:ogc="http://www.opengis.net/ogc"
 | 
			
		||||
    xmlns:ows="http://www.opengis.net/ows"
 | 
			
		||||
    xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8600/geoserver/schemas/wfs/1.1.0/wfs.xsd">
 | 
			
		||||
    <wfs:TransactionSummary>
 | 
			
		||||
        <wfs:totalInserted>0</wfs:totalInserted>
 | 
			
		||||
        <wfs:totalUpdated>0</wfs:totalUpdated>
 | 
			
		||||
        <wfs:totalDeleted>0</wfs:totalDeleted>
 | 
			
		||||
    </wfs:TransactionSummary>
 | 
			
		||||
    <wfs:InsertResults>
 | 
			
		||||
        <wfs:Feature>
 | 
			
		||||
            <ogc:FeatureId fid="none"/>
 | 
			
		||||
        </wfs:Feature>
 | 
			
		||||
    </wfs:InsertResults>
 | 
			
		||||
</wfs:TransactionResponse>
 | 
			
		||||
							
								
								
									
										20
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_added.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_added.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema"
 | 
			
		||||
    xmlns:wfs="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net/gml"
 | 
			
		||||
    xmlns:ogc="http://www.opengis.net/ogc"
 | 
			
		||||
    xmlns:ows="http://www.opengis.net/ows"
 | 
			
		||||
    xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8600/geoserver/schemas/wfs/1.1.0/wfs.xsd">
 | 
			
		||||
    <wfs:TransactionSummary>
 | 
			
		||||
        <wfs:totalInserted>1</wfs:totalInserted>
 | 
			
		||||
        <wfs:totalUpdated>0</wfs:totalUpdated>
 | 
			
		||||
        <wfs:totalDeleted>0</wfs:totalDeleted>
 | 
			
		||||
    </wfs:TransactionSummary>
 | 
			
		||||
    <wfs:TransactionResults/>
 | 
			
		||||
    <wfs:InsertResults>
 | 
			
		||||
        <wfs:Feature>
 | 
			
		||||
            <ogc:FeatureId fid="123"/>
 | 
			
		||||
        </wfs:Feature>
 | 
			
		||||
    </wfs:InsertResults>
 | 
			
		||||
</wfs:TransactionResponse>
 | 
			
		||||
							
								
								
									
										14
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_changed.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_changed.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema"
 | 
			
		||||
    xmlns:wfs="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net/gml"
 | 
			
		||||
    xmlns:ogc="http://www.opengis.net/ogc"
 | 
			
		||||
    xmlns:ows="http://www.opengis.net/ows"
 | 
			
		||||
    xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8600/geoserver/schemas/wfs/1.1.0/wfs.xsd">
 | 
			
		||||
    <wfs:TransactionSummary>
 | 
			
		||||
        <wfs:totalInserted>0</wfs:totalInserted>
 | 
			
		||||
        <wfs:totalUpdated>1</wfs:totalUpdated>
 | 
			
		||||
        <wfs:totalDeleted>0</wfs:totalDeleted>
 | 
			
		||||
    </wfs:TransactionSummary>
 | 
			
		||||
</wfs:TransactionResponse>
 | 
			
		||||
							
								
								
									
										14
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_deleted.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/testdata/provider/wfst-1-1/transaction_response_feature_deleted.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema"
 | 
			
		||||
    xmlns:wfs="http://www.opengis.net/wfs"
 | 
			
		||||
    xmlns:gml="http://www.opengis.net/gml"
 | 
			
		||||
    xmlns:ogc="http://www.opengis.net/ogc"
 | 
			
		||||
    xmlns:ows="http://www.opengis.net/ows"
 | 
			
		||||
    xmlns:xlink="http://www.w3.org/1999/xlink"
 | 
			
		||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8600/geoserver/schemas/wfs/1.1.0/wfs.xsd">
 | 
			
		||||
    <wfs:TransactionSummary>
 | 
			
		||||
        <wfs:totalInserted>0</wfs:totalInserted>
 | 
			
		||||
        <wfs:totalUpdated>0</wfs:totalUpdated>
 | 
			
		||||
        <wfs:totalDeleted>1</wfs:totalDeleted>
 | 
			
		||||
    </wfs:TransactionSummary>
 | 
			
		||||
</wfs:TransactionResponse>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user