24 #include <QNetworkRequest> 25 #include <QNetworkReply> 26 #include <QProgressDialog> 48 for (
int i = 0; i < mFields.
size(); i++ )
50 if ( mFields[i].name() == name )
return i;
58 , mCurrentFeature( nullptr )
61 , mSkipLevel( std::numeric_limits<int>::
max() )
63 mGeometryTypes <<
"Point" <<
"MultiPoint" 64 <<
"LineString" <<
"MultiLineString" 65 <<
"Polygon" <<
"MultiPolygon";
73 QString QgsGmlSchema::readAttribute(
const QString& attributeName,
const XML_Char** attr )
const 78 if ( attributeName.
compare( attr[i] ) == 0 )
93 if ( !dom.
setContent( xml,
false, &errorMsg, &errorLine, &errorColumn ) )
105 Q_FOREACH (
const QDomElement& elementElement, elementElements )
110 QString gmlBaseType = xsdComplexTypeGmlBaseType( docElem, stripNS( type ) );
117 if ( gmlBaseType ==
"AbstractFeatureType" )
121 xsdFeatureClass( docElem, stripNS( type ), featureClass );
122 mFeatureClassMap.
insert( name, featureClass );
133 QDomElement complexTypeElement = domElement( element,
"complexType",
"name", typeName );
134 if ( complexTypeElement.
isNull() )
return false;
137 QDomElement extrest = domElement( complexTypeElement,
"complexContent.extension" );
140 extrest = domElement( complexTypeElement,
"complexContent.restriction" );
142 if ( extrest.
isNull() )
return false;
145 if ( extrestName ==
"gml:AbstractFeatureType" )
154 if ( !xsdFeatureClass( element, stripNS( extrestName ), featureClass ) )
return false;
159 Q_FOREACH (
const QString& geom, mGeometryTypes )
161 geometryPropertyTypes << geom +
"PropertyType";
165 geometryAliases <<
"location" <<
"centerOf" <<
"position" <<
"extentOf" 166 <<
"coverage" <<
"edgeOf" <<
"centerLineOf" <<
"multiLocation" 167 <<
"multiCenterOf" <<
"multiPosition" <<
"multiCenterLineOf" 168 <<
"multiEdgeOf" <<
"multiCoverage" <<
"multiExtentOf";
172 Q_FOREACH (
const QDomElement& sequenceElement, sequenceElements )
179 if ( !ref.isEmpty() )
181 if ( ref.startsWith(
"gml:" ) )
183 if ( geometryAliases.
contains( stripNS( ref ) ) )
195 QgsDebugMsg(
QString(
"field %1.%2 is referencing %3 - not supported" ).arg( typeName, fieldName ) );
210 QDomElement sequenceElementRestriction = domElement( sequenceElement,
"simpleType.restriction" );
211 fieldTypeName = stripNS( sequenceElementRestriction.
attribute(
"base" ) );
214 QVariant::Type fieldType = QVariant::String;
221 if ( geometryPropertyTypes.
contains( fieldTypeName ) )
228 if ( fieldTypeName ==
"decimal" )
230 fieldType = QVariant::Double;
232 else if ( fieldTypeName ==
"integer" )
234 fieldType = QVariant::Int;
238 QgsField field( fieldName, fieldType, fieldTypeName );
248 QDomElement complexTypeElement = domElement( element,
"complexType",
"name", name );
249 if ( complexTypeElement.
isNull() )
return "";
251 QDomElement extrest = domElement( complexTypeElement,
"complexContent.extension" );
254 extrest = domElement( complexTypeElement,
"complexContent.restriction" );
256 if ( extrest.
isNull() )
return "";
262 return stripNS( extrestName );
265 return xsdComplexTypeGmlBaseType( element, stripNS( extrestName ) );
278 if ( names.
isEmpty() )
return list;
289 if ( tagName == name )
297 list.
append( domElements( el, names.
join(
"." ) ) );
309 return domElements( element, path ).
value( 0 );
328 return domElements( list, attr, attrVal ).
value( 0 );
336 XML_Parser p = XML_ParserCreateNS(
nullptr,
NS_SEPARATOR );
337 XML_SetUserData( p,
this );
338 XML_SetElementHandler( p, QgsGmlSchema::start, QgsGmlSchema::end );
339 XML_SetCharacterDataHandler( p, QgsGmlSchema::chars );
341 int res = XML_Parse( p, data.
constData(), data.
size(), atEnd );
345 QString err =
QString( XML_ErrorString( XML_GetErrorCode( p ) ) );
347 mError =
QgsError( err,
"GML schema" );
348 mError.
append(
tr(
"Cannot guess schema" ) );
354 void QgsGmlSchema::startElement(
const XML_Char* el,
const XML_Char** attr )
360 QgsDebugMsgLevel(
QString(
"-> %1 %2 %3" ).arg( mLevel ).arg( elementName, mLevel >= mSkipLevel ?
"skip" :
"" ), 5 );
362 if ( mLevel >= mSkipLevel )
368 mParsePathStack.
append( elementName );
376 ParseMode parseMode = modeStackTop();
379 if ( ns == GML_NAMESPACE && localName ==
"boundedBy" )
382 mSkipLevel = mLevel + 1;
384 else if ( localName.
compare(
"featureMembers", Qt::CaseInsensitive ) == 0 )
386 mParseModeStack.
push( QgsGmlSchema::featureMembers );
393 else if ( localName.
endsWith(
"member", Qt::CaseInsensitive ) )
395 mParseModeStack.
push( QgsGmlSchema::featureMember );
398 else if ( elementName.
endsWith(
"_layer" ) )
406 else if ( elementName.
endsWith(
"_feature" )
407 || parseMode == QgsGmlSchema::featureMember
408 || parseMode == QgsGmlSchema::featureMembers
409 || localName.
compare(
"feature", Qt::CaseInsensitive ) == 0 )
412 if ( mFeatureClassMap.
count( localName ) == 0 )
416 mCurrentFeatureName = localName;
417 mParseModeStack.
push( QgsGmlSchema::feature );
419 else if ( parseMode == QgsGmlSchema::attribute && ns == GML_NAMESPACE && mGeometryTypes.
indexOf( localName ) >= 0 )
423 if ( geometryAttributes.
count( mAttributeName ) == 0 )
425 geometryAttributes.
append( mAttributeName );
427 mSkipLevel = mLevel + 1;
429 else if ( parseMode == QgsGmlSchema::feature )
438 QString name = readAttribute(
"name", attr );
440 if ( localName.
compare(
"attribute", Qt::CaseInsensitive ) == 0
443 QString value = readAttribute(
"value", attr );
445 addAttribute( name, value );
449 mAttributeName = localName;
450 mParseModeStack.
push( QgsGmlSchema::attribute );
456 void QgsGmlSchema::endElement(
const XML_Char* el )
461 if ( mLevel >= mSkipLevel )
477 QgsGmlSchema::ParseMode parseMode = modeStackTop();
479 if ( parseMode == QgsGmlSchema::featureMembers )
483 else if ( parseMode == QgsGmlSchema::attribute && localName == mAttributeName )
489 if ( mFeatureClassMap[mCurrentFeatureName].
geometryAttributes().count( mAttributeName ) == 0 )
491 addAttribute( mAttributeName, mStringCash );
494 else if ( ns == GML_NAMESPACE && localName ==
"boundedBy" )
498 else if ( localName.
endsWith(
"member", Qt::CaseInsensitive ) )
506 void QgsGmlSchema::characters(
const XML_Char* chars,
int len )
509 if ( mLevel >= mSkipLevel )
516 if ( modeStackTop() == QgsGmlSchema::attribute )
522 void QgsGmlSchema::addAttribute(
const QString& name,
const QString& value )
527 QVariant::Type type = QVariant::String;
530 type = QVariant::Int;
537 type = QVariant::Double;
543 int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( name );
544 if ( fieldIndex == -1 )
551 QgsField &field = fields[fieldIndex];
553 if (( field.
type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
554 ( field.
type() == QVariant::Double && type == QVariant::String ) )
563 return mFeatureClassMap.
keys();
569 return mFeatureClassMap[typeName].fields();
575 return mFeatureClassMap[typeName].geometryAttributes();
QString & append(QChar ch)
bool guessSchema(const QByteArray &data)
Guess GML schema from data if XSD does not exist.
QString attribute(const QString &name, const QString &defValue) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QDomElement documentElement() const
QString join(const QString &separator) const
double toDouble(bool *ok) const
QString tr(const char *sourceText, const char *disambiguation, int n)
QDomNode nextSibling() const
const QString GML_NAMESPACE
QDomElement toElement() const
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
QList< Key > keys() const
QList< QgsField > & fields()
const char * name() const
int count(const T &value) const
void append(const T &value)
QString fromUtf8(const char *str, int size)
#define QgsDebugMsgLevel(str, level)
QStringList typeNames() const
Get list of dot separated paths to feature classes parsed from GML or XSD.
int toInt(bool *ok, int base) const
const char * constData() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QList< QgsField > fields(const QString &typeName)
Get fields for type/class name parsed from GML or XSD.
Encapsulate a field in an attribute table or data source.
bool contains(QChar ch, Qt::CaseSensitivity cs) const
void setType(QVariant::Type type)
Set variant type.
QDomNode firstChild() const
QgsError is container for error messages (report).
void append(const QString &theMessage, const QString &theTag)
Append new error message.
QString section(QChar sep, int start, int end, QFlags< QString::SectionFlag > flags) const
int indexOf(const QRegExp &rx, int from) const
iterator insert(const Key &key, const T &value)
QStringList & geometryAttributes()
int compare(const QString &other) const
int count(const Key &key) const
int fieldIndex(const QString &name)
bool parseXSD(const QByteArray &xml)
Get fields info from XSD.
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
QStringList geometryAttributes(const QString &typeName)
Get list of geometry attributes for type/class name.