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 );
335 XML_Parser p = XML_ParserCreateNS(
nullptr,
NS_SEPARATOR );
336 XML_SetUserData( p,
this );
337 XML_SetElementHandler( p, QgsGmlSchema::start, QgsGmlSchema::end );
338 XML_SetCharacterDataHandler( p, QgsGmlSchema::chars );
340 int res = XML_Parse( p, data.
constData(), data.
size(), atEnd );
344 QString err =
QString( XML_ErrorString( XML_GetErrorCode( p ) ) );
346 mError =
QgsError( err,
"GML schema" );
347 mError.
append(
tr(
"Cannot guess schema" ) );
353 void QgsGmlSchema::startElement(
const XML_Char* el,
const XML_Char** attr )
359 QgsDebugMsgLevel(
QString(
"-> %1 %2 %3" ).arg( mLevel ).arg( elementName, mLevel >= mSkipLevel ?
"skip" :
"" ), 5 );
361 if ( mLevel >= mSkipLevel )
367 mParsePathStack.
append( elementName );
375 ParseMode parseMode = modeStackTop();
378 if ( ns == GML_NAMESPACE && localName ==
"boundedBy" )
381 mSkipLevel = mLevel + 1;
383 else if ( localName.
compare(
"featureMembers", Qt::CaseInsensitive ) == 0 )
385 mParseModeStack.
push( QgsGmlSchema::featureMembers );
392 else if ( localName.
endsWith(
"member", Qt::CaseInsensitive ) )
394 mParseModeStack.
push( QgsGmlSchema::featureMember );
397 else if ( elementName.
endsWith(
"_layer" ) )
405 else if ( elementName.
endsWith(
"_feature" )
406 || parseMode == QgsGmlSchema::featureMember
407 || parseMode == QgsGmlSchema::featureMembers
408 || localName.
compare(
"feature", Qt::CaseInsensitive ) == 0 )
411 if ( mFeatureClassMap.
count( localName ) == 0 )
415 mCurrentFeatureName = localName;
416 mParseModeStack.
push( QgsGmlSchema::feature );
418 else if ( parseMode == QgsGmlSchema::attribute && ns == GML_NAMESPACE && mGeometryTypes.
indexOf( localName ) >= 0 )
422 if ( geometryAttributes.
count( mAttributeName ) == 0 )
424 geometryAttributes.
append( mAttributeName );
426 mSkipLevel = mLevel + 1;
428 else if ( parseMode == QgsGmlSchema::feature )
437 QString name = readAttribute(
"name", attr );
439 if ( localName.
compare(
"attribute", Qt::CaseInsensitive ) == 0
442 QString value = readAttribute(
"value", attr );
444 addAttribute( name, value );
448 mAttributeName = localName;
449 mParseModeStack.
push( QgsGmlSchema::attribute );
455 void QgsGmlSchema::endElement(
const XML_Char* el )
460 if ( mLevel >= mSkipLevel )
476 QgsGmlSchema::ParseMode parseMode = modeStackTop();
478 if ( parseMode == QgsGmlSchema::featureMembers )
482 else if ( parseMode == QgsGmlSchema::attribute && localName == mAttributeName )
488 if ( mFeatureClassMap[mCurrentFeatureName].
geometryAttributes().count( mAttributeName ) == 0 )
490 addAttribute( mAttributeName, mStringCash );
493 else if ( ns == GML_NAMESPACE && localName ==
"boundedBy" )
497 else if ( localName.
endsWith(
"member", Qt::CaseInsensitive ) )
505 void QgsGmlSchema::characters(
const XML_Char* chars,
int len )
508 if ( mLevel >= mSkipLevel )
515 if ( modeStackTop() == QgsGmlSchema::attribute )
521 void QgsGmlSchema::addAttribute(
const QString& name,
const QString& value )
526 QVariant::Type type = QVariant::String;
529 type = QVariant::Int;
536 type = QVariant::Double;
542 int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( name );
543 if ( fieldIndex == -1 )
550 QgsField &field = fields[fieldIndex];
552 if (( field.
type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
553 ( field.
type() == QVariant::Double && type == QVariant::String ) )
562 return mFeatureClassMap.
keys();
568 return mFeatureClassMap[typeName].fields();
574 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)
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
Description of feature class in GML.
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()
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
int compare(const QString &other) const
int count(const Key &key) const
QStringList typeNames() const
Get list of dot separated paths to feature classes parsed from GML or XSD.
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)
QStringList geometryAttributes(const QString &typeName)
Get list of geometry attributes for type/class name.