Skip to content

Commit c0117df

Browse files
committedOct 12, 2017
[Server][WFS] Update GetCapabilities 1.1.0
1 parent 1b9d8ee commit c0117df

File tree

3 files changed

+341
-131
lines changed

3 files changed

+341
-131
lines changed
 

‎src/server/services/wfs/qgswfsgetcapabilities.cpp

Lines changed: 326 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,14 @@ namespace QgsWfs
6868
wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
6969
doc.appendChild( wfsCapabilitiesElement );
7070

71-
//wfs:Service
72-
wfsCapabilitiesElement.appendChild( getServiceElement( doc, project ) );
71+
//ows:ServiceIdentification
72+
wfsCapabilitiesElement.appendChild( getServiceIdentificationElement( doc, project ) );
7373

74-
//wfs:Capability
75-
wfsCapabilitiesElement.appendChild( getCapabilityElement( doc, project, request ) );
74+
//ows:ServiceProvider
75+
wfsCapabilitiesElement.appendChild( getServiceProviderElement( doc, project ) );
76+
77+
//wfs:OperationsMetadata
78+
wfsCapabilitiesElement.appendChild( getOperationsMetadataElement( doc, project, request ) );
7679

7780
//wfs:FeatureTypeList
7881
wfsCapabilitiesElement.appendChild( getFeatureTypeListElement( doc, serverIface, project ) );
@@ -85,43 +88,66 @@ namespace QgsWfs
8588
wfsCapabilitiesElement.appendChild( filterCapabilitiesElement );
8689
QDomElement spatialCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Spatial_Capabilities" )/*ogc:Spatial_Capabilities*/ );
8790
filterCapabilitiesElement.appendChild( spatialCapabilitiesElement );
88-
QDomElement spatialOperatorsElement = doc.createElement( QStringLiteral( "ogc:Spatial_Operators" )/*ogc:Spatial_Operators*/ );
89-
spatialCapabilitiesElement.appendChild( spatialOperatorsElement );
90-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:BBOX" )/*ogc:BBOX*/ ) );
91-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Disjoint" )/*ogc:Disjoint*/ ) );
92-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Intersect" )/*ogc:Intersects*/ ) );
93-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Touches" )/*ogc:Touches*/ ) );
94-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Crosses" )/*ogc:Crosses*/ ) );
95-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Contains" )/*ogc:Contains*/ ) );
96-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Overlaps" )/*ogc:Overlaps*/ ) );
97-
spatialOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Within" )/*ogc:Within*/ ) );
91+
//GeometryOperands
92+
QStringList geometryOperands;
93+
geometryOperands << QStringLiteral( "gml:Point" ) << QStringLiteral( "gml:LineString" ) << QStringLiteral( "gml:Polygon" )
94+
<< QStringLiteral( "gml:Envelope" );
95+
QDomElement geometryOperandsElem = doc.createElement( QStringLiteral( "ogc:GeometryOperands" ) );
96+
for ( const QString &geometryOperand : geometryOperands )
97+
{
98+
QDomElement geometryOperandElem = doc.createElement( QStringLiteral( "ogc:GeometryOperand" ) );
99+
QDomText geometryOperandText = doc.createTextNode( geometryOperand );
100+
geometryOperandElem.appendChild( geometryOperandText );
101+
geometryOperandsElem.appendChild( geometryOperandElem );
102+
}
103+
spatialCapabilitiesElement.appendChild( geometryOperandsElem );
104+
//SpatialOperators
105+
QStringList spatialOperators;
106+
spatialOperators << QStringLiteral( "Equals" ) << QStringLiteral( "Disjoint" ) << QStringLiteral( "Touches" )
107+
<< QStringLiteral( "Within" ) << QStringLiteral( "Overlaps" ) << QStringLiteral( "Crosses" )
108+
<< QStringLiteral( "Intersects" ) << QStringLiteral( "Contains" ) << QStringLiteral( "DWithin" )
109+
<< QStringLiteral( "Beyond" ) << QStringLiteral( "BBOX" );
110+
QDomElement spatialOperatorsElem = doc.createElement( QStringLiteral( "ogc:SpatialOperators" ) );
111+
for ( const QString &spatialOperator : spatialOperators )
112+
{
113+
QDomElement spatialOperatorElem = doc.createElement( QStringLiteral( "ogc:SpatialOperator" ) );
114+
QDomText spatialOperatorText = doc.createTextNode( spatialOperator );
115+
spatialOperatorElem.appendChild( spatialOperatorText );
116+
spatialOperatorsElem.appendChild( spatialOperatorElem );
117+
}
118+
spatialCapabilitiesElement.appendChild( spatialOperatorsElem );
98119
QDomElement scalarCapabilitiesElement = doc.createElement( QStringLiteral( "ogc:Scalar_Capabilities" )/*ogc:Scalar_Capabilities*/ );
99120
filterCapabilitiesElement.appendChild( scalarCapabilitiesElement );
100-
QDomElement comparisonOperatorsElement = doc.createElement( QStringLiteral( "ogc:Comparison_Operators" )/*ogc:Comparison_Operators*/ );
101-
scalarCapabilitiesElement.appendChild( comparisonOperatorsElement );
102-
comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Simple_Comparisons" )/*ogc:Simple_Comparisons*/ ) );
103-
comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Between" )/*ogc:Between*/ ) );
104-
comparisonOperatorsElement.appendChild( doc.createElement( QStringLiteral( "ogc:Like" )/*ogc:Like*/ ) );
121+
QDomElement logicalOperatorsElement = doc.createElement( QStringLiteral( "ogc:LogicalOperators" ) );
122+
scalarCapabilitiesElement.appendChild( logicalOperatorsElement );
123+
// ComparisonOperators
124+
QStringList comparisonOperators;
125+
comparisonOperators << QStringLiteral( "LessThan" ) << QStringLiteral( "GreaterThan" )
126+
<< QStringLiteral( "LessThanEqualTo" ) << QStringLiteral( "GreaterThanEqualTo" )
127+
<< QStringLiteral( "EqualTo" ) << QStringLiteral( "Like" ) << QStringLiteral( "Between" );
128+
QDomElement comparisonOperatorsElem = doc.createElement( QStringLiteral( "ogc:ComparisonOperators" ) );
129+
for ( const QString &comparisonOperator : comparisonOperators )
130+
{
131+
QDomElement comparisonOperatorElem = doc.createElement( QStringLiteral( "ogc:ComparisonOperator" ) );
132+
QDomText comparisonOperatorText = doc.createTextNode( comparisonOperator );
133+
comparisonOperatorElem.appendChild( comparisonOperatorText );
134+
comparisonOperatorsElem.appendChild( comparisonOperatorElem );
135+
}
136+
scalarCapabilitiesElement.appendChild( comparisonOperatorsElem );
105137

106138
return doc;
107139

108140
}
109141

110-
QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project )
142+
QDomElement getServiceIdentificationElement( QDomDocument &doc, const QgsProject *project )
111143
{
112144
//Service element
113-
QDomElement serviceElem = doc.createElement( QStringLiteral( "Service" ) );
114-
115-
//Service name
116-
QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) );
117-
QDomText nameText = doc.createTextNode( "WFS" );
118-
nameElem.appendChild( nameText );
119-
serviceElem.appendChild( nameElem );
145+
QDomElement serviceElem = doc.createElement( QStringLiteral( "ows:ServiceIdentification" ) );
120146

121147
QString title = QgsServerProjectUtils::owsServiceTitle( *project );
122148
if ( !title.isEmpty() )
123149
{
124-
QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) );
150+
QDomElement titleElem = doc.createElement( QStringLiteral( "ows:Title" ) );
125151
QDomText titleText = doc.createTextNode( title );
126152
titleElem.appendChild( titleText );
127153
serviceElem.appendChild( titleElem );
@@ -130,7 +156,7 @@ namespace QgsWfs
130156
QString abstract = QgsServerProjectUtils::owsServiceAbstract( *project );
131157
if ( !abstract.isEmpty() )
132158
{
133-
QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) );
159+
QDomElement abstractElem = doc.createElement( QStringLiteral( "ows:Abstract" ) );
134160
QDomText abstractText = doc.createCDATASection( abstract );
135161
abstractElem.appendChild( abstractText );
136162
serviceElem.appendChild( abstractElem );
@@ -139,109 +165,240 @@ namespace QgsWfs
139165
QStringList keywords = QgsServerProjectUtils::owsServiceKeywords( *project );
140166
if ( !keywords.isEmpty() && !keywords.join( QStringLiteral( ", " ) ).isEmpty() )
141167
{
142-
QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
143-
QDomText keywordsText = doc.createTextNode( keywords.join( QStringLiteral( ", " ) ) );
144-
keywordsElem.appendChild( keywordsText );
168+
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
169+
for ( QString keyword : keywords )
170+
{
171+
if ( !keyword.isEmpty() )
172+
{
173+
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
174+
QDomText keywordText = doc.createTextNode( keyword );
175+
keywordElem.appendChild( keywordText );
176+
keywordsElem.appendChild( keywordElem );
177+
}
178+
}
145179
serviceElem.appendChild( keywordsElem );
146180
}
147181

148-
QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "OnlineResource" ) );
149-
QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project );
150-
if ( !onlineResource.isEmpty() )
151-
{
152-
QDomText onlineResourceText = doc.createTextNode( onlineResource );
153-
onlineResourceElem.appendChild( onlineResourceText );
154-
}
155-
serviceElem.appendChild( onlineResourceElem );
182+
//Service type
183+
QDomElement serviceTypeElem = doc.createElement( QStringLiteral( "ows:ServiceType" ) );
184+
QDomText serviceTypeText = doc.createTextNode( "WFS" );
185+
serviceTypeElem.appendChild( serviceTypeText );
186+
serviceElem.appendChild( serviceTypeElem );
187+
188+
//Service type version
189+
QDomElement serviceTypeVersionElem = doc.createElement( QStringLiteral( "ows:ServiceTypeVersion" ) );
190+
QDomText serviceTypeVersionText = doc.createTextNode( "1.1.0" );
191+
serviceTypeElem.appendChild( serviceTypeText );
192+
serviceElem.appendChild( serviceTypeElem );
156193

194+
QDomElement feesElem = doc.createElement( QStringLiteral( "ows:Fees" ) );
195+
QDomText feesText = doc.createTextNode( "None" );
157196
QString fees = QgsServerProjectUtils::owsServiceFees( *project );
158197
if ( !fees.isEmpty() )
159198
{
160-
QDomElement feesElem = doc.createElement( QStringLiteral( "Fees" ) );
161-
QDomText feesText = doc.createTextNode( fees );
162-
feesElem.appendChild( feesText );
163-
serviceElem.appendChild( feesElem );
199+
feesText = doc.createTextNode( fees );
164200
}
201+
feesElem.appendChild( feesText );
202+
serviceElem.appendChild( feesElem );
165203

204+
QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "ows:AccessConstraints" ) );
166205
QString accessConstraints = QgsServerProjectUtils::owsServiceAccessConstraints( *project );
206+
QDomText accessConstraintsText = doc.createTextNode( "None" );
167207
if ( !accessConstraints.isEmpty() )
168208
{
169-
QDomElement accessConstraintsElem = doc.createElement( QStringLiteral( "AccessConstraints" ) );
170-
QDomText accessConstraintsText = doc.createTextNode( accessConstraints );
171-
accessConstraintsElem.appendChild( accessConstraintsText );
172-
serviceElem.appendChild( accessConstraintsElem );
209+
accessConstraintsText = doc.createTextNode( accessConstraints );
173210
}
211+
accessConstraintsElem.appendChild( accessConstraintsText );
212+
serviceElem.appendChild( accessConstraintsElem );
174213

175214
return serviceElem;
176215

177216
}
178217

179-
QDomElement getCapabilityElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request )
218+
QDomElement getServiceProviderElement( QDomDocument &doc, const QgsProject *project )
180219
{
181-
//wfs:Capability element
182-
QDomElement capabilityElement = doc.createElement( QStringLiteral( "Capability" )/*wfs:Capability*/ );
220+
//Service element
221+
QDomElement serviceElem = doc.createElement( QStringLiteral( "ows:ServiceProvider" ) );
222+
223+
//ProviderName
224+
QString contactOrganization = QgsServerProjectUtils::owsServiceContactOrganization( *project );
225+
if ( !contactOrganization.isEmpty() )
226+
{
227+
QDomElement providerNameElem = doc.createElement( QStringLiteral( "ows:ProviderName" ) );
228+
QDomText providerNameText = doc.createTextNode( contactOrganization );
229+
providerNameElem.appendChild( providerNameText );
230+
serviceElem.appendChild( providerNameElem );
231+
}
232+
233+
QString contactPerson = QgsServerProjectUtils::owsServiceContactPerson( *project );
234+
QString contactPosition = QgsServerProjectUtils::owsServiceContactPosition( *project );
235+
if ( !contactPerson.isEmpty() ||
236+
!contactPosition.isEmpty() )
237+
{
238+
//Contact information
239+
QDomElement serviceContactElem = doc.createElement( QStringLiteral( "ows:ServiceContact" ) );
240+
241+
if ( !contactPerson.isEmpty() )
242+
{
243+
QDomElement individualNameElem = doc.createElement( QStringLiteral( "ows:IndividualName" ) );
244+
QDomText individualNameText = doc.createTextNode( contactPerson );
245+
individualNameElem.appendChild( individualNameText );
246+
serviceContactElem.appendChild( individualNameElem );
247+
}
248+
249+
if ( !contactPosition.isEmpty() )
250+
{
251+
QDomElement positionNameElem = doc.createElement( QStringLiteral( "ows:PositionName" ) );
252+
QDomText positionNameText = doc.createTextNode( contactPosition );
253+
positionNameElem.appendChild( positionNameText );
254+
serviceContactElem.appendChild( positionNameElem );
255+
}
183256

184-
//wfs:Request element
185-
QDomElement requestElement = doc.createElement( QStringLiteral( "Request" )/*wfs:Request*/ );
186-
capabilityElement.appendChild( requestElement );
187-
//wfs:GetCapabilities
188-
QDomElement getCapabilitiesElement = doc.createElement( QStringLiteral( "GetCapabilities" )/*wfs:GetCapabilities*/ );
189-
requestElement.appendChild( getCapabilitiesElement );
257+
QString contactMail = QgsServerProjectUtils::owsServiceContactMail( *project );
258+
QString contactPhone = QgsServerProjectUtils::owsServiceContactPhone( *project );
259+
QString onlineResource = QgsServerProjectUtils::owsServiceOnlineResource( *project );
260+
if ( !contactMail.isEmpty() ||
261+
!contactPhone.isEmpty() ||
262+
!onlineResource.isEmpty() )
263+
{
264+
//Contact information
265+
QDomElement contactInfoElem = doc.createElement( QStringLiteral( "ows:ContactInfo" ) );
190266

191-
QDomElement dcpTypeElement = doc.createElement( QStringLiteral( "DCPType" )/*wfs:DCPType*/ );
192-
getCapabilitiesElement.appendChild( dcpTypeElement );
193-
QDomElement httpElement = doc.createElement( QStringLiteral( "HTTP" )/*wfs:HTTP*/ );
194-
dcpTypeElement.appendChild( httpElement );
267+
if ( !contactPhone.isEmpty() )
268+
{
269+
QDomElement phoneElem = doc.createElement( QStringLiteral( "ows:Phone" ) );
270+
QDomElement voiceElem = doc.createElement( QStringLiteral( "ows:Voice" ) );
271+
QDomText voiceText = doc.createTextNode( contactPhone );
272+
voiceElem.appendChild( voiceText );
273+
phoneElem.appendChild( voiceElem );
274+
contactInfoElem.appendChild( phoneElem );
275+
}
276+
277+
if ( !contactMail.isEmpty() )
278+
{
279+
QDomElement addressElem = doc.createElement( QStringLiteral( "ows:Address" ) );
280+
QDomElement mailElem = doc.createElement( QStringLiteral( "ows:ElectronicMailAddress" ) );
281+
QDomText mailText = doc.createTextNode( contactMail );
282+
mailElem.appendChild( mailText );
283+
addressElem.appendChild( mailElem );
284+
contactInfoElem.appendChild( addressElem );
285+
}
286+
287+
if ( !onlineResource.isEmpty() )
288+
{
289+
QDomElement onlineResourceElem = doc.createElement( QStringLiteral( "ows:OnlineResource" ) );
290+
onlineResourceElem.setAttribute( "xlink:href", onlineResource );
291+
contactInfoElem.appendChild( onlineResourceElem );
292+
}
293+
}
294+
295+
QDomElement roleElem = doc.createElement( QStringLiteral( "ows:Role" ) );
296+
QDomText roleText = doc.createTextNode( "PointOfContact" );
297+
roleElem.appendChild( roleText );
298+
serviceContactElem.appendChild( roleElem );
299+
300+
serviceElem.appendChild( serviceContactElem );
301+
}
302+
303+
return serviceElem;
304+
305+
}
306+
307+
QDomElement getParameterElement( QDomDocument &doc, const QString &name, const QStringList &values )
308+
{
309+
QDomElement parameterElement = doc.createElement( QStringLiteral( "ows:Parameter" ) );
310+
parameterElement.setAttribute( QStringLiteral( "name" ), name );
311+
312+
for ( const QString &v : values )
313+
{
314+
QDomElement valueElement = doc.createElement( QStringLiteral( "ows:Value" ) );
315+
QDomText valueText = doc.createTextNode( v );
316+
valueElement.appendChild( valueText );
317+
parameterElement.appendChild( valueElement );
318+
}
319+
320+
return parameterElement;
321+
}
322+
323+
QDomElement getOperationsMetadataElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request )
324+
{
325+
QDomElement oprationsElement = doc.createElement( QStringLiteral( "ows:OperationsMetadata" ) );
195326

196327
//Prepare url
197328
QString hrefString = serviceUrl( request, project );
198329

199-
//only Get supported for the moment
200-
QDomElement getElement = doc.createElement( QStringLiteral( "Get" )/*wfs:Get*/ );
330+
QDomElement operationElement = doc.createElement( QStringLiteral( "ows:Operation" ) );
331+
QDomElement dcpElement = doc.createElement( QStringLiteral( "ows:DCP" ) );
332+
QDomElement httpElement = doc.createElement( QStringLiteral( "ows:HTTP" ) );
333+
QDomElement getElement = doc.createElement( QStringLiteral( "ows:Get" ) );
334+
getElement.setAttribute( QStringLiteral( "xlink:type" ), QStringLiteral( "xlink:simple" ) );
335+
getElement.setAttribute( QStringLiteral( "xlink:href" ), hrefString );
336+
QDomElement postElement = getElement.cloneNode().toElement();
201337
httpElement.appendChild( getElement );
202-
getElement.setAttribute( QStringLiteral( "onlineResource" ), hrefString );
203-
QDomElement getCapabilitiesDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
204-
getCapabilitiesDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
205-
getCapabilitiesElement.appendChild( getCapabilitiesDhcTypePostElement );
206-
207-
//wfs:DescribeFeatureType
208-
QDomElement describeFeatureTypeElement = doc.createElement( QStringLiteral( "DescribeFeatureType" )/*wfs:DescribeFeatureType*/ );
209-
requestElement.appendChild( describeFeatureTypeElement );
210-
QDomElement schemaDescriptionLanguageElement = doc.createElement( QStringLiteral( "SchemaDescriptionLanguage" )/*wfs:SchemaDescriptionLanguage*/ );
211-
describeFeatureTypeElement.appendChild( schemaDescriptionLanguageElement );
212-
QDomElement xmlSchemaElement = doc.createElement( QStringLiteral( "XMLSCHEMA" )/*wfs:XMLSCHEMA*/ );
213-
schemaDescriptionLanguageElement.appendChild( xmlSchemaElement );
214-
QDomElement describeFeatureTypeDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
215-
describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypeElement );
216-
QDomElement describeFeatureTypeDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
217-
describeFeatureTypeDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
218-
describeFeatureTypeElement.appendChild( describeFeatureTypeDhcTypePostElement );
219-
220-
//wfs:GetFeature
221-
QDomElement getFeatureElement = doc.createElement( QStringLiteral( "GetFeature" )/*wfs:GetFeature*/ );
222-
requestElement.appendChild( getFeatureElement );
223-
QDomElement getFeatureFormatElement = doc.createElement( QStringLiteral( "ResultFormat" ) );/*wfs:ResultFormat*/
224-
getFeatureElement.appendChild( getFeatureFormatElement );
225-
QDomElement gmlFormatElement = doc.createElement( QStringLiteral( "GML2" ) );/*wfs:GML2*/
226-
getFeatureFormatElement.appendChild( gmlFormatElement );
227-
QDomElement gml3FormatElement = doc.createElement( QStringLiteral( "GML3" ) );/*wfs:GML3*/
228-
getFeatureFormatElement.appendChild( gml3FormatElement );
229-
QDomElement geojsonFormatElement = doc.createElement( QStringLiteral( "GeoJSON" ) );/*wfs:GeoJSON*/
230-
getFeatureFormatElement.appendChild( geojsonFormatElement );
231-
QDomElement getFeatureDhcTypeGetElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
232-
getFeatureElement.appendChild( getFeatureDhcTypeGetElement );
233-
QDomElement getFeatureDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
234-
getFeatureDhcTypePostElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
235-
getFeatureElement.appendChild( getFeatureDhcTypePostElement );
236-
237-
//wfs:Transaction
238-
QDomElement transactionElement = doc.createElement( QStringLiteral( "Transaction" )/*wfs:Transaction*/ );
239-
requestElement.appendChild( transactionElement );
240-
QDomElement transactionDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
241-
transactionDhcTypeElement.firstChild().firstChild().toElement().setTagName( QStringLiteral( "Post" ) );
242-
transactionElement.appendChild( transactionDhcTypeElement );
243-
244-
return capabilityElement;
338+
httpElement.appendChild( postElement );
339+
dcpElement.appendChild( httpElement );
340+
operationElement.appendChild( dcpElement );
341+
342+
// GetCapabilities
343+
QDomElement getCapabilitiesElement = operationElement.cloneNode().toElement();
344+
getCapabilitiesElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetCapabilities" ) );
345+
// GetCapabilities service
346+
QDomElement serviceParameterElement = getParameterElement( doc, QStringLiteral( "service" ),
347+
QStringList() << QStringLiteral( "WFS" ) );
348+
getCapabilitiesElement.appendChild( serviceParameterElement );
349+
// GetCapabilities AcceptVersions
350+
QDomElement acceptVersionsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptVersions" ),
351+
QStringList() << QStringLiteral( "1.1.0" ) << QStringLiteral( "1.0.0" ) );
352+
getCapabilitiesElement.appendChild( acceptVersionsParameterElement );
353+
// GetCapabilities AcceptFormats
354+
QDomElement acceptFormatsParameterElement = getParameterElement( doc, QStringLiteral( "AcceptFormats" ),
355+
QStringList() << QStringLiteral( "text/xml" ) );
356+
getCapabilitiesElement.appendChild( acceptFormatsParameterElement );
357+
// Add
358+
oprationsElement.appendChild( getCapabilitiesElement );
359+
360+
// DescribeFeatureType
361+
QDomElement describeFeatureTypeElement = operationElement.cloneNode().toElement();
362+
describeFeatureTypeElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "DescribeFeatureType" ) );
363+
// DescribeFeatureType outputFormat
364+
QDomElement dftOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ),
365+
QStringList() << QStringLiteral( "XMLSCHEMA" )
366+
<< QStringLiteral( "text/xml; subtype=gml/2.1.2" )
367+
<< QStringLiteral( "text/xml; subtype=gml/3.1.1" ) );
368+
describeFeatureTypeElement.appendChild( dftOutputFormatParameterElement );
369+
// Add
370+
oprationsElement.appendChild( describeFeatureTypeElement );
371+
372+
// GetFeature
373+
QDomElement getFeatureElement = operationElement.cloneNode().toElement();
374+
getFeatureElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "GetFeature" ) );
375+
// GetFeature outputFormat
376+
QDomElement gfOutputFormatParameterElement = getParameterElement( doc, QStringLiteral( "outputFormat" ),
377+
QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" )
378+
<< QStringLiteral( "text/xml; subtype=gml/3.1.1" )
379+
<< QStringLiteral( "application/vnd.geo+json" ) );
380+
getFeatureElement.appendChild( gfOutputFormatParameterElement );
381+
// GetFeature resultType
382+
QDomElement resultTypeParameterElement = getParameterElement( doc, QStringLiteral( "resultType" ),
383+
QStringList() << QStringLiteral( "results" ) );
384+
getFeatureElement.appendChild( resultTypeParameterElement );
385+
// Add
386+
oprationsElement.appendChild( getFeatureElement );
387+
388+
// Transaction
389+
QDomElement transactionElement = operationElement.cloneNode().toElement();
390+
transactionElement.setAttribute( QStringLiteral( "name" ), QStringLiteral( "Transaction" ) );
391+
// GetFeature inputFormat
392+
QDomElement inputFormatParameterElement = getParameterElement( doc, QStringLiteral( "inputFormat" ),
393+
QStringList() << QStringLiteral( "text/xml; subtype=gml/2.1.2" )
394+
<< QStringLiteral( "text/xml; subtype=gml/3.1.1" )
395+
<< QStringLiteral( "application/vnd.geo+json" ) );
396+
transactionElement.appendChild( inputFormatParameterElement );
397+
// Add
398+
oprationsElement.appendChild( transactionElement );
399+
400+
return oprationsElement;
401+
245402
}
246403

247404
QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project )
@@ -310,25 +467,75 @@ namespace QgsWfs
310467
QString keywords = layer->keywordList();
311468
if ( !keywords.isEmpty() )
312469
{
313-
QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) );
314-
QDomText keywordsText = doc.createTextNode( keywords );
315-
keywordsElem.appendChild( keywordsText );
470+
QDomElement keywordsElem = doc.createElement( QStringLiteral( "ows:Keywords" ) );
471+
for ( const QString &keyword : keywords.split( ',' ) )
472+
{
473+
if ( !keyword.trimmed().isEmpty() )
474+
{
475+
QDomElement keywordElem = doc.createElement( QStringLiteral( "ows:Keyword" ) );
476+
QDomText keywordText = doc.createTextNode( keyword.trimmed() );
477+
keywordElem.appendChild( keywordText );
478+
keywordsElem.appendChild( keywordElem );
479+
}
480+
}
316481
layerElem.appendChild( keywordsElem );
317482
}
318483

319-
//create SRS
320-
QDomElement srsElem = doc.createElement( QStringLiteral( "SRS" ) );
321-
QDomText srsText = doc.createTextNode( layer->crs().authid() );
484+
//create DefaultSRS element
485+
QString defaultSrs = layer->crs().authid();
486+
QDomElement srsElem = doc.createElement( QStringLiteral( "DefaultSRS" ) );
487+
QDomText srsText = doc.createTextNode( defaultSrs );
322488
srsElem.appendChild( srsText );
323489
layerElem.appendChild( srsElem );
324490

325-
//create LatLongBoundingBox
491+
//create OtherSRS elements
492+
QStringList outputCrsList = QgsServerProjectUtils::wmsOutputCrsList( *project );
493+
for ( const QString &crs : outputCrsList )
494+
{
495+
if ( crs == defaultSrs )
496+
continue;
497+
QDomElement otherSrsElem = doc.createElement( QStringLiteral( "OtherSRS" ) );
498+
QDomText otherSrsText = doc.createTextNode( crs );
499+
otherSrsElem.appendChild( otherSrsText );
500+
layerElem.appendChild( otherSrsElem );
501+
}
502+
503+
//create OutputFormats element
504+
QDomElement outputFormatsElem = doc.createElement( QStringLiteral( "OutputFormats" ) );
505+
QDomElement outputFormatElem = doc.createElement( QStringLiteral( "Format" ) );
506+
QDomText outputFormatText = doc.createTextNode( QStringLiteral( "text/xml; subtype=gml/3.1.1" ) );
507+
outputFormatElem.appendChild( outputFormatText );
508+
outputFormatsElem.appendChild( outputFormatElem );
509+
layerElem.appendChild( outputFormatsElem );
510+
511+
//create WGS84BoundingBox
326512
QgsRectangle layerExtent = layer->extent();
327-
QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) );
328-
bBoxElement.setAttribute( QStringLiteral( "minx" ), QString::number( layerExtent.xMinimum() ) );
329-
bBoxElement.setAttribute( QStringLiteral( "miny" ), QString::number( layerExtent.yMinimum() ) );
330-
bBoxElement.setAttribute( QStringLiteral( "maxx" ), QString::number( layerExtent.xMaximum() ) );
331-
bBoxElement.setAttribute( QStringLiteral( "maxy" ), QString::number( layerExtent.yMaximum() ) );
513+
//transform the layers native CRS into WGS84
514+
QgsCoordinateReferenceSystem wgs84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
515+
QgsRectangle wgs84BoundingRect;
516+
if ( !layerExtent.isNull() )
517+
{
518+
QgsCoordinateTransform exGeoTransform( layer->crs(), wgs84 );
519+
try
520+
{
521+
wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent );
522+
}
523+
catch ( const QgsCsException & )
524+
{
525+
wgs84BoundingRect = QgsRectangle();
526+
}
527+
}
528+
//create WGS84BoundingBox element
529+
QDomElement bBoxElement = doc.createElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
530+
bBoxElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) );
531+
QDomElement lCornerElement = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
532+
QDomText lCornerText = doc.createTextNode( QString::number( wgs84BoundingRect.xMinimum() ) + " " + QString::number( wgs84BoundingRect.yMinimum() ) );
533+
lCornerElement.appendChild( lCornerText );
534+
bBoxElement.appendChild( lCornerElement );
535+
QDomElement uCornerElement = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
536+
QDomText uCornerText = doc.createTextNode( QString::number( wgs84BoundingRect.xMaximum() ) + " " + QString::number( wgs84BoundingRect.yMaximum() ) );
537+
uCornerElement.appendChild( uCornerText );
538+
bBoxElement.appendChild( uCornerElement );
332539
layerElem.appendChild( bBoxElement );
333540

334541
// layer metadata URL
@@ -339,14 +546,7 @@ namespace QgsWfs
339546
QString metadataUrlType = layer->metadataUrlType();
340547
metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType );
341548
QString metadataUrlFormat = layer->metadataUrlFormat();
342-
if ( metadataUrlFormat == QLatin1String( "text/xml" ) )
343-
{
344-
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "XML" ) );
345-
}
346-
else
347-
{
348-
metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "TXT" ) );
349-
}
549+
metaUrlElem.setAttribute( QStringLiteral( "format" ), metadataUrlFormat );
350550
QDomText metaUrlText = doc.createTextNode( metadataUrl );
351551
metaUrlElem.appendChild( metaUrlText );
352552
layerElem.appendChild( metaUrlElem );

‎src/server/services/wfs/qgswfsgetcapabilities.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,24 @@ namespace QgsWfs
3333
QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project );
3434

3535
/**
36-
* Create Capability element for get capabilities document
36+
* Create a parameter element
3737
*/
38-
QDomElement getCapabilityElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request );
38+
QDomElement getParameterElement( QDomDocument &doc, const QString &name, const QStringList &values );
3939

4040
/**
41-
* Create Service element for get capabilities document
41+
* Create OperationsMetadata element for get capabilities document
4242
*/
43-
QDomElement getServiceElement( QDomDocument &doc, const QgsProject *project );
43+
QDomElement getOperationsMetadataElement( QDomDocument &doc, const QgsProject *project, const QgsServerRequest &request );
44+
45+
/**
46+
* Create Service Provider element for get capabilities document
47+
*/
48+
QDomElement getServiceProviderElement( QDomDocument &doc, const QgsProject *project );
49+
50+
/**
51+
* Create Service Identification element for get capabilities document
52+
*/
53+
QDomElement getServiceIdentificationElement( QDomDocument &doc, const QgsProject *project );
4454

4555
/**
4656
* Create get capabilities document

‎src/server/services/wfs/qgswfsgetcapabilities_1_0_0.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ namespace QgsWfs
6666
wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
6767
wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:ows" ), QStringLiteral( "http://www.opengis.net/ows" ) );
6868
wfsCapabilitiesElement.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
69-
wfsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), implementationVersion() );
69+
wfsCapabilitiesElement.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
7070
wfsCapabilitiesElement.setAttribute( QStringLiteral( "updateSequence" ), QStringLiteral( "0" ) );
7171
doc.appendChild( wfsCapabilitiesElement );
7272

0 commit comments

Comments
 (0)
Please sign in to comment.