27 #include <QNetworkRequest>    28 #include <QNetworkReply>    29 #include <QProgressDialog>    39 static const char *
GML_NAMESPACE = 
"http://www.opengis.net/gml";
    40 static const char *GML32_NAMESPACE = 
"http://www.opengis.net/gml/3.2";
    43   const QString &typeName,
    44   const QString &geometryAttribute,
    46   : mParser( typeName, geometryAttribute, fields )
    47   , mTypeName( typeName )
    50   int index = mTypeName.indexOf( 
':' );
    51   if ( index != -1 && index < mTypeName.length() )
    53     mTypeName = mTypeName.mid( index + 1 );
    62   QNetworkRequest request( uri );
    63   if ( !authcfg.isEmpty() )
    68         tr( 
"GML Getfeature network request update failed for authcfg %1" ).arg( authcfg ),
    75   else if ( !userName.isNull() || !password.isNull() )
    77     request.setRawHeader( 
"Authorization", 
"Basic " + QStringLiteral( 
"%1:%2" ).arg( userName, password ).toLatin1().toBase64() );
    81   if ( !authcfg.isEmpty() )
    87         tr( 
"GML Getfeature network reply update failed for authcfg %1" ).arg( authcfg ),
    95   connect( reply, &QNetworkReply::finished, 
this, &QgsGml::setFinished );
    96   connect( reply, &QNetworkReply::downloadProgress, 
this, &QgsGml::handleProgressEvent );
    99   QProgressDialog *progressDialog = 
nullptr;
   100   QWidget *mainWindow = 
nullptr;
   101   QWidgetList topLevelWidgets = qApp->topLevelWidgets();
   102   for ( QWidgetList::const_iterator it = topLevelWidgets.constBegin(); it != topLevelWidgets.constEnd(); ++it )
   104     if ( ( *it )->objectName() == QLatin1String( 
"QgisApp" ) )
   112     progressDialog = 
new QProgressDialog( tr( 
"Loading GML data\n%1" ).arg( mTypeName ), tr( 
"Abort" ), 0, 0, mainWindow );
   113     progressDialog->setWindowModality( Qt::ApplicationModal );
   116     connect( progressDialog, &QProgressDialog::canceled, 
this, &QgsGml::setFinished );
   117     progressDialog->show();
   127     QByteArray readData = reply->readAll();
   128     if ( !readData.isEmpty() )
   131       if ( !mParser.
processData( readData, atEnd, errorMsg ) )
   135     QCoreApplication::processEvents();
   138   fillMapsFromParser();
   140   QNetworkReply::NetworkError replyError = reply->error();
   141   QString replyErrorString = reply->errorString();
   144   delete progressDialog;
   149       tr( 
"GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
   163       calculateExtentFromFeatures();
   178   if ( !mParser.
processData( data, 
true , errorMsg ) )
   181   fillMapsFromParser();
   191 void QgsGml::fillMapsFromParser()
   197     const QString &gmlId = featPair.second;
   198     mFeatures.insert( feat->
id(), feat );
   199     if ( !gmlId.isEmpty() )
   201       mIdMap.insert( feat->
id(), gmlId );
   206 void QgsGml::setFinished()
   211 void QgsGml::handleProgressEvent( qint64 progress, qint64 totalSteps )
   213   if ( totalSteps < 0 )
   223 void QgsGml::calculateExtentFromFeatures()
   225   if ( mFeatures.empty() )
   232   bool bboxInitialized = 
false; 
   234   for ( 
int i = 0; i < mFeatures.size(); ++i )
   236     currentFeature = mFeatures[i];
   237     if ( !currentFeature )
   241     currentGeometry = currentFeature->
geometry();
   242     if ( !currentGeometry.
isNull() )
   244       if ( !bboxInitialized )
   247         bboxInitialized = 
true;
   272     const QString &geometryAttribute,
   275     bool invertAxisOrientation )
   276   : mTypeName( typeName )
   277   , mTypeNameBA( mTypeName.toUtf8() )
   278   , mTypeNamePtr( mTypeNameBA.constData() )
   279   , mTypeNameUTF8Len( strlen( mTypeNamePtr ) )
   281   , mGeometryAttribute( geometryAttribute )
   282   , mGeometryAttributeBA( geometryAttribute.toUtf8() )
   283   , mGeometryAttributePtr( mGeometryAttributeBA.constData() )
   284   , mGeometryAttributeUTF8Len( strlen( mGeometryAttributePtr ) )
   286   , mIsException( false )
   287   , mTruncatedResponse( false )
   289   , mFeatureTupleDepth( 0 )
   291   , mCurrentWKB( nullptr, 0 )
   292   , mBoundedByNullFound( false )
   294   , mCoorMode( Coordinate )
   296   , mAxisOrientationLogic( axisOrientationLogic )
   297   , mInvertAxisOrientationRequest( invertAxisOrientation )
   298   , mInvertAxisOrientation( invertAxisOrientation )
   299   , mNumberReturned( -1 )
   300   , mNumberMatched( -1 )
   301   , mFoundUnhandledGeometryElement( false )
   303   mThematicAttributes.clear();
   304   for ( 
int i = 0; i < fields.
size(); i++ )
   306     mThematicAttributes.insert( fields.
at( i ).
name(), qMakePair( i, fields.
at( i ) ) );
   311   int index = mTypeName.indexOf( 
':' );
   312   if ( index != -1 && index < mTypeName.length() )
   314     mTypeName = mTypeName.mid( index + 1 );
   315     mTypeNameBA = mTypeName.toUtf8();
   316     mTypeNamePtr = mTypeNameBA.constData();
   317     mTypeNameUTF8Len = strlen( mTypeNamePtr );
   321   XML_SetUserData( mParser, 
this );
   322   XML_SetElementHandler( mParser, QgsGmlStreamingParser::start, QgsGmlStreamingParser::end );
   323   XML_SetCharacterDataHandler( mParser, QgsGmlStreamingParser::chars );
   326 static QString stripNS( 
const QString &
string )
   328   int index = 
string.indexOf( 
':' );
   329   if ( index != -1 && index < 
string.length() )
   331     return string.mid( index + 1 );
   338     const QMap< QString, QPair<QString, QString> > &mapFieldNameToSrcLayerNameFieldName,
   340     bool invertAxisOrientation )
   341   : mLayerProperties( layerProperties )
   342   , mTypeNameUTF8Len( 0 )
   344   , mGeometryAttributeUTF8Len( 0 )
   346   , mIsException( false )
   347   , mTruncatedResponse( false )
   349   , mFeatureTupleDepth( 0 )
   351   , mCurrentWKB( nullptr, 0 )
   352   , mBoundedByNullFound( false )
   354   , mCoorMode( Coordinate )
   356   , mAxisOrientationLogic( axisOrientationLogic )
   357   , mInvertAxisOrientationRequest( invertAxisOrientation )
   358   , mInvertAxisOrientation( invertAxisOrientation )
   359   , mNumberReturned( -1 )
   360   , mNumberMatched( -1 )
   361   , mFoundUnhandledGeometryElement( false )
   363   mThematicAttributes.clear();
   364   for ( 
int i = 0; i < fields.
size(); i++ )
   366     QMap< QString, QPair<QString, QString> >::const_iterator att_it = mapFieldNameToSrcLayerNameFieldName.constFind( fields.
at( i ).
name() );
   367     if ( att_it != mapFieldNameToSrcLayerNameFieldName.constEnd() )
   369       if ( mLayerProperties.size() == 1 )
   370         mThematicAttributes.insert( att_it.value().second, qMakePair( i, fields.
at( i ) ) );
   372         mThematicAttributes.insert( stripNS( att_it.value().first ) + 
"|" + att_it.value().second, qMakePair( i, fields.
at( i ) ) );
   375   bool alreadyFoundGeometry = 
false;
   376   for ( 
int i = 0; i < mLayerProperties.size(); i++ )
   379     if ( !mLayerProperties[i].mGeometryAttribute.isEmpty() )
   381       if ( alreadyFoundGeometry )
   383         QgsDebugMsg( QString( 
"Will ignore geometry field %1 from typename %2" ).
   384                      arg( mLayerProperties[i].mGeometryAttribute, mLayerProperties[i].mName ) );
   385         mLayerProperties[i].mGeometryAttribute.clear();
   387       alreadyFoundGeometry = 
true;
   389     mMapTypeNameToProperties.insert( stripNS( mLayerProperties[i].mName ), mLayerProperties[i] );
   392   if ( mLayerProperties.size() == 1 )
   394     mTypeName = mLayerProperties[0].mName;
   395     mGeometryAttribute = mLayerProperties[0].mGeometryAttribute;
   396     mGeometryAttributeBA = mGeometryAttribute.toUtf8();
   397     mGeometryAttributePtr = mGeometryAttributeBA.constData();
   398     mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
   399     int index = mTypeName.indexOf( 
':' );
   400     if ( index != -1 && index < mTypeName.length() )
   402       mTypeName = mTypeName.mid( index + 1 );
   404     mTypeNameBA = mTypeName.toUtf8();
   405     mTypeNamePtr = mTypeNameBA.constData();
   406     mTypeNameUTF8Len = strlen( mTypeNamePtr );
   412   XML_SetUserData( mParser, 
this );
   413   XML_SetElementHandler( mParser, QgsGmlStreamingParser::start, QgsGmlStreamingParser::end );
   414   XML_SetCharacterDataHandler( mParser, QgsGmlStreamingParser::chars );
   420   XML_ParserFree( mParser );
   425     delete featPair.first;
   428   delete mCurrentFeature;
   444   if ( XML_Parse( mParser, data.data(), data.size(), atEnd ) == 0 )
   446     XML_Error errorCode = XML_GetErrorCode( mParser );
   447     errorMsg = QObject::tr( 
"Error: %1 on line %2, column %3" )
   448                .arg( XML_ErrorString( errorCode ) )
   449                .arg( XML_GetCurrentLineNumber( mParser ) )
   450                .arg( XML_GetCurrentColumnNumber( mParser ) );
   460   QVector<QgsGmlFeaturePtrGmlIdPair> ret = mFeatureList;
   461   mFeatureList.clear();
   465 #define LOCALNAME_EQUALS(string_constant) \   466   ( localNameLen == ( int )strlen( string_constant ) && memcmp(pszLocalName, string_constant, localNameLen) == 0 )   468 void QgsGmlStreamingParser::startElement( 
const XML_Char *el, 
const XML_Char **attr )
   470   const int elLen = ( int )strlen( el );
   472   const char *pszLocalName = ( pszSep ) ? pszSep + 1 : el;
   473   const int nsLen = ( pszSep ) ? ( 
int )( pszSep - el ) : 0;
   474   const int localNameLen = ( pszSep ) ? ( 
int )( elLen - nsLen ) - 1 : elLen;
   475   ParseMode parseMode( mParseModeStack.isEmpty() ? None : mParseModeStack.top() );
   479   if ( !mGMLNameSpaceURIPtr && pszSep )
   486     else if ( nsLen == ( 
int )strlen( GML32_NAMESPACE ) && memcmp( el, GML32_NAMESPACE, nsLen ) == 0 )
   488       mGMLNameSpaceURI = GML32_NAMESPACE;
   489       mGMLNameSpaceURIPtr = GML32_NAMESPACE;
   493   const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && mGMLNameSpaceURIPtr && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
   496   if ( parseMode == Geometry || parseMode == Coordinate || parseMode == PosList ||
   497        parseMode == MultiPoint || parseMode == MultiLine || parseMode == MultiPolygon )
   499     mGeometryString.append( 
"<", 1 );
   500     mGeometryString.append( pszLocalName, localNameLen );
   501     mGeometryString.append( 
" ", 1 );
   502     for ( 
const XML_Char **attrIter = attr; attrIter && *attrIter; attrIter += 2 )
   504       mGeometryString.append( attrIter[0] );
   505       mGeometryString.append( 
"=\"", 2 );
   506       mGeometryString.append( attrIter[1] );
   507       mGeometryString.append( 
"\" ", 2 );
   510     mGeometryString.append( 
">", 1 );
   515     mParseModeStack.push( Coordinate );
   516     mCoorMode = QgsGmlStreamingParser::Coordinate;
   518     mCoordinateSeparator = readAttribute( QStringLiteral( 
"cs" ), attr );
   519     if ( mCoordinateSeparator.isEmpty() )
   521       mCoordinateSeparator = 
',';
   523     mTupleSeparator = readAttribute( QStringLiteral( 
"ts" ), attr );
   524     if ( mTupleSeparator.isEmpty() )
   526       mTupleSeparator = 
' ';
   532     mParseModeStack.push( QgsGmlStreamingParser::PosList );
   533     mCoorMode = QgsGmlStreamingParser::PosList;
   535     if ( elDimension == 0 )
   537       QString srsDimension = readAttribute( QStringLiteral( 
"srsDimension" ), attr );
   539       int dimension = srsDimension.toInt( &ok );
   542         elDimension = dimension;
   546   else if ( ( parseMode == Feature || parseMode == FeatureTuple ) &&
   548             localNameLen == static_cast<int>( mGeometryAttributeUTF8Len ) &&
   549             memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
   551     mParseModeStack.push( QgsGmlStreamingParser::Geometry );
   552     mFoundUnhandledGeometryElement = 
false;
   553     mGeometryString.clear();
   558     mParseModeStack.push( QgsGmlStreamingParser::BoundingBox );
   560     mBoundedByNullFound = 
false;
   562   else if ( parseMode == BoundingBox &&
   565     mParseModeStack.push( QgsGmlStreamingParser::Null );
   566     mBoundedByNullFound = 
true;
   568   else if ( parseMode == BoundingBox &&
   572     mParseModeStack.push( QgsGmlStreamingParser::Envelope );
   574   else if ( parseMode == Envelope &&
   577     mParseModeStack.push( QgsGmlStreamingParser::LowerCorner );
   580   else if ( parseMode == Envelope &&
   583     mParseModeStack.push( QgsGmlStreamingParser::UpperCorner );
   586   else if ( parseMode == None && !mTypeNamePtr &&
   589     Q_ASSERT( !mCurrentFeature );
   590     mCurrentFeature = 
new QgsFeature( mFeatureCount );
   594     mParseModeStack.push( QgsGmlStreamingParser::Tuple );
   595     mCurrentFeatureId.clear();
   597   else if ( parseMode == Tuple )
   599     QString currentTypename( QString::fromUtf8( pszLocalName, localNameLen ) );
   600     QMap< QString, LayerProperties >::const_iterator iter = mMapTypeNameToProperties.constFind( currentTypename );
   601     if ( iter != mMapTypeNameToProperties.constEnd() )
   603       mFeatureTupleDepth = mParseDepth;
   604       mCurrentTypename = currentTypename;
   605       mGeometryAttribute.clear();
   606       if ( mCurrentWKB.
size() == 0 )
   608         mGeometryAttribute = iter.value().mGeometryAttribute;
   610       mGeometryAttributeBA = mGeometryAttribute.toUtf8();
   611       mGeometryAttributePtr = mGeometryAttributeBA.constData();
   612       mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
   613       mParseModeStack.push( QgsGmlStreamingParser::FeatureTuple );
   615       if ( mGMLNameSpaceURI.isEmpty() )
   625           id = readAttribute( QString( GML32_NAMESPACE ) + 
NS_SEPARATOR + 
"id", attr );
   628             mGMLNameSpaceURI = GML32_NAMESPACE;
   629             mGMLNameSpaceURIPtr = GML32_NAMESPACE;
   634         id = readAttribute( mGMLNameSpaceURI + 
NS_SEPARATOR + 
"id", attr );
   635       if ( !mCurrentFeatureId.isEmpty() )
   636         mCurrentFeatureId += 
'|';
   637       mCurrentFeatureId += id;
   640   else if ( parseMode == None &&
   641             localNameLen == static_cast<int>( mTypeNameUTF8Len ) &&
   642             memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 )
   644     Q_ASSERT( !mCurrentFeature );
   645     mCurrentFeature = 
new QgsFeature( mFeatureCount );
   649     mParseModeStack.push( QgsGmlStreamingParser::Feature );
   650     mCurrentFeatureId = readAttribute( QStringLiteral( 
"fid" ), attr );
   651     if ( mCurrentFeatureId.isEmpty() )
   656       if ( mGMLNameSpaceURI.isEmpty() )
   659         if ( !mCurrentFeatureId.isEmpty() )
   666           mCurrentFeatureId = readAttribute( QString( GML32_NAMESPACE ) + 
NS_SEPARATOR + 
"id", attr );
   667           if ( !mCurrentFeatureId.isEmpty() )
   669             mGMLNameSpaceURI = GML32_NAMESPACE;
   670             mGMLNameSpaceURIPtr = GML32_NAMESPACE;
   675         mCurrentFeatureId = readAttribute( mGMLNameSpaceURI + 
NS_SEPARATOR + 
"id", attr );
   679   else if ( parseMode == BoundingBox && isGMLNS && 
LOCALNAME_EQUALS( 
"Box" ) )
   692             localNameLen == ( 
int )strlen( 
"Polygon" ) && memcmp( pszLocalName, 
"Polygon", localNameLen ) == 0 )
   695     mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
   700     mParseModeStack.push( QgsGmlStreamingParser::MultiPoint );
   702     mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
   707     mParseModeStack.push( QgsGmlStreamingParser::MultiLine );
   709     mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
   714     mParseModeStack.push( QgsGmlStreamingParser::MultiPolygon );
   716   else if ( parseMode == FeatureTuple )
   718     QString localName( QString::fromUtf8( pszLocalName, localNameLen ) );
   719     if ( mThematicAttributes.contains( mCurrentTypename + 
'|' + localName ) )
   721       mParseModeStack.push( QgsGmlStreamingParser::AttributeTuple );
   722       mAttributeName = mCurrentTypename + 
'|' + localName;
   726   else if ( parseMode == Feature )
   728     QString localName( QString::fromUtf8( pszLocalName, localNameLen ) );
   729     if ( mThematicAttributes.contains( localName ) )
   731       mParseModeStack.push( QgsGmlStreamingParser::Attribute );
   732       mAttributeName = localName;
   739       if ( localName.compare( QLatin1String( 
"attribute" ), Qt::CaseInsensitive ) == 0 )
   741         QString name = readAttribute( QStringLiteral( 
"name" ), attr );
   742         if ( mThematicAttributes.contains( name ) )
   744           QString value = readAttribute( QStringLiteral( 
"value" ), attr );
   745           setAttribute( name, value );
   752     QString 
numberReturned = readAttribute( QStringLiteral( 
"numberReturned" ), attr ); 
   753     if ( numberReturned.isEmpty() )
   754       numberReturned = readAttribute( QStringLiteral( 
"numberOfFeatures" ), attr ); 
   756     mNumberReturned = numberReturned.toInt( &conversionOk );
   758       mNumberReturned = -1;
   760     QString 
numberMatched = readAttribute( QStringLiteral( 
"numberMatched" ), attr ); 
   761     mNumberMatched = numberMatched.toInt( &conversionOk );
   768     mParseModeStack.push( QgsGmlStreamingParser::ExceptionReport );
   773     mParseModeStack.push( QgsGmlStreamingParser::ExceptionText );
   778     mTruncatedResponse = 
true;
   780   else if ( !mGeometryString.empty() &&
   796     mFoundUnhandledGeometryElement = 
true;
   799   if ( !mGeometryString.empty() )
   802   if ( elDimension == 0 && isGeom )
   806     QString srsDimension = readAttribute( QStringLiteral( 
"srsDimension" ), attr );
   808     int dimension = srsDimension.toInt( &ok );
   811       elDimension = dimension;
   815   if ( elDimension != 0 )
   817     mDimension = elDimension;
   819   mDimensionStack.push( mDimension );
   821   if ( mEpsg == 0 && isGeom )
   823     if ( readEpsgFromAttribute( mEpsg, attr ) != 0 )
   829       QgsDebugMsg( QString( 
"mEpsg = %1" ).arg( mEpsg ) );
   836 void QgsGmlStreamingParser::endElement( 
const XML_Char *el )
   840   const int elLen = ( int )strlen( el );
   842   const char *pszLocalName = ( pszSep ) ? pszSep + 1 : el;
   843   const int nsLen = ( pszSep ) ? ( 
int )( pszSep - el ) : 0;
   844   const int localNameLen = ( pszSep ) ? ( 
int )( elLen - nsLen ) - 1 : elLen;
   845   ParseMode parseMode( mParseModeStack.isEmpty() ? None : mParseModeStack.top() );
   847   mDimension = mDimensionStack.isEmpty() ? 0 : mDimensionStack.pop();
   849   const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && mGMLNameSpaceURIPtr && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
   851   if ( parseMode == Coordinate && isGMLNS && 
LOCALNAME_EQUALS( 
"coordinates" ) )
   853     mParseModeStack.pop();
   855   else if ( parseMode == PosList && isGMLNS &&
   858     mParseModeStack.pop();
   860   else if ( parseMode == AttributeTuple &&
   861             mCurrentTypename + 
'|' + QString::fromUtf8( pszLocalName, localNameLen ) == mAttributeName ) 
   863     mParseModeStack.pop();
   865     setAttribute( mAttributeName, mStringCash );
   867   else if ( parseMode == Attribute && QString::fromUtf8( pszLocalName, localNameLen ) == mAttributeName ) 
   869     mParseModeStack.pop();
   871     setAttribute( mAttributeName, mStringCash );
   873   else if ( parseMode == Geometry &&
   874             localNameLen == static_cast<int>( mGeometryAttributeUTF8Len ) &&
   875             memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
   877     mParseModeStack.pop();
   878     if ( mFoundUnhandledGeometryElement )
   883         const int wkbSize = OGR_G_WkbSize( hGeom.get() );
   884         unsigned char *pabyBuffer = 
new unsigned char[ wkbSize ];
   885         OGR_G_ExportToIsoWkb( hGeom.get(), wkbNDR, pabyBuffer );
   887         g.
fromWkb( pabyBuffer, wkbSize );
   888         if ( mInvertAxisOrientation )
   890           g.transform( QTransform( 0, 1, 1, 0, 0, 0 ) );
   892         Q_ASSERT( mCurrentFeature );
   896     mGeometryString.clear();
   898   else if ( parseMode == BoundingBox && isGMLNS && 
LOCALNAME_EQUALS( 
"boundedBy" ) )
   901     if ( mCurrentExtent.
isNull() &&
   902          !mBoundedByNullFound &&
   903          !createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) )
   907     if ( !mCurrentExtent.
isNull() && mLayerExtent.
isNull() &&
   908          !mCurrentFeature && mFeatureCount == 0 )
   910       mLayerExtent = mCurrentExtent;
   914     mParseModeStack.pop();
   918     mParseModeStack.pop();
   920   else if ( parseMode == Envelope && isGMLNS && 
LOCALNAME_EQUALS( 
"Envelope" ) )
   922     mParseModeStack.pop();
   924   else if ( parseMode == LowerCorner && isGMLNS && 
LOCALNAME_EQUALS( 
"lowerCorner" ) )
   926     QList<QgsPointXY> points;
   927     pointsFromPosListString( points, mStringCash, 2 );
   928     if ( points.size() == 1 )
   933     mParseModeStack.pop();
   935   else if ( parseMode == UpperCorner && isGMLNS && 
LOCALNAME_EQUALS( 
"upperCorner" ) )
   937     QList<QgsPointXY> points;
   938     pointsFromPosListString( points, mStringCash, 2 );
   939     if ( points.size() == 1 )
   944     mParseModeStack.pop();
   946   else if ( parseMode == FeatureTuple && mParseDepth == mFeatureTupleDepth )
   948     mParseModeStack.pop();
   949     mFeatureTupleDepth = 0;
   951   else if ( ( parseMode == Tuple && !mTypeNamePtr &&
   953             ( parseMode == Feature &&
   954               localNameLen == static_cast<int>( mTypeNameUTF8Len ) &&
   955               memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 ) )
   957     Q_ASSERT( mCurrentFeature );
   960       if ( mCurrentWKB.
size() > 0 )
   967       else if ( !mCurrentExtent.
isEmpty() )
   976     mCurrentFeature = 
nullptr;
   978     mParseModeStack.pop();
   982     QList<QgsPointXY> pointList;
   983     if ( pointsFromString( pointList, mStringCash ) != 0 )
   988     if ( pointList.isEmpty() )
   991     if ( parseMode == QgsGmlStreamingParser::Geometry )
   994       if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 )
  1007       if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 )
  1011       if ( !mCurrentWKBFragments.isEmpty() )
  1013         mCurrentWKBFragments.last().push_back( wkbPtr );
  1026     QList<QgsPointXY> pointList;
  1027     if ( pointsFromString( pointList, mStringCash ) != 0 )
  1031     if ( parseMode == QgsGmlStreamingParser::Geometry )
  1033       if ( getLineWKB( mCurrentWKB, pointList ) != 0 )
  1046       if ( getLineWKB( wkbPtr, pointList ) != 0 )
  1050       if ( !mCurrentWKBFragments.isEmpty() )
  1052         mCurrentWKBFragments.last().push_back( wkbPtr );
  1061   else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) &&
  1064     QList<QgsPointXY> pointList;
  1065     if ( pointsFromString( pointList, mStringCash ) != 0 )
  1071     if ( getRingWKB( wkbPtr, pointList ) != 0 )
  1076     if ( !mCurrentWKBFragments.isEmpty() )
  1078       mCurrentWKBFragments.last().push_back( wkbPtr );
  1086   else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) && isGMLNS &&
  1094     if ( parseMode == Geometry )
  1096       createPolygonFromFragments();
  1099   else if ( parseMode == MultiPoint &&  isGMLNS &&
  1103     mParseModeStack.pop();
  1104     createMultiPointFromFragments();
  1106   else if ( parseMode == MultiLine && isGMLNS &&
  1110     mParseModeStack.pop();
  1111     createMultiLineFromFragments();
  1113   else if ( parseMode == MultiPolygon && isGMLNS &&
  1117     mParseModeStack.pop();
  1118     createMultiPolygonFromFragments();
  1122     mParseModeStack.pop();
  1124   else if ( parseMode == ExceptionText && 
LOCALNAME_EQUALS( 
"ExceptionText" ) )
  1126     mExceptionText = mStringCash;
  1127     mParseModeStack.pop();
  1130   if ( !mGeometryString.empty() )
  1132     mGeometryString.append( 
"</", 2 );
  1133     mGeometryString.append( pszLocalName, localNameLen );
  1134     mGeometryString.append( 
">", 1 );
  1139 void QgsGmlStreamingParser::characters( 
const XML_Char *chars, 
int len )
  1142   if ( mParseModeStack.isEmpty() )
  1147   if ( !mGeometryString.empty() )
  1149     mGeometryString.append( chars, len );
  1152   QgsGmlStreamingParser::ParseMode parseMode = mParseModeStack.top();
  1153   if ( parseMode == QgsGmlStreamingParser::Attribute ||
  1154        parseMode == QgsGmlStreamingParser::AttributeTuple ||
  1155        parseMode == QgsGmlStreamingParser::Coordinate ||
  1156        parseMode == QgsGmlStreamingParser::PosList ||
  1157        parseMode == QgsGmlStreamingParser::LowerCorner ||
  1158        parseMode == QgsGmlStreamingParser::UpperCorner ||
  1159        parseMode == QgsGmlStreamingParser::ExceptionText )
  1161     mStringCash.append( QString::fromUtf8( chars, len ) );
  1165 void QgsGmlStreamingParser::setAttribute( 
const QString &name, 
const QString &value )
  1168   QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.constFind( name );
  1169   if ( att_it != mThematicAttributes.constEnd() )
  1172     switch ( att_it.value().second.type() )
  1174       case QVariant::Double:
  1175         var = QVariant( value.toDouble() );
  1178         var = QVariant( value.toInt() );
  1180       case QVariant::LongLong:
  1181         var = QVariant( value.toLongLong() );
  1183       case QVariant::DateTime:
  1184         var = QVariant( QDateTime::fromString( value, Qt::ISODate ) );
  1187         var = QVariant( value );
  1190     Q_ASSERT( mCurrentFeature );
  1191     mCurrentFeature->
setAttribute( att_it.value().first, var );
  1195 int QgsGmlStreamingParser::readEpsgFromAttribute( 
int &epsgNr, 
const XML_Char **attr )
  1200     if ( strcmp( attr[i], 
"srsName" ) == 0 )
  1202       QString epsgString( attr[i + 1] );
  1203       QString epsgNrString;
  1204       bool bIsUrn = 
false;
  1205       if ( epsgString.startsWith( QLatin1String( 
"http" ) ) ) 
  1207         epsgNrString = epsgString.section( 
'#', 1, 1 );
  1210       else if ( epsgString.startsWith( QLatin1String( 
"urn:ogc:def:crs:EPSG:" ) ) ||
  1211                 epsgString.startsWith( QLatin1String( 
"urn:x-ogc:def:crs:EPSG:" ) ) )
  1214         epsgNrString = epsgString.split( 
':' ).last();
  1218         epsgNrString = epsgString.section( 
':', 1, 1 );
  1221       int eNr = epsgNrString.toInt( &conversionOk );
  1222       if ( !conversionOk )
  1227       mSrsName = epsgString;
  1235           mInvertAxisOrientation = !mInvertAxisOrientationRequest;
  1246 QString QgsGmlStreamingParser::readAttribute( 
const QString &attributeName, 
const XML_Char **attr )
 const  1251     if ( attributeName.compare( attr[i] ) == 0 )
  1253       return QString::fromUtf8( attr[i + 1] );
  1260 bool QgsGmlStreamingParser::createBBoxFromCoordinateString( 
QgsRectangle &r, 
const QString &coordString )
 const  1262   QList<QgsPointXY> points;
  1263   if ( pointsFromCoordinateString( points, coordString ) != 0 )
  1268   if ( points.size() < 2 )
  1273   r.
set( points[0], points[1] );
  1278 int QgsGmlStreamingParser::pointsFromCoordinateString( QList<QgsPointXY> &points, 
const QString &coordString )
 const  1281   QStringList tuples = coordString.split( mTupleSeparator, QString::SkipEmptyParts );
  1282   QStringList tuples_coordinates;
  1284   bool conversionSuccess;
  1286   QStringList::const_iterator tupleIterator;
  1287   for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
  1289     tuples_coordinates = tupleIterator->split( mCoordinateSeparator, QString::SkipEmptyParts );
  1290     if ( tuples_coordinates.size() < 2 )
  1294     x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
  1295     if ( !conversionSuccess )
  1299     y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
  1300     if ( !conversionSuccess )
  1309 int QgsGmlStreamingParser::pointsFromPosListString( QList<QgsPointXY> &points, 
const QString &coordString, 
int dimension )
 const  1312   QStringList coordinates = coordString.split( 
' ', QString::SkipEmptyParts );
  1314   if ( coordinates.size() % dimension != 0 )
  1319   int ncoor = coordinates.size() / dimension;
  1320   for ( 
int i = 0; i < ncoor; i++ )
  1322     bool conversionSuccess;
  1323     double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
  1324     if ( !conversionSuccess )
  1328     double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
  1329     if ( !conversionSuccess )
  1338 int QgsGmlStreamingParser::pointsFromString( QList<QgsPointXY> &points, 
const QString &coordString )
 const  1340   if ( mCoorMode == QgsGmlStreamingParser::Coordinate )
  1342     return pointsFromCoordinateString( points, coordString );
  1344   else if ( mCoorMode == QgsGmlStreamingParser::PosList )
  1346     return pointsFromPosListString( points, coordString, mDimension ? mDimension : 2 );
  1351 int QgsGmlStreamingParser::getPointWKB( 
QgsWkbPtr &wkbPtr, 
const QgsPointXY &point )
 const  1353   int wkbSize = 1 + 
sizeof( int ) + 2 * 
sizeof( 
double );
  1354   wkbPtr = 
QgsWkbPtr( 
new unsigned char[wkbSize], wkbSize );
  1362 int QgsGmlStreamingParser::getLineWKB( 
QgsWkbPtr &wkbPtr, 
const QList<QgsPointXY> &lineCoordinates )
 const  1364   int wkbSize = 1 + 2 * 
sizeof( int ) + lineCoordinates.size() * 2 * 
sizeof( double );
  1365   wkbPtr = 
QgsWkbPtr( 
new unsigned char[wkbSize], wkbSize );
  1371   QList<QgsPointXY>::const_iterator iter;
  1372   for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
  1374     fillPtr << iter->x() << iter->y();
  1380 int QgsGmlStreamingParser::getRingWKB( 
QgsWkbPtr &wkbPtr, 
const QList<QgsPointXY> &ringCoordinates )
 const  1382   int wkbSize = 
sizeof( int ) + ringCoordinates.size() * 2 * 
sizeof( double );
  1383   wkbPtr = 
QgsWkbPtr( 
new unsigned char[wkbSize], wkbSize );
  1387   fillPtr << ringCoordinates.
size();
  1389   QList<QgsPointXY>::const_iterator iter;
  1390   for ( iter = ringCoordinates.constBegin(); iter != ringCoordinates.constEnd(); ++iter )
  1392     fillPtr << iter->x() << iter->y();
  1398 int QgsGmlStreamingParser::createMultiLineFromFragments()
  1400   int size = 1 + 2 * 
sizeof( int ) + totalWKBFragmentSize();
  1401   mCurrentWKB = 
QgsWkbPtr( 
new unsigned char[size], size );
  1408   QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
  1409   for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
  1411     memcpy( wkbPtr, *wkbIt, wkbIt->
size() );
  1412     wkbPtr += wkbIt->
size();
  1416   mCurrentWKBFragments.clear();
  1421 int QgsGmlStreamingParser::createMultiPointFromFragments()
  1423   int size = 1 + 2 * 
sizeof( int ) + totalWKBFragmentSize();
  1424   mCurrentWKB = 
QgsWkbPtr( 
new unsigned char[size], size );
  1429   QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
  1430   for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
  1432     memcpy( wkbPtr, *wkbIt, wkbIt->
size() );
  1433     wkbPtr += wkbIt->
size();
  1437   mCurrentWKBFragments.clear();
  1443 int QgsGmlStreamingParser::createPolygonFromFragments()
  1445   int size = 1 + 2 * 
sizeof( int ) + totalWKBFragmentSize();
  1446   mCurrentWKB = 
QgsWkbPtr( 
new unsigned char[size], size );
  1451   QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
  1452   for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
  1454     memcpy( wkbPtr, *wkbIt, wkbIt->
size() );
  1455     wkbPtr += wkbIt->
size();
  1459   mCurrentWKBFragments.clear();
  1464 int QgsGmlStreamingParser::createMultiPolygonFromFragments()
  1467   size += 1 + 2 * 
sizeof( int );
  1468   size += totalWKBFragmentSize();
  1469   size += mCurrentWKBFragments.size() * ( 1 + 2 * 
sizeof( int ) ); 
  1471   mCurrentWKB = 
QgsWkbPtr( 
new unsigned char[size], size );
  1477   QList< QList<QgsWkbPtr> >::const_iterator outerWkbIt = mCurrentWKBFragments.constBegin();
  1479   for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt )
  1484     QList<QgsWkbPtr>::const_iterator innerWkbIt = outerWkbIt->constBegin();
  1485     for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt )
  1487       memcpy( wkbPtr, *innerWkbIt, innerWkbIt->
size() );
  1488       wkbPtr += innerWkbIt->
size();
  1489       delete[] *innerWkbIt;
  1493   mCurrentWKBFragments.clear();
  1498 int QgsGmlStreamingParser::totalWKBFragmentSize()
 const  1501   Q_FOREACH ( 
const QList<QgsWkbPtr> &list, mCurrentWKBFragments )
 
int getEPSGCode() const
Returns the EPSG code, or 0 if unknown. 
 
A rectangle specified with double values. 
 
int size() const
Returns number of items. 
 
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min. 
 
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name. 
 
AxisOrientationLogic
Axis orientation logic. 
 
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
 
void setXMaximum(double x)
Set the maximum x value. 
 
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length...
 
int numberReturned() const
Returns WFS 2.0 "numberReturned" or WFS 1.1 "numberOfFeatures" attribute, or -1 if invalid/not found...
 
Handles storage of information regarding WKB types and their properties. 
 
A class to represent a 2D point. 
 
std::unique_ptr< std::remove_pointer< OGRGeometryH >::type, OGRGeometryDeleter > ogr_geometry_unique_ptr
Scoped OGR geometry. 
 
int numberMatched() const
Returns WFS 2.0 "numberMatched" attribute, or -1 if invalid/not found. 
 
Container of fields for a vector layer. 
 
A geometry is the spatial representation of a feature. 
 
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes. 
 
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index. 
 
void dataReadProgress(int progress)
 
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
 
bool hasGeometry() const
Returns true if the feature has an associated geometry. 
 
static endian_t endian()
Returns whether this machine uses big or little endian. 
 
#define LOCALNAME_EQUALS(string_constant)
 
void totalStepsUpdate(int totalSteps)
 
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1) 
 
const QString GML_NAMESPACE
 
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle. 
 
Type
The WKB type describes the number of dimensions a geometry has. 
 
void dataProgressAndSteps(int progress, int totalSteps)
Also emit signal with progress and totalSteps together (this is better for the status message) ...
 
bool isEmpty() const
Returns true if the rectangle is empty. 
 
QgsGml(const QString &typeName, const QString &geometryAttribute, const QgsFields &fields)
 
void setYMinimum(double y)
Set the minimum y value. 
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary). 
 
QgsGeometry geometry() const
Returns the geometry associated with this feature. 
 
Honour EPSG axis order only if srsName is of the form urn:ogc:def:crs:EPSG: *. 
 
QVector< QgsGmlFeaturePtrGmlIdPair > getAndStealReadyFeatures()
Returns the list of features that have been completely parsed. 
 
QPair< QgsFeature *, QString > QgsGmlFeaturePtrGmlIdPair
 
int getFeatures(const QString &uri, QgsWkbTypes::Type *wkbType, QgsRectangle *extent=nullptr, const QString &userName=QString(), const QString &password=QString(), const QString &authcfg=QString())
Does the Http GET request to the wfs server Supports only UTF-8, UTF-16, ISO-8859-1, ISO-8859-1 XML encodings. 
 
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
 
static QgsAuthManager * authManager()
Returns the application's authentication manager instance. 
 
void setValid(bool validity)
Sets the validity of the feature. 
 
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread. 
 
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string. 
 
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config. 
 
void setYMaximum(double y)
Set the maximum y value. 
 
bool processData(const QByteArray &data, bool atEnd, QString &errorMsg)
Process a new chunk of data. 
 
QgsRectangle boundingBox() const
Returns the bounding box of the geometry. 
 
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS. 
 
This class represents a coordinate reference system (CRS). 
 
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry. 
 
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()). 
 
QgsGmlStreamingParser(const QString &typeName, const QString &geometryAttribute, const QgsFields &fields, AxisOrientationLogic axisOrientationLogic=Honour_EPSG_if_urn, bool invertAxisOrientation=false)
Constructor. 
 
QgsCoordinateReferenceSystem crs() const
Returns features spatial reference system. 
 
bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkReply with an authentication config (used to skip known SSL errors...
 
void set(const QgsPointXY &p1, const QgsPointXY &p2)
Sets the rectangle from two QgsPoints. 
 
void setXMinimum(double x)
Set the minimum x value. 
 
QgsWkbTypes::Type wkbType() const
Returns the geometry type. 
 
bool isValid() const
Returns whether this CRS is correctly initialized and usable.