Skip to content
Permalink
Browse files

added support for QGIS mapserver GetFeatureInfo GML flavour

  • Loading branch information
blazek committed May 21, 2014
1 parent be318fe commit c00bcb1bd07461fd95a3d067235459bd81c3cafe
Showing with 115 additions and 67 deletions.
  1. +41 −25 src/core/qgsgml.cpp
  2. +3 −0 src/core/qgsgml.h
  3. +69 −42 src/core/qgsgmlschema.cpp
  4. +2 −0 src/core/qgsgmlschema.h
@@ -296,7 +296,18 @@ void QgsGml::startElement( const XML_Char* el, const XML_Char** attr )
mAttributeName = localName;
mStringCash.clear();
}

// QGIS server (2.2) is using:
// <Attribute value="My description" name="desc"/>
else if ( theParseMode == feature
&& localName.compare( "attribute", Qt::CaseInsensitive ) == 0 )
{
QString name = readAttribute( "name", attr );
if ( mThematicAttributes.contains( name ) )
{
QString value = readAttribute( "value", attr );
setAttribute( name, value );
}
}

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

//find index with attribute name
QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.find( mAttributeName );
if ( att_it != mThematicAttributes.constEnd() )
{
QVariant var;
switch ( att_it.value().second.type() )
{
case QVariant::Double:
var = QVariant( mStringCash.toDouble() );
break;
case QVariant::Int:
var = QVariant( mStringCash.toInt() );
break;
case QVariant::LongLong:
var = QVariant( mStringCash.toLongLong() );
break;
default: //string type is default
var = QVariant( mStringCash );
break;
}
Q_ASSERT( mCurrentFeature );
mCurrentFeature->setAttribute( att_it.value().first, QVariant( mStringCash ) );
}
setAttribute( mAttributeName, mStringCash );
}
else if ( theParseMode == geometry && localName == mGeometryAttribute )
{
@@ -550,6 +539,33 @@ void QgsGml::characters( const XML_Char* chars, int len )
}
}

void QgsGml::setAttribute( const QString& name, const QString& value )
{
//find index with attribute name
QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.find( name );
if ( att_it != mThematicAttributes.constEnd() )
{
QVariant var;
switch ( att_it.value().second.type() )
{
case QVariant::Double:
var = QVariant( value.toDouble() );
break;
case QVariant::Int:
var = QVariant( value.toInt() );
break;
case QVariant::LongLong:
var = QVariant( value.toLongLong() );
break;
default: //string type is default
var = QVariant( value );
break;
}
Q_ASSERT( mCurrentFeature );
mCurrentFeature->setAttribute( att_it.value().first, var );
}
}

int QgsGml::readEpsgFromAttribute( int& epsgNr, const XML_Char** attr ) const
{
int i = 0;
@@ -590,7 +606,7 @@ QString QgsGml::readAttribute( const QString& attributeName, const XML_Char** at
{
return QString( attr[i+1] );
}
++i;
i += 2;
}
return QString();
}
@@ -121,6 +121,9 @@ class CORE_EXPORT QgsGml : public QObject
static_cast<QgsGml*>( data )->characters( chars, len );
}

// Set current feature attribute
void setAttribute( const QString& name, const QString& value );

//helper routines

/**Reads attribute srsName="EpsgCrsId:..."
@@ -79,7 +79,7 @@ QString QgsGmlSchema::readAttribute( const QString& attributeName, const XML_Cha
{
return QString( attr[i+1] );
}
++i;
i += 2;
}
return QString();
}
@@ -374,6 +374,7 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
//QgsDebugMsg( "ns = " + ns + " localName = " + localName );

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

if ( ns == GML_NAMESPACE && localName == "boundedBy" )
{
@@ -388,6 +389,7 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
// with 'Member' apart standard gml:featureMember, but it is quite usual to
// that the names ends with 'Member', e.g.: osgb:topographicMember, cityMember,...
// so this is really fail if the name does not contain 'Member'

else if ( localName.endsWith( "member", Qt::CaseInsensitive ) )
{
mParseModeStack.push( QgsGmlSchema::featureMember );
@@ -398,12 +400,15 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
// do nothing, we catch _feature children
}
// UMN Mapserver simple GetFeatureInfo response feature element (ends with _feature)
// or featureMember children
// or featureMember children.
// QGIS mapserver 2.2 GetFeatureInfo is using <Feature id="###"> for feature member,
// without any feature class distinction.
else if ( elementName.endsWith( "_feature" )
|| parseMode == QgsGmlSchema::featureMember
|| parseMode == QgsGmlSchema::featureMembers )
|| parseMode == QgsGmlSchema::featureMembers
|| localName.compare( "feature", Qt::CaseInsensitive ) == 0 )
{
//QgsDebugMsg ( "is feature path = " + path );
QgsDebugMsg( "is feature path = " + path );
if ( mFeatureClassMap.count( localName ) == 0 )
{
mFeatureClassMap.insert( localName, QgsGmlFeatureClass( localName, path ) );
@@ -425,9 +430,26 @@ void QgsGmlSchema::startElement( const XML_Char* el, const XML_Char** attr )
{
// An element in feature should be ordinary or geometry attribute
//QgsDebugMsg( "is attribute");
mParseModeStack.push( QgsGmlSchema::attribute );
mAttributeName = localName;
mStringCash.clear();

// Usually localName is attribute name, e.g.
// <gml:desc>My description</gml:desc>
// but QGIS server (2.2) is using:
// <Attribute value="My description" name="desc"/>
QString name = readAttribute( "name", attr );
//QgsDebugMsg ( "attribute name = " + name );
if ( localName.compare( "attribute", Qt::CaseInsensitive ) == 0
&& !name.isEmpty() )
{
QString value = readAttribute( "value", attr );
//QgsDebugMsg ( "attribute value = " + value );
addAttribute( name, value );
}
else
{
mAttributeName = localName;
mParseModeStack.push( QgsGmlSchema::attribute );
mStringCash.clear();
}
}
}

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

if ( mFeatureClassMap[mCurrentFeatureName].geometryAttributes().count( mAttributeName ) == 0 )
{
// It is not geometry attribute -> analyze value
bool ok;
mStringCash.toInt( &ok );
QVariant::Type type = QVariant::String;
if ( ok )
{
type = QVariant::Int;
}
else
{
mStringCash.toDouble( &ok );
if ( ok )
{
type = QVariant::Double;
}
}
//QgsDebugMsg( "mStringCash = " + mStringCash + " type = " + QVariant::typeToName( type ) );
//QMap<QString, QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
QList<QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( mAttributeName );
if ( fieldIndex == -1 )
{
QgsField field( mAttributeName, type );
fields.append( field );
}
else
{
QgsField &field = fields[fieldIndex];
// check if type is sufficient
if (( field.type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
( field.type() == QVariant::Double && type == QVariant::String ) )
{
field.setType( type );
}
}
addAttribute( mAttributeName, mStringCash );
}
}
else if ( ns == GML_NAMESPACE && localName == "boundedBy" )
@@ -531,6 +519,45 @@ void QgsGmlSchema::characters( const XML_Char* chars, int len )
}
}

void QgsGmlSchema::addAttribute( const QString& name, const QString& value )
{
// It is not geometry attribute -> analyze value
bool ok;
value.toInt( &ok );
QVariant::Type type = QVariant::String;
if ( ok )
{
type = QVariant::Int;
}
else
{
value.toDouble( &ok );
if ( ok )
{
type = QVariant::Double;
}
}
//QgsDebugMsg( "mStringCash = " + mStringCash + " type = " + QVariant::typeToName( type ) );
//QMap<QString, QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
QList<QgsField> & fields = mFeatureClassMap[mCurrentFeatureName].fields();
int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( name );
if ( fieldIndex == -1 )
{
QgsField field( name, type );
fields.append( field );
}
else
{
QgsField &field = fields[fieldIndex];
// check if type is sufficient
if (( field.type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
( field.type() == QVariant::Double && type == QVariant::String ) )
{
field.setType( type );
}
}
}

QStringList QgsGmlSchema::typeNames() const
{
return mFeatureClassMap.keys();
@@ -131,6 +131,8 @@ class CORE_EXPORT QgsGmlSchema : public QObject
{
static_cast<QgsGmlSchema*>( data )->characters( chars, len );
}
// Add attribute or reset its type according to value of current feature
void addAttribute( const QString& name, const QString& value );

//helper routines

0 comments on commit c00bcb1

Please sign in to comment.
You can’t perform that action at this time.