24 #include <QNetworkRequest>
25 #include <QNetworkReply>
26 #include <QProgressDialog>
52 for (
int i = 0; i < mFields.size(); i++ )
54 if ( mFields[i].name() == name )
return i;
62 , mCurrentFeature( NULL )
65 , mSkipLevel( std::numeric_limits<int>::
max() )
67 mGeometryTypes <<
"Point" <<
"MultiPoint"
68 <<
"LineString" <<
"MultiLineString"
69 <<
"Polygon" <<
"MultiPolygon";
77 QString QgsGmlSchema::readAttribute(
const QString& attributeName,
const XML_Char** attr )
const
80 while ( attr[i] != NULL )
82 if ( attributeName.compare( attr[i] ) == 0 )
84 return QString( attr[i+1] );
97 if ( !dom.setContent( xml,
false, &errorMsg, &errorLine, &errorColumn ) )
103 QDomElement docElem = dom.documentElement();
105 QList<QDomElement> elementElements = domElements( docElem,
"element" );
109 foreach ( QDomElement elementElement, elementElements )
111 QString name = elementElement.attribute(
"name" );
112 QString type = elementElement.attribute(
"type" );
114 QString gmlBaseType = xsdComplexTypeGmlBaseType( docElem, stripNS( type ) );
121 if ( gmlBaseType ==
"AbstractFeatureType" )
125 xsdFeatureClass( docElem, stripNS( type ), featureClass );
126 mFeatureClassMap.insert( name, featureClass );
134 bool QgsGmlSchema::xsdFeatureClass(
const QDomElement &element,
const QString & typeName,
QgsGmlFeatureClass & featureClass )
137 QDomElement complexTypeElement = domElement( element,
"complexType",
"name", typeName );
138 if ( complexTypeElement.isNull() )
return false;
141 QDomElement extrest = domElement( complexTypeElement,
"complexContent.extension" );
142 if ( extrest.isNull() )
144 extrest = domElement( complexTypeElement,
"complexContent.restriction" );
146 if ( extrest.isNull() )
return false;
148 QString extrestName = extrest.attribute(
"base" );
149 if ( extrestName ==
"gml:AbstractFeatureType" )
158 if ( !xsdFeatureClass( element, stripNS( extrestName ), featureClass ) )
return false;
162 QStringList geometryPropertyTypes;
163 foreach ( QString geom, mGeometryTypes )
165 geometryPropertyTypes << geom +
"PropertyType";
168 QStringList geometryAliases;
169 geometryAliases <<
"location" <<
"centerOf" <<
"position" <<
"extentOf"
170 <<
"coverage" <<
"edgeOf" <<
"centerLineOf" <<
"multiLocation"
171 <<
"multiCenterOf" <<
"multiPosition" <<
"multiCenterLineOf"
172 <<
"multiEdgeOf" <<
"multiCoverage" <<
"multiExtentOf";
175 QList<QDomElement> sequenceElements = domElements( extrest,
"sequence.element" );
176 foreach ( QDomElement sequenceElement, sequenceElements )
178 QString fieldName = sequenceElement.attribute(
"name" );
179 QString fieldTypeName = stripNS( sequenceElement.attribute(
"type" ) );
180 QString ref = sequenceElement.attribute(
"ref" );
183 if ( !ref.isEmpty() )
185 if ( ref.startsWith(
"gml:" ) )
187 if ( geometryAliases.contains( stripNS( ref ) ) )
193 QgsDebugMsg( QString(
"Unknown referenced GML element: %1" ).arg( ref ) );
199 QgsDebugMsg( QString(
"field %1.%2 is referencing %3 - not supported" ).arg( typeName ).arg( fieldName ) );
204 if ( fieldName.isEmpty() )
206 QgsDebugMsg( QString(
"field in %1 without name" ).arg( typeName ) );
211 if ( fieldTypeName.isEmpty() )
214 QDomElement sequenceElementRestriction = domElement( sequenceElement,
"simpleType.restriction" );
215 fieldTypeName = stripNS( sequenceElementRestriction.attribute(
"base" ) );
218 QVariant::Type fieldType = QVariant::String;
219 if ( fieldTypeName.isEmpty() )
221 QgsDebugMsg( QString(
"Cannot get %1.%2 field type" ).arg( typeName ).arg( fieldName ) );
225 if ( geometryPropertyTypes.contains( fieldTypeName ) )
232 if ( fieldTypeName ==
"decimal" )
234 fieldType = QVariant::Double;
236 else if ( fieldTypeName ==
"integer" )
238 fieldType = QVariant::Int;
242 QgsField field( fieldName, fieldType, fieldTypeName );
243 featureClass.
fields().append( field );
249 QString QgsGmlSchema::xsdComplexTypeGmlBaseType(
const QDomElement &element,
const QString & name )
252 QDomElement complexTypeElement = domElement( element,
"complexType",
"name", name );
253 if ( complexTypeElement.isNull() )
return "";
255 QDomElement extrest = domElement( complexTypeElement,
"complexContent.extension" );
256 if ( extrest.isNull() )
258 extrest = domElement( complexTypeElement,
"complexContent.restriction" );
260 if ( extrest.isNull() )
return "";
262 QString extrestName = extrest.attribute(
"base" );
263 if ( extrestName.startsWith(
"gml:" ) )
266 return stripNS( extrestName );
269 return xsdComplexTypeGmlBaseType( element, stripNS( extrestName ) );
272 QString QgsGmlSchema::stripNS(
const QString & name )
274 return name.contains(
":" ) ? name.section(
':', 1 ) : name;
277 QList<QDomElement> QgsGmlSchema::domElements(
const QDomElement &element,
const QString & path )
279 QList<QDomElement> list;
281 QStringList names = path.split(
"." );
282 if ( names.size() == 0 )
return list;
283 QString name = names.value( 0 );
286 QDomNode n1 = element.firstChild();
287 while ( !n1.isNull() )
289 QDomElement el = n1.toElement();
292 QString tagName = stripNS( el.tagName() );
293 if ( tagName == name )
295 if ( names.size() == 0 )
301 list.append( domElements( el, names.join(
"." ) ) );
305 n1 = n1.nextSibling();
311 QDomElement QgsGmlSchema::domElement(
const QDomElement &element,
const QString & path )
313 return domElements( element, path ).value( 0 );
316 QList<QDomElement> QgsGmlSchema::domElements( QList<QDomElement> &elements,
const QString & attr,
const QString & attrVal )
318 QList<QDomElement> list;
319 foreach ( QDomElement el, elements )
321 if ( el.attribute( attr ) == attrVal )
329 QDomElement QgsGmlSchema::domElement(
const QDomElement &element,
const QString & path,
const QString & attr,
const QString & attrVal )
331 QList<QDomElement> list = domElements( element, path );
332 return domElements( list, attr, attrVal ).value( 0 );
340 XML_Parser p = XML_ParserCreateNS( NULL,
NS_SEPARATOR );
341 XML_SetUserData( p,
this );
342 XML_SetElementHandler( p, QgsGmlSchema::start, QgsGmlSchema::end );
343 XML_SetCharacterDataHandler( p, QgsGmlSchema::chars );
345 int res = XML_Parse( p, data.constData(), data.size(), atEnd );
349 QString err = QString( XML_ErrorString( XML_GetErrorCode( p ) ) );
350 QgsDebugMsg( QString(
"XML_Parse returned %1 error %2" ).arg( res ).arg( err ) );
351 mError =
QgsError( err,
"GML schema" );
352 mError.
append(
tr(
"Cannot guess schema" ) );
358 void QgsGmlSchema::startElement(
const XML_Char* el,
const XML_Char** attr )
363 QString elementName = QString::fromUtf8( el );
364 QgsDebugMsgLevel( QString(
"-> %1 %2 %3" ).arg( mLevel ).arg( elementName ).arg( mLevel >= mSkipLevel ?
"skip" :
"" ), 5 );
366 if ( mLevel >= mSkipLevel )
372 mParsePathStack.append( elementName );
373 QString path = mParsePathStack.join(
"." );
375 QStringList splitName = elementName.split(
NS_SEPARATOR );
376 QString localName = splitName.last();
377 QString ns = splitName.size() > 1 ? splitName.first() :
"";
380 ParseMode parseMode = modeStackTop();
386 mSkipLevel = mLevel + 1;
388 else if ( localName.compare(
"featureMembers", Qt::CaseInsensitive ) == 0 )
390 mParseModeStack.push( QgsGmlSchema::featureMembers );
397 else if ( localName.endsWith(
"member", Qt::CaseInsensitive ) )
399 mParseModeStack.push( QgsGmlSchema::featureMember );
402 else if ( elementName.endsWith(
"_layer" ) )
410 else if ( elementName.endsWith(
"_feature" )
411 || parseMode == QgsGmlSchema::featureMember
412 || parseMode == QgsGmlSchema::featureMembers
413 || localName.compare(
"feature", Qt::CaseInsensitive ) == 0 )
416 if ( mFeatureClassMap.count( localName ) == 0 )
420 mCurrentFeatureName = localName;
421 mParseModeStack.push( QgsGmlSchema::feature );
423 else if ( parseMode == QgsGmlSchema::attribute && ns ==
GML_NAMESPACE && mGeometryTypes.indexOf( localName ) >= 0 )
426 QStringList &
geometryAttributes = mFeatureClassMap[mCurrentFeatureName].geometryAttributes();
427 if ( geometryAttributes.count( mAttributeName ) == 0 )
429 geometryAttributes.append( mAttributeName );
431 mSkipLevel = mLevel + 1;
433 else if ( parseMode == QgsGmlSchema::feature )
442 QString name = readAttribute(
"name", attr );
444 if ( localName.compare(
"attribute", Qt::CaseInsensitive ) == 0
447 QString value = readAttribute(
"value", attr );
449 addAttribute( name, value );
453 mAttributeName = localName;
454 mParseModeStack.push( QgsGmlSchema::attribute );
460 void QgsGmlSchema::endElement(
const XML_Char* el )
462 QString elementName = QString::fromUtf8( el );
463 QgsDebugMsgLevel( QString(
"<- %1 %2" ).arg( mLevel ).arg( elementName ), 5 );
465 if ( mLevel >= mSkipLevel )
477 QStringList splitName = elementName.split(
NS_SEPARATOR );
478 QString localName = splitName.last();
479 QString ns = splitName.size() > 1 ? splitName.first() :
"";
481 QgsGmlSchema::ParseMode parseMode = modeStackTop();
483 if ( parseMode == QgsGmlSchema::featureMembers )
487 else if ( parseMode == QgsGmlSchema::attribute && localName == mAttributeName )
493 if ( mFeatureClassMap[mCurrentFeatureName].
geometryAttributes().count( mAttributeName ) == 0 )
495 addAttribute( mAttributeName, mStringCash );
502 else if ( localName.endsWith(
"member", Qt::CaseInsensitive ) )
506 mParsePathStack.removeLast();
510 void QgsGmlSchema::characters(
const XML_Char* chars,
int len )
513 if ( mLevel >= mSkipLevel )
520 if ( modeStackTop() == QgsGmlSchema::attribute )
522 mStringCash.append( QString::fromUtf8( chars, len ) );
526 void QgsGmlSchema::addAttribute(
const QString& name,
const QString& value )
531 QVariant::Type type = QVariant::String;
534 type = QVariant::Int;
538 value.toDouble( &ok );
541 type = QVariant::Double;
546 QList<QgsField> &
fields = mFeatureClassMap[mCurrentFeatureName].fields();
547 int fieldIndex = mFeatureClassMap[mCurrentFeatureName].fieldIndex( name );
548 if ( fieldIndex == -1 )
551 fields.append( field );
555 QgsField &field = fields[fieldIndex];
557 if (( field.
type() == QVariant::Int && ( type == QVariant::String || type == QVariant::Double ) ) ||
558 ( field.
type() == QVariant::Double && type == QVariant::String ) )
567 return mFeatureClassMap.keys();
572 if ( mFeatureClassMap.count( typeName ) == 0 )
return QList<QgsField>();
573 return mFeatureClassMap[typeName].fields();
578 if ( mFeatureClassMap.count( typeName ) == 0 )
return QStringList();
579 return mFeatureClassMap[typeName].geometryAttributes();