Skip to content

Commit c00bcb1

Browse files
committed
added support for QGIS mapserver GetFeatureInfo GML flavour
1 parent be318fe commit c00bcb1

File tree

4 files changed

+115
-67
lines changed

4 files changed

+115
-67
lines changed

src/core/qgsgml.cpp

+41-25
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,18 @@ void QgsGml::startElement( const XML_Char* el, const XML_Char** attr )
296296
mAttributeName = localName;
297297
mStringCash.clear();
298298
}
299-
299+
// QGIS server (2.2) is using:
300+
// <Attribute value="My description" name="desc"/>
301+
else if ( theParseMode == feature
302+
&& localName.compare( "attribute", Qt::CaseInsensitive ) == 0 )
303+
{
304+
QString name = readAttribute( "name", attr );
305+
if ( mThematicAttributes.contains( name ) )
306+
{
307+
QString value = readAttribute( "value", attr );
308+
setAttribute( name, value );
309+
}
310+
}
300311

301312
if ( mEpsg == 0 && ( localName == "Point" || localName == "MultiPoint" ||
302313
localName == "LineString" || localName == "MultiLineString" ||
@@ -332,29 +343,7 @@ void QgsGml::endElement( const XML_Char* el )
332343
{
333344
mParseModeStack.pop();
334345

335-
//find index with attribute name
336-
QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.find( mAttributeName );
337-
if ( att_it != mThematicAttributes.constEnd() )
338-
{
339-
QVariant var;
340-
switch ( att_it.value().second.type() )
341-
{
342-
case QVariant::Double:
343-
var = QVariant( mStringCash.toDouble() );
344-
break;
345-
case QVariant::Int:
346-
var = QVariant( mStringCash.toInt() );
347-
break;
348-
case QVariant::LongLong:
349-
var = QVariant( mStringCash.toLongLong() );
350-
break;
351-
default: //string type is default
352-
var = QVariant( mStringCash );
353-
break;
354-
}
355-
Q_ASSERT( mCurrentFeature );
356-
mCurrentFeature->setAttribute( att_it.value().first, QVariant( mStringCash ) );
357-
}
346+
setAttribute( mAttributeName, mStringCash );
358347
}
359348
else if ( theParseMode == geometry && localName == mGeometryAttribute )
360349
{
@@ -550,6 +539,33 @@ void QgsGml::characters( const XML_Char* chars, int len )
550539
}
551540
}
552541

542+
void QgsGml::setAttribute( const QString& name, const QString& value )
543+
{
544+
//find index with attribute name
545+
QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.find( name );
546+
if ( att_it != mThematicAttributes.constEnd() )
547+
{
548+
QVariant var;
549+
switch ( att_it.value().second.type() )
550+
{
551+
case QVariant::Double:
552+
var = QVariant( value.toDouble() );
553+
break;
554+
case QVariant::Int:
555+
var = QVariant( value.toInt() );
556+
break;
557+
case QVariant::LongLong:
558+
var = QVariant( value.toLongLong() );
559+
break;
560+
default: //string type is default
561+
var = QVariant( value );
562+
break;
563+
}
564+
Q_ASSERT( mCurrentFeature );
565+
mCurrentFeature->setAttribute( att_it.value().first, var );
566+
}
567+
}
568+
553569
int QgsGml::readEpsgFromAttribute( int& epsgNr, const XML_Char** attr ) const
554570
{
555571
int i = 0;
@@ -590,7 +606,7 @@ QString QgsGml::readAttribute( const QString& attributeName, const XML_Char** at
590606
{
591607
return QString( attr[i+1] );
592608
}
593-
++i;
609+
i += 2;
594610
}
595611
return QString();
596612
}

src/core/qgsgml.h

+3
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ class CORE_EXPORT QgsGml : public QObject
121121
static_cast<QgsGml*>( data )->characters( chars, len );
122122
}
123123

124+
// Set current feature attribute
125+
void setAttribute( const QString& name, const QString& value );
126+
124127
//helper routines
125128

126129
/**Reads attribute srsName="EpsgCrsId:..."

src/core/qgsgmlschema.cpp

+69-42
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ QString QgsGmlSchema::readAttribute( const QString& attributeName, const XML_Cha
7979
{
8080
return QString( attr[i+1] );
8181
}
82-
++i;
82+
i += 2;
8383
}
8484
return QString();
8585
}
@@ -374,6 +374,7 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
374374
//QgsDebugMsg( "ns = " + ns + " localName = " + localName );
375375

376376
ParseMode parseMode = modeStackTop();
377+
//QgsDebugMsg ( QString("localName = %1 parseMode = %2").arg(localName).arg(parseMode) );
377378

378379
if ( ns == GML_NAMESPACE && localName == "boundedBy" )
379380
{
@@ -388,6 +389,7 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
388389
// with 'Member' apart standard gml:featureMember, but it is quite usual to
389390
// that the names ends with 'Member', e.g.: osgb:topographicMember, cityMember,...
390391
// so this is really fail if the name does not contain 'Member'
392+
391393
else if ( localName.endsWith( "member", Qt::CaseInsensitive ) )
392394
{
393395
mParseModeStack.push( QgsGmlSchema::featureMember );
@@ -398,12 +400,15 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
398400
// do nothing, we catch _feature children
399401
}
400402
// UMN Mapserver simple GetFeatureInfo response feature element (ends with _feature)
401-
// or featureMember children
403+
// or featureMember children.
404+
// QGIS mapserver 2.2 GetFeatureInfo is using <Feature id="###"> for feature member,
405+
// without any feature class distinction.
402406
else if ( elementName.endsWith( "_feature" )
403407
|| parseMode == QgsGmlSchema::featureMember
404-
|| parseMode == QgsGmlSchema::featureMembers )
408+
|| parseMode == QgsGmlSchema::featureMembers
409+
|| localName.compare( "feature", Qt::CaseInsensitive ) == 0 )
405410
{
406-
//QgsDebugMsg ( "is feature path = " + path );
411+
QgsDebugMsg( "is feature path = " + path );
407412
if ( mFeatureClassMap.count( localName ) == 0 )
408413
{
409414
mFeatureClassMap.insert( localName, QgsGmlFeatureClass( localName, path ) );
@@ -425,9 +430,26 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
425430
{
426431
// An element in feature should be ordinary or geometry attribute
427432
//QgsDebugMsg( "is attribute");
428-
mParseModeStack.push( QgsGmlSchema::attribute );
429-
mAttributeName = localName;
430-
mStringCash.clear();
433+
434+
// Usually localName is attribute name, e.g.
435+
// <gml:desc>My description</gml:desc>
436+
// but QGIS server (2.2) is using:
437+
// <Attribute value="My description" name="desc"/>
438+
QString name = readAttribute( "name", attr );
439+
//QgsDebugMsg ( "attribute name = " + name );
440+
if ( localName.compare( "attribute", Qt::CaseInsensitive ) == 0
441+
&& !name.isEmpty() )
442+
{
443+
QString value = readAttribute( "value", attr );
444+
//QgsDebugMsg ( "attribute value = " + value );
445+
addAttribute( name, value );
446+
}
447+
else
448+
{
449+
mAttributeName = localName;
450+
mParseModeStack.push( QgsGmlSchema::attribute );
451+
mStringCash.clear();
452+
}
431453
}
432454
}
433455

@@ -466,41 +488,7 @@ void QgsGmlSchema::endElement( const XML_Char* el )
466488

467489
if ( mFeatureClassMap[mCurrentFeatureName].geometryAttributes().count( mAttributeName ) == 0 )
468490
{
469-
// It is not geometry attribute -> analyze value
470-
bool ok;
471-
mStringCash.toInt( &ok );
472-
QVariant::Type type = QVariant::String;
473-
if ( ok )
474-
{
475-
type = QVariant::Int;
476-
}
477-
else
478-
{
479-
mStringCash.toDouble( &ok );
480-
if ( ok )
481-
{
482-
type = QVariant::Double;
483-
}
484-
}
485-
//QgsDebugMsg( "mStringCash = " + mStringCash + " type = " + QVariant::typeToName( type ) );
486-
//QMap<QString, QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
487-
QList<QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
488-
int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( mAttributeName );
489-
if ( fieldIndex == -1 )
490-
{
491-
QgsField field( mAttributeName, type );
492-
fields.append( field );
493-
}
494-
else
495-
{
496-
QgsField &field = fields[fieldIndex];
497-
// check if type is sufficient
498-
if (( field.type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
499-
( field.type() == QVariant::Double && type == QVariant::String ) )
500-
{
501-
field.setType( type );
502-
}
503-
}
491+
addAttribute( mAttributeName, mStringCash );
504492
}
505493
}
506494
else if ( ns == GML_NAMESPACE && localName == "boundedBy" )
@@ -531,6 +519,45 @@ void QgsGmlSchema::characters( const XML_Char* chars, int len )
531519
}
532520
}
533521

522+
void QgsGmlSchema::addAttribute( const QString& name, const QString& value )
523+
{
524+
// It is not geometry attribute -> analyze value
525+
bool ok;
526+
value.toInt( &ok );
527+
QVariant::Type type = QVariant::String;
528+
if ( ok )
529+
{
530+
type = QVariant::Int;
531+
}
532+
else
533+
{
534+
value.toDouble( &ok );
535+
if ( ok )
536+
{
537+
type = QVariant::Double;
538+
}
539+
}
540+
//QgsDebugMsg( "mStringCash = " + mStringCash + " type = " + QVariant::typeToName( type ) );
541+
//QMap<QString, QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
542+
QList<QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
543+
int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( name );
544+
if ( fieldIndex == -1 )
545+
{
546+
QgsField field( name, type );
547+
fields.append( field );
548+
}
549+
else
550+
{
551+
QgsField &field = fields[fieldIndex];
552+
// check if type is sufficient
553+
if (( field.type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
554+
( field.type() == QVariant::Double && type == QVariant::String ) )
555+
{
556+
field.setType( type );
557+
}
558+
}
559+
}
560+
534561
QStringList QgsGmlSchema::typeNames() const
535562
{
536563
return mFeatureClassMap.keys();

src/core/qgsgmlschema.h

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ class CORE_EXPORT QgsGmlSchema : public QObject
131131
{
132132
static_cast<QgsGmlSchema*>( data )->characters( chars, len );
133133
}
134+
// Add attribute or reset its type according to value of current feature
135+
void addAttribute( const QString& name, const QString& value );
134136

135137
//helper routines
136138

0 commit comments

Comments
 (0)