Merge pull request #39368 from elpaso/wfs-t-1.1

Fix WFS-T 1.1.0 support
This commit is contained in:
Alessandro Pasotti 2020-10-17 21:45:58 +02:00 committed by GitHub
commit a0711d710d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 924 additions and 71 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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 )
{

View File

@ -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

View File

@ -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 );
}

View File

@ -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" ) );

View File

@ -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

View File

@ -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,

View File

@ -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; }

View File

@ -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" ) );

View File

@ -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

View File

@ -27,6 +27,7 @@ QgsWFSSharedData::QgsWFSSharedData( const QString &uri )
, mURI( uri )
{
mHideProgressDialog = mURI.hideDownloadProgressDialog();
mServerPrefersCoordinatesForTransactions_1_1 = mURI.preferCoordinatesForWfst11();
}
QgsWFSSharedData::~QgsWFSSharedData()

View File

@ -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;

View File

@ -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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter a number to limit the maximum number of features retrieved per feature request. If let to empty, no limit is set.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter a number to limit the maximum number of features retrieved per feature request. If let to empty, no limit is set.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="cbxWfsUseGml2EncodingForTransactions">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This might be necessary on some &lt;span style=&quot; font-weight:600;&quot;&gt;broken&lt;/span&gt; ESRI map servers when using WFS-T 1.1.0.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Invert axis orientation</string>
<string>Use GML2 encoding for transactions</string>
</property>
</widget>
</item>

View File

@ -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&amp;VERSION=1.0.0&amp;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&amp;VERSION=1.0.0&amp;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&amp;VERSION=1.0.0&amp;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&amp;VERSION=1.0.0&amp;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&amp;VERSION=1.0.0&amp;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()

View File

@ -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()

View 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>

View 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>

View 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&amp;REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=ws1:polygons" version="1.1.0" service="WFS">
<Insert xmlns="http:__www.opengis.net_wfs">
<polygons xmlns="ws1"/>
</Insert>
</Transaction>

View 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>

View 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>

View 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>

View 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>