28 #include <QNetworkRequest>
29 #include <QNetworkReply>
30 #include <QProgressDialog>
40 static const char *
GML_NAMESPACE =
"http://www.opengis.net/gml";
45 const QString &geometryAttribute,
47 : mParser(
typeName, geometryAttribute, fields )
51 int index = mTypeName.indexOf(
':' );
52 if ( index != -1 && index < mTypeName.length() )
54 mTypeName = mTypeName.mid( index + 1 );
63 QNetworkRequest request( uri );
66 if ( !authcfg.isEmpty() )
71 tr(
"GML Getfeature network request update failed for authcfg %1" ).arg( authcfg ),
78 else if ( !userName.isNull() || !password.isNull() )
80 request.setRawHeader(
"Authorization",
"Basic " + QStringLiteral(
"%1:%2" ).arg( userName, password ).toLatin1().toBase64() );
84 if ( !authcfg.isEmpty() )
90 tr(
"GML Getfeature network reply update failed for authcfg %1" ).arg( authcfg ),
98 connect( reply, &QNetworkReply::finished,
this, &QgsGml::setFinished );
99 connect( reply, &QNetworkReply::downloadProgress,
this, &QgsGml::handleProgressEvent );
102 QProgressDialog *progressDialog =
nullptr;
103 QWidget *mainWindow =
nullptr;
104 QWidgetList topLevelWidgets = qApp->topLevelWidgets();
105 for ( QWidgetList::const_iterator it = topLevelWidgets.constBegin(); it != topLevelWidgets.constEnd(); ++it )
107 if ( ( *it )->objectName() == QLatin1String(
"QgisApp" ) )
115 progressDialog =
new QProgressDialog( tr(
"Loading GML data\n%1" ).arg( mTypeName ), tr(
"Abort" ), 0, 0, mainWindow );
116 progressDialog->setWindowModality( Qt::ApplicationModal );
119 connect( progressDialog, &QProgressDialog::canceled,
this, &QgsGml::setFinished );
120 progressDialog->show();
130 QByteArray readData = reply->readAll();
131 if ( !readData.isEmpty() )
134 if ( !mParser.
processData( readData, atEnd, errorMsg ) )
138 QCoreApplication::processEvents();
141 fillMapsFromParser();
143 QNetworkReply::NetworkError replyError = reply->error();
144 QString replyErrorString = reply->errorString();
147 delete progressDialog;
152 tr(
"GML Getfeature network request failed with error: %1" ).arg( replyErrorString ),
166 calculateExtentFromFeatures();
181 if ( !mParser.
processData( data,
true , errorMsg ) )
184 fillMapsFromParser();
194 void QgsGml::fillMapsFromParser()
197 const auto constFeatures = features;
201 const QString &gmlId = featPair.second;
202 mFeatures.insert( feat->
id(), feat );
203 if ( !gmlId.isEmpty() )
205 mIdMap.insert( feat->
id(), gmlId );
210 void QgsGml::setFinished()
215 void QgsGml::handleProgressEvent( qint64 progress, qint64 totalSteps )
217 if ( totalSteps < 0 )
227 void QgsGml::calculateExtentFromFeatures()
229 if ( mFeatures.empty() )
236 bool bboxInitialized =
false;
238 for (
int i = 0; i < mFeatures.size(); ++i )
240 currentFeature = mFeatures[i];
241 if ( !currentFeature )
245 currentGeometry = currentFeature->
geometry();
246 if ( !currentGeometry.
isNull() )
248 if ( !bboxInitialized )
251 bboxInitialized =
true;
276 const QString &geometryAttribute,
279 bool invertAxisOrientation )
281 , mTypeNameBA( mTypeName.toUtf8() )
282 , mTypeNamePtr( mTypeNameBA.constData() )
283 , mTypeNameUTF8Len( strlen( mTypeNamePtr ) )
285 , mGeometryAttribute( geometryAttribute )
286 , mGeometryAttributeBA( geometryAttribute.toUtf8() )
287 , mGeometryAttributePtr( mGeometryAttributeBA.constData() )
288 , mGeometryAttributeUTF8Len( strlen( mGeometryAttributePtr ) )
290 , mIsException( false )
291 , mTruncatedResponse( false )
293 , mFeatureTupleDepth( 0 )
295 , mCurrentWKB( nullptr, 0 )
296 , mBoundedByNullFound( false )
298 , mCoorMode( Coordinate )
300 , mAxisOrientationLogic( axisOrientationLogic )
301 , mInvertAxisOrientationRequest( invertAxisOrientation )
302 , mInvertAxisOrientation( invertAxisOrientation )
303 , mNumberReturned( -1 )
304 , mNumberMatched( -1 )
305 , mFoundUnhandledGeometryElement( false )
307 mThematicAttributes.clear();
308 for (
int i = 0; i < fields.
size(); i++ )
310 mThematicAttributes.insert( fields.
at( i ).
name(), qMakePair( i, fields.
at( i ) ) );
315 int index = mTypeName.indexOf(
':' );
316 if ( index != -1 && index < mTypeName.length() )
318 mTypeName = mTypeName.mid( index + 1 );
319 mTypeNameBA = mTypeName.toUtf8();
320 mTypeNamePtr = mTypeNameBA.constData();
321 mTypeNameUTF8Len = strlen( mTypeNamePtr );
325 XML_SetUserData( mParser,
this );
326 XML_SetElementHandler( mParser, QgsGmlStreamingParser::start, QgsGmlStreamingParser::end );
327 XML_SetCharacterDataHandler( mParser, QgsGmlStreamingParser::chars );
330 static QString stripNS(
const QString &
string )
332 int index =
string.indexOf(
':' );
333 if ( index != -1 && index <
string.length() )
335 return string.mid( index + 1 );
342 const QMap< QString, QPair<QString, QString> > &mapFieldNameToSrcLayerNameFieldName,
344 bool invertAxisOrientation )
345 : mLayerProperties( layerProperties )
346 , mTypeNameUTF8Len( 0 )
348 , mGeometryAttributeUTF8Len( 0 )
350 , mIsException( false )
351 , mTruncatedResponse( false )
353 , mFeatureTupleDepth( 0 )
355 , mCurrentWKB( nullptr, 0 )
356 , mBoundedByNullFound( false )
358 , mCoorMode( Coordinate )
360 , mAxisOrientationLogic( axisOrientationLogic )
361 , mInvertAxisOrientationRequest( invertAxisOrientation )
362 , mInvertAxisOrientation( invertAxisOrientation )
363 , mNumberReturned( -1 )
364 , mNumberMatched( -1 )
365 , mFoundUnhandledGeometryElement( false )
367 mThematicAttributes.clear();
368 for (
int i = 0; i < fields.
size(); i++ )
370 QMap< QString, QPair<QString, QString> >::const_iterator att_it = mapFieldNameToSrcLayerNameFieldName.constFind( fields.
at( i ).
name() );
371 if ( att_it != mapFieldNameToSrcLayerNameFieldName.constEnd() )
373 if ( mLayerProperties.size() == 1 )
374 mThematicAttributes.insert( att_it.value().second, qMakePair( i, fields.
at( i ) ) );
376 mThematicAttributes.insert( stripNS( att_it.value().first ) +
"|" + att_it.value().second, qMakePair( i, fields.
at( i ) ) );
379 bool alreadyFoundGeometry =
false;
380 for (
int i = 0; i < mLayerProperties.size(); i++ )
383 if ( !mLayerProperties[i].mGeometryAttribute.isEmpty() )
385 if ( alreadyFoundGeometry )
387 QgsDebugMsg( QStringLiteral(
"Will ignore geometry field %1 from typename %2" ).
388 arg( mLayerProperties[i].mGeometryAttribute, mLayerProperties[i].mName ) );
389 mLayerProperties[i].mGeometryAttribute.clear();
391 alreadyFoundGeometry =
true;
393 mMapTypeNameToProperties.insert( stripNS( mLayerProperties[i].mName ), mLayerProperties[i] );
396 if ( mLayerProperties.size() == 1 )
398 mTypeName = mLayerProperties[0].mName;
399 mGeometryAttribute = mLayerProperties[0].mGeometryAttribute;
400 mGeometryAttributeBA = mGeometryAttribute.toUtf8();
401 mGeometryAttributePtr = mGeometryAttributeBA.constData();
402 mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
403 int index = mTypeName.indexOf(
':' );
404 if ( index != -1 && index < mTypeName.length() )
406 mTypeName = mTypeName.mid( index + 1 );
408 mTypeNameBA = mTypeName.toUtf8();
409 mTypeNamePtr = mTypeNameBA.constData();
410 mTypeNameUTF8Len = strlen( mTypeNamePtr );
416 XML_SetUserData( mParser,
this );
417 XML_SetElementHandler( mParser, QgsGmlStreamingParser::start, QgsGmlStreamingParser::end );
418 XML_SetCharacterDataHandler( mParser, QgsGmlStreamingParser::chars );
424 XML_ParserFree( mParser );
427 const auto constMFeatureList = mFeatureList;
430 delete featPair.first;
433 delete mCurrentFeature;
449 if ( XML_Parse( mParser, data.data(), data.size(), atEnd ) == 0 )
451 XML_Error errorCode = XML_GetErrorCode( mParser );
452 errorMsg = QObject::tr(
"Error: %1 on line %2, column %3" )
453 .arg( XML_ErrorString( errorCode ) )
454 .arg( XML_GetCurrentLineNumber( mParser ) )
455 .arg( XML_GetCurrentColumnNumber( mParser ) );
465 QVector<QgsGmlFeaturePtrGmlIdPair> ret = mFeatureList;
466 mFeatureList.clear();
470 #define LOCALNAME_EQUALS(string_constant) \
471 ( localNameLen == static_cast<int>(strlen( string_constant )) && memcmp(pszLocalName, string_constant, localNameLen) == 0 )
473 void QgsGmlStreamingParser::startElement(
const XML_Char *el,
const XML_Char **attr )
475 const int elLen =
static_cast<int>( strlen( el ) );
477 const char *pszLocalName = ( pszSep ) ? pszSep + 1 : el;
478 const int nsLen = ( pszSep ) ? (
int )( pszSep - el ) : 0;
479 const int localNameLen = ( pszSep ) ? (
int )( elLen - nsLen ) - 1 : elLen;
480 ParseMode parseMode( mParseModeStack.isEmpty() ? None : mParseModeStack.top() );
484 if ( !mGMLNameSpaceURIPtr && pszSep )
498 const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && mGMLNameSpaceURIPtr && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
501 if ( parseMode == Geometry || parseMode == Coordinate || parseMode == PosList ||
502 parseMode == MultiPoint || parseMode == MultiLine || parseMode == MultiPolygon )
504 mGeometryString.append(
"<", 1 );
505 mGeometryString.append( pszLocalName, localNameLen );
506 mGeometryString.append(
" ", 1 );
507 for (
const XML_Char **attrIter = attr; attrIter && *attrIter; attrIter += 2 )
509 mGeometryString.append( attrIter[0] );
510 mGeometryString.append(
"=\"", 2 );
511 mGeometryString.append( attrIter[1] );
512 mGeometryString.append(
"\" ", 2 );
515 mGeometryString.append(
">", 1 );
520 mParseModeStack.push( Coordinate );
521 mCoorMode = QgsGmlStreamingParser::Coordinate;
523 mCoordinateSeparator = readAttribute( QStringLiteral(
"cs" ), attr );
524 if ( mCoordinateSeparator.isEmpty() )
526 mCoordinateSeparator =
',';
528 mTupleSeparator = readAttribute( QStringLiteral(
"ts" ), attr );
529 if ( mTupleSeparator.isEmpty() )
531 mTupleSeparator =
' ';
537 mParseModeStack.push( QgsGmlStreamingParser::PosList );
538 mCoorMode = QgsGmlStreamingParser::PosList;
540 if ( elDimension == 0 )
542 QString srsDimension = readAttribute( QStringLiteral(
"srsDimension" ), attr );
544 int dimension = srsDimension.toInt( &ok );
547 elDimension = dimension;
551 else if ( ( parseMode == Feature || parseMode == FeatureTuple ) &&
553 localNameLen ==
static_cast<int>( mGeometryAttributeUTF8Len ) &&
554 memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
556 mParseModeStack.push( QgsGmlStreamingParser::Geometry );
557 mFoundUnhandledGeometryElement =
false;
558 mGeometryString.clear();
563 mParseModeStack.push( QgsGmlStreamingParser::BoundingBox );
565 mBoundedByNullFound =
false;
567 else if ( parseMode == BoundingBox &&
570 mParseModeStack.push( QgsGmlStreamingParser::Null );
571 mBoundedByNullFound =
true;
573 else if ( parseMode == BoundingBox &&
577 mParseModeStack.push( QgsGmlStreamingParser::Envelope );
579 else if ( parseMode == Envelope &&
582 mParseModeStack.push( QgsGmlStreamingParser::LowerCorner );
585 else if ( parseMode == Envelope &&
588 mParseModeStack.push( QgsGmlStreamingParser::UpperCorner );
591 else if ( parseMode == None && !mTypeNamePtr &&
594 Q_ASSERT( !mCurrentFeature );
595 mCurrentFeature =
new QgsFeature( mFeatureCount );
599 mParseModeStack.push( QgsGmlStreamingParser::Tuple );
600 mCurrentFeatureId.clear();
602 else if ( parseMode == Tuple )
604 QString currentTypename( QString::fromUtf8( pszLocalName, localNameLen ) );
605 QMap< QString, LayerProperties >::const_iterator iter = mMapTypeNameToProperties.constFind( currentTypename );
606 if ( iter != mMapTypeNameToProperties.constEnd() )
608 mFeatureTupleDepth = mParseDepth;
609 mCurrentTypename = currentTypename;
610 mGeometryAttribute.clear();
611 if ( mCurrentWKB.
size() == 0 )
613 mGeometryAttribute = iter.value().mGeometryAttribute;
615 mGeometryAttributeBA = mGeometryAttribute.toUtf8();
616 mGeometryAttributePtr = mGeometryAttributeBA.constData();
617 mGeometryAttributeUTF8Len = strlen( mGeometryAttributePtr );
618 mParseModeStack.push( QgsGmlStreamingParser::FeatureTuple );
620 if ( mGMLNameSpaceURI.isEmpty() )
639 id = readAttribute( mGMLNameSpaceURI +
NS_SEPARATOR +
"id", attr );
640 if ( !mCurrentFeatureId.isEmpty() )
641 mCurrentFeatureId +=
'|';
642 mCurrentFeatureId += id;
645 else if ( parseMode == None &&
646 localNameLen ==
static_cast<int>( mTypeNameUTF8Len ) &&
647 memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 )
649 Q_ASSERT( !mCurrentFeature );
650 mCurrentFeature =
new QgsFeature( mFeatureCount );
654 mParseModeStack.push( QgsGmlStreamingParser::Feature );
655 mCurrentFeatureId = readAttribute( QStringLiteral(
"fid" ), attr );
656 if ( mCurrentFeatureId.isEmpty() )
661 if ( mGMLNameSpaceURI.isEmpty() )
664 if ( !mCurrentFeatureId.isEmpty() )
672 if ( !mCurrentFeatureId.isEmpty() )
680 mCurrentFeatureId = readAttribute( mGMLNameSpaceURI +
NS_SEPARATOR +
"id", attr );
684 else if ( parseMode == BoundingBox && isGMLNS &&
LOCALNAME_EQUALS(
"Box" ) )
697 localNameLen ==
static_cast<int>( strlen(
"Polygon" ) ) && memcmp( pszLocalName,
"Polygon", localNameLen ) == 0 )
700 mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
705 mParseModeStack.push( QgsGmlStreamingParser::MultiPoint );
707 mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
712 mParseModeStack.push( QgsGmlStreamingParser::MultiLine );
714 mCurrentWKBFragments.push_back( QList<QgsWkbPtr>() );
719 mParseModeStack.push( QgsGmlStreamingParser::MultiPolygon );
721 else if ( parseMode == FeatureTuple )
723 QString localName( QString::fromUtf8( pszLocalName, localNameLen ) );
724 if ( mThematicAttributes.contains( mCurrentTypename +
'|' + localName ) )
726 mParseModeStack.push( QgsGmlStreamingParser::AttributeTuple );
727 mAttributeName = mCurrentTypename +
'|' + localName;
731 else if ( parseMode == Feature )
733 QString localName( QString::fromUtf8( pszLocalName, localNameLen ) );
734 if ( mThematicAttributes.contains( localName ) )
736 mParseModeStack.push( QgsGmlStreamingParser::Attribute );
737 mAttributeName = localName;
744 if ( localName.compare( QLatin1String(
"attribute" ), Qt::CaseInsensitive ) == 0 )
746 QString name = readAttribute( QStringLiteral(
"name" ), attr );
747 if ( mThematicAttributes.contains( name ) )
749 QString value = readAttribute( QStringLiteral(
"value" ), attr );
750 setAttribute( name, value );
757 QString
numberReturned = readAttribute( QStringLiteral(
"numberReturned" ), attr );
759 numberReturned = readAttribute( QStringLiteral(
"numberOfFeatures" ), attr );
763 mNumberReturned = -1;
765 QString
numberMatched = readAttribute( QStringLiteral(
"numberMatched" ), attr );
773 mParseModeStack.push( QgsGmlStreamingParser::ExceptionReport );
778 mParseModeStack.push( QgsGmlStreamingParser::ExceptionText );
783 mTruncatedResponse =
true;
785 else if ( !mGeometryString.empty() &&
801 mFoundUnhandledGeometryElement =
true;
804 if ( !mGeometryString.empty() )
807 if ( elDimension == 0 && isGeom )
811 QString srsDimension = readAttribute( QStringLiteral(
"srsDimension" ), attr );
813 int dimension = srsDimension.toInt( &ok );
816 elDimension = dimension;
820 if ( elDimension != 0 || mDimensionStack.isEmpty() )
822 mDimensionStack.push( elDimension );
826 mDimensionStack.push( mDimensionStack.back() );
829 if ( mEpsg == 0 && isGeom )
831 if ( readEpsgFromAttribute( mEpsg, attr ) != 0 )
833 QgsDebugMsg( QStringLiteral(
"error, could not get epsg id" ) );
837 QgsDebugMsg( QStringLiteral(
"mEpsg = %1" ).arg( mEpsg ) );
844 void QgsGmlStreamingParser::endElement(
const XML_Char *el )
848 const int elLen =
static_cast<int>( strlen( el ) );
850 const char *pszLocalName = ( pszSep ) ? pszSep + 1 : el;
851 const int nsLen = ( pszSep ) ? (
int )( pszSep - el ) : 0;
852 const int localNameLen = ( pszSep ) ? (
int )( elLen - nsLen ) - 1 : elLen;
853 ParseMode parseMode( mParseModeStack.isEmpty() ? None : mParseModeStack.top() );
855 int lastDimension = mDimensionStack.isEmpty() ? 0 : mDimensionStack.pop();
857 const bool isGMLNS = ( nsLen == mGMLNameSpaceURI.size() && mGMLNameSpaceURIPtr && memcmp( el, mGMLNameSpaceURIPtr, nsLen ) == 0 );
859 if ( parseMode == Coordinate && isGMLNS &&
LOCALNAME_EQUALS(
"coordinates" ) )
861 mParseModeStack.pop();
863 else if ( parseMode == PosList && isGMLNS &&
866 mDimension = lastDimension;
867 mParseModeStack.pop();
869 else if ( parseMode == AttributeTuple &&
870 mCurrentTypename +
'|' + QString::fromUtf8( pszLocalName, localNameLen ) == mAttributeName )
872 mParseModeStack.pop();
874 setAttribute( mAttributeName, mStringCash );
876 else if ( parseMode == Attribute && QString::fromUtf8( pszLocalName, localNameLen ) == mAttributeName )
878 mParseModeStack.pop();
880 setAttribute( mAttributeName, mStringCash );
882 else if ( parseMode == Geometry &&
883 localNameLen ==
static_cast<int>( mGeometryAttributeUTF8Len ) &&
884 memcmp( pszLocalName, mGeometryAttributePtr, localNameLen ) == 0 )
886 mParseModeStack.pop();
887 if ( mFoundUnhandledGeometryElement )
892 const int wkbSize = OGR_G_WkbSize( hGeom.get() );
893 unsigned char *pabyBuffer =
new unsigned char[ wkbSize ];
894 OGR_G_ExportToIsoWkb( hGeom.get(), wkbNDR, pabyBuffer );
896 g.
fromWkb( pabyBuffer, wkbSize );
897 if ( mInvertAxisOrientation )
899 g.
transform( QTransform( 0, 1, 1, 0, 0, 0 ) );
901 Q_ASSERT( mCurrentFeature );
905 mGeometryString.clear();
907 else if ( parseMode == BoundingBox && isGMLNS &&
LOCALNAME_EQUALS(
"boundedBy" ) )
910 if ( mCurrentExtent.
isNull() &&
911 !mBoundedByNullFound &&
912 !createBBoxFromCoordinateString( mCurrentExtent, mStringCash ) )
914 QgsDebugMsg( QStringLiteral(
"creation of bounding box failed" ) );
916 if ( !mCurrentExtent.
isNull() && mLayerExtent.
isNull() &&
917 !mCurrentFeature && mFeatureCount == 0 )
919 mLayerExtent = mCurrentExtent;
923 mParseModeStack.pop();
927 mParseModeStack.pop();
929 else if ( parseMode == Envelope && isGMLNS &&
LOCALNAME_EQUALS(
"Envelope" ) )
931 mParseModeStack.pop();
933 else if ( parseMode == LowerCorner && isGMLNS &&
LOCALNAME_EQUALS(
"lowerCorner" ) )
935 QList<QgsPointXY> points;
936 pointsFromPosListString( points, mStringCash, 2 );
937 if ( points.size() == 1 )
942 mParseModeStack.pop();
944 else if ( parseMode == UpperCorner && isGMLNS &&
LOCALNAME_EQUALS(
"upperCorner" ) )
946 QList<QgsPointXY> points;
947 pointsFromPosListString( points, mStringCash, 2 );
948 if ( points.size() == 1 )
953 mParseModeStack.pop();
955 else if ( parseMode == FeatureTuple && mParseDepth == mFeatureTupleDepth )
957 mParseModeStack.pop();
958 mFeatureTupleDepth = 0;
960 else if ( ( parseMode == Tuple && !mTypeNamePtr &&
962 ( parseMode == Feature &&
963 localNameLen ==
static_cast<int>( mTypeNameUTF8Len ) &&
964 memcmp( pszLocalName, mTypeNamePtr, mTypeNameUTF8Len ) == 0 ) )
966 Q_ASSERT( mCurrentFeature );
969 if ( mCurrentWKB.
size() > 0 )
976 else if ( !mCurrentExtent.
isEmpty() )
985 mCurrentFeature =
nullptr;
987 mParseModeStack.pop();
991 QList<QgsPointXY> pointList;
992 if ( pointsFromString( pointList, mStringCash ) != 0 )
997 if ( pointList.isEmpty() )
1000 if ( parseMode == QgsGmlStreamingParser::Geometry )
1003 if ( getPointWKB( mCurrentWKB, *( pointList.constBegin() ) ) != 0 )
1016 if ( getPointWKB( wkbPtr, *( pointList.constBegin() ) ) != 0 )
1020 if ( !mCurrentWKBFragments.isEmpty() )
1022 mCurrentWKBFragments.last().push_back( wkbPtr );
1026 QgsDebugMsg( QStringLiteral(
"No wkb fragments" ) );
1035 QList<QgsPointXY> pointList;
1036 if ( pointsFromString( pointList, mStringCash ) != 0 )
1040 if ( parseMode == QgsGmlStreamingParser::Geometry )
1042 if ( getLineWKB( mCurrentWKB, pointList ) != 0 )
1055 if ( getLineWKB( wkbPtr, pointList ) != 0 )
1059 if ( !mCurrentWKBFragments.isEmpty() )
1061 mCurrentWKBFragments.last().push_back( wkbPtr );
1065 QgsDebugMsg( QStringLiteral(
"no wkb fragments" ) );
1070 else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) &&
1073 QList<QgsPointXY> pointList;
1074 if ( pointsFromString( pointList, mStringCash ) != 0 )
1080 if ( getRingWKB( wkbPtr, pointList ) != 0 )
1085 if ( !mCurrentWKBFragments.isEmpty() )
1087 mCurrentWKBFragments.last().push_back( wkbPtr );
1092 QgsDebugMsg( QStringLiteral(
"no wkb fragments" ) );
1095 else if ( ( parseMode == Geometry || parseMode == MultiPolygon ) && isGMLNS &&
1103 if ( parseMode == Geometry )
1105 createPolygonFromFragments();
1108 else if ( parseMode == MultiPoint && isGMLNS &&
1112 mParseModeStack.pop();
1113 createMultiPointFromFragments();
1115 else if ( parseMode == MultiLine && isGMLNS &&
1119 mParseModeStack.pop();
1120 createMultiLineFromFragments();
1122 else if ( parseMode == MultiPolygon && isGMLNS &&
1126 mParseModeStack.pop();
1127 createMultiPolygonFromFragments();
1131 mParseModeStack.pop();
1133 else if ( parseMode == ExceptionText &&
LOCALNAME_EQUALS(
"ExceptionText" ) )
1135 mExceptionText = mStringCash;
1136 mParseModeStack.pop();
1139 if ( !mGeometryString.empty() )
1141 mGeometryString.append(
"</", 2 );
1142 mGeometryString.append( pszLocalName, localNameLen );
1143 mGeometryString.append(
">", 1 );
1148 void QgsGmlStreamingParser::characters(
const XML_Char *chars,
int len )
1151 if ( mParseModeStack.isEmpty() )
1156 if ( !mGeometryString.empty() )
1158 mGeometryString.append( chars, len );
1161 QgsGmlStreamingParser::ParseMode parseMode = mParseModeStack.top();
1162 if ( parseMode == QgsGmlStreamingParser::Attribute ||
1163 parseMode == QgsGmlStreamingParser::AttributeTuple ||
1164 parseMode == QgsGmlStreamingParser::Coordinate ||
1165 parseMode == QgsGmlStreamingParser::PosList ||
1166 parseMode == QgsGmlStreamingParser::LowerCorner ||
1167 parseMode == QgsGmlStreamingParser::UpperCorner ||
1168 parseMode == QgsGmlStreamingParser::ExceptionText )
1170 mStringCash.append( QString::fromUtf8( chars, len ) );
1174 void QgsGmlStreamingParser::setAttribute(
const QString &name,
const QString &value )
1177 QMap<QString, QPair<int, QgsField> >::const_iterator att_it = mThematicAttributes.constFind( name );
1178 bool conversionOk =
true;
1179 if ( att_it != mThematicAttributes.constEnd() )
1182 switch ( att_it.value().second.type() )
1184 case QVariant::Double:
1185 var = QVariant( value.toDouble( &conversionOk ) );
1188 var = QVariant( value.toInt( &conversionOk ) );
1190 case QVariant::LongLong:
1191 var = QVariant( value.toLongLong( &conversionOk ) );
1193 case QVariant::DateTime:
1194 var = QVariant( QDateTime::fromString( value, Qt::ISODate ) );
1197 var = QVariant( value );
1200 if ( ! conversionOk )
1204 Q_ASSERT( mCurrentFeature );
1205 mCurrentFeature->
setAttribute( att_it.value().first, var );
1209 int QgsGmlStreamingParser::readEpsgFromAttribute(
int &epsgNr,
const XML_Char **attr )
1214 if ( strcmp( attr[i],
"srsName" ) == 0 )
1216 QString epsgString( attr[i + 1] );
1217 QString epsgNrString;
1218 bool bIsUrn =
false;
1219 if ( epsgString.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
1221 epsgNrString = epsgString.section(
'#', 1, 1 );
1224 else if ( epsgString.startsWith( QLatin1String(
"urn:ogc:def:crs:EPSG:" ) ) ||
1225 epsgString.startsWith( QLatin1String(
"urn:x-ogc:def:crs:EPSG:" ) ) )
1228 epsgNrString = epsgString.split(
':' ).last();
1230 else if ( epsgString.startsWith( QLatin1String(
"http://www.opengis.net/def/crs/EPSG/" ) ) )
1233 epsgNrString = epsgString.split(
'/' ).last();
1237 epsgNrString = epsgString.section(
':', 1, 1 );
1240 int eNr = epsgNrString.toInt( &conversionOk );
1241 if ( !conversionOk )
1246 mSrsName = epsgString;
1254 mInvertAxisOrientation = !mInvertAxisOrientationRequest;
1265 QString QgsGmlStreamingParser::readAttribute(
const QString &attributeName,
const XML_Char **attr )
const
1270 if ( attributeName.compare( attr[i] ) == 0 )
1272 return QString::fromUtf8( attr[i + 1] );
1279 bool QgsGmlStreamingParser::createBBoxFromCoordinateString(
QgsRectangle &r,
const QString &coordString )
const
1281 QList<QgsPointXY> points;
1282 if ( pointsFromCoordinateString( points, coordString ) != 0 )
1287 if ( points.size() < 2 )
1292 r.
set( points[0], points[1] );
1297 int QgsGmlStreamingParser::pointsFromCoordinateString( QList<QgsPointXY> &points,
const QString &coordString )
const
1300 QStringList tuples = coordString.split( mTupleSeparator, QString::SkipEmptyParts );
1301 QStringList tuples_coordinates;
1303 bool conversionSuccess;
1305 QStringList::const_iterator tupleIterator;
1306 for ( tupleIterator = tuples.constBegin(); tupleIterator != tuples.constEnd(); ++tupleIterator )
1308 tuples_coordinates = tupleIterator->split( mCoordinateSeparator, QString::SkipEmptyParts );
1309 if ( tuples_coordinates.size() < 2 )
1313 x = tuples_coordinates.at( 0 ).toDouble( &conversionSuccess );
1314 if ( !conversionSuccess )
1318 y = tuples_coordinates.at( 1 ).toDouble( &conversionSuccess );
1319 if ( !conversionSuccess )
1328 int QgsGmlStreamingParser::pointsFromPosListString( QList<QgsPointXY> &points,
const QString &coordString,
int dimension )
const
1331 QStringList coordinates = coordString.split(
' ', QString::SkipEmptyParts );
1333 if ( coordinates.size() % dimension != 0 )
1335 QgsDebugMsg( QStringLiteral(
"Wrong number of coordinates" ) );
1338 int ncoor = coordinates.size() / dimension;
1339 for (
int i = 0; i < ncoor; i++ )
1341 bool conversionSuccess;
1342 double x = coordinates.value( i * dimension ).toDouble( &conversionSuccess );
1343 if ( !conversionSuccess )
1347 double y = coordinates.value( i * dimension + 1 ).toDouble( &conversionSuccess );
1348 if ( !conversionSuccess )
1357 int QgsGmlStreamingParser::pointsFromString( QList<QgsPointXY> &points,
const QString &coordString )
const
1359 if ( mCoorMode == QgsGmlStreamingParser::Coordinate )
1361 return pointsFromCoordinateString( points, coordString );
1363 else if ( mCoorMode == QgsGmlStreamingParser::PosList )
1365 return pointsFromPosListString( points, coordString, mDimension ? mDimension : 2 );
1370 int QgsGmlStreamingParser::getPointWKB(
QgsWkbPtr &wkbPtr,
const QgsPointXY &point )
const
1372 int wkbSize = 1 +
sizeof( int ) + 2 *
sizeof(
double );
1373 wkbPtr =
QgsWkbPtr(
new unsigned char[wkbSize], wkbSize );
1381 int QgsGmlStreamingParser::getLineWKB(
QgsWkbPtr &wkbPtr,
const QList<QgsPointXY> &lineCoordinates )
const
1383 int wkbSize = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
1384 wkbPtr =
QgsWkbPtr(
new unsigned char[wkbSize], wkbSize );
1390 QList<QgsPointXY>::const_iterator iter;
1391 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
1393 fillPtr << iter->x() << iter->y();
1399 int QgsGmlStreamingParser::getRingWKB(
QgsWkbPtr &wkbPtr,
const QList<QgsPointXY> &ringCoordinates )
const
1401 int wkbSize =
sizeof( int ) + ringCoordinates.size() * 2 *
sizeof( double );
1402 wkbPtr =
QgsWkbPtr(
new unsigned char[wkbSize], wkbSize );
1406 fillPtr << ringCoordinates.size();
1408 QList<QgsPointXY>::const_iterator iter;
1409 for ( iter = ringCoordinates.constBegin(); iter != ringCoordinates.constEnd(); ++iter )
1411 fillPtr << iter->x() << iter->y();
1417 int QgsGmlStreamingParser::createMultiLineFromFragments()
1419 int size = 1 + 2 *
sizeof( int ) + totalWKBFragmentSize();
1420 mCurrentWKB =
QgsWkbPtr(
new unsigned char[size], size );
1427 QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1428 for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1430 memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1431 wkbPtr += wkbIt->
size();
1435 mCurrentWKBFragments.clear();
1440 int QgsGmlStreamingParser::createMultiPointFromFragments()
1442 int size = 1 + 2 *
sizeof( int ) + totalWKBFragmentSize();
1443 mCurrentWKB =
QgsWkbPtr(
new unsigned char[size], size );
1448 QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1449 for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1451 memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1452 wkbPtr += wkbIt->
size();
1456 mCurrentWKBFragments.clear();
1462 int QgsGmlStreamingParser::createPolygonFromFragments()
1464 int size = 1 + 2 *
sizeof( int ) + totalWKBFragmentSize();
1465 mCurrentWKB =
QgsWkbPtr(
new unsigned char[size], size );
1470 QList<QgsWkbPtr>::const_iterator wkbIt = mCurrentWKBFragments.constBegin()->constBegin();
1471 for ( ; wkbIt != mCurrentWKBFragments.constBegin()->constEnd(); ++wkbIt )
1473 memcpy( wkbPtr, *wkbIt, wkbIt->size() );
1474 wkbPtr += wkbIt->
size();
1478 mCurrentWKBFragments.clear();
1483 int QgsGmlStreamingParser::createMultiPolygonFromFragments()
1486 size += 1 + 2 *
sizeof( int );
1487 size += totalWKBFragmentSize();
1488 size += mCurrentWKBFragments.size() * ( 1 + 2 *
sizeof( int ) );
1490 mCurrentWKB =
QgsWkbPtr(
new unsigned char[size], size );
1496 QList< QList<QgsWkbPtr> >::const_iterator outerWkbIt = mCurrentWKBFragments.constBegin();
1498 for ( ; outerWkbIt != mCurrentWKBFragments.constEnd(); ++outerWkbIt )
1503 QList<QgsWkbPtr>::const_iterator innerWkbIt = outerWkbIt->constBegin();
1504 for ( ; innerWkbIt != outerWkbIt->constEnd(); ++innerWkbIt )
1506 memcpy( wkbPtr, *innerWkbIt, innerWkbIt->size() );
1507 wkbPtr += innerWkbIt->
size();
1508 delete[] *innerWkbIt;
1512 mCurrentWKBFragments.clear();
1517 int QgsGmlStreamingParser::totalWKBFragmentSize()
const
1520 const auto constMCurrentWKBFragments = mCurrentWKBFragments;
1521 for (
const QList<QgsWkbPtr> &list : constMCurrentWKBFragments )
1523 const auto constList = list;