void GMLReader::SetFeatureProperty( const char *pszElement, const char *pszValue ) { GMLFeature *poFeature = GetState()->m_poFeature; CPLAssert( poFeature != NULL ); /* -------------------------------------------------------------------- */ /* Does this property exist in the feature class? If not, add */ /* it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = poFeature->GetClass(); int iProperty; for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ ) { if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(), pszElement ) ) break; } if( iProperty == poClass->GetPropertyCount() ) { if( poClass->IsSchemaLocked() ) { CPLDebug("GML","Encountered property missing from class schema."); return; } GMLPropertyDefn *poPDefn = new GMLPropertyDefn(pszElement,pszElement); if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") ) poPDefn->SetType( GMLPT_String ); poClass->AddProperty( poPDefn ); } /* -------------------------------------------------------------------- */ /* Set the property */ /* -------------------------------------------------------------------- */ poFeature->SetProperty( iProperty, pszValue ); /* -------------------------------------------------------------------- */ /* Do we need to update the property type? */ /* -------------------------------------------------------------------- */ if( !poClass->IsSchemaLocked() ) poClass->GetProperty( iProperty )->AnalysePropertyValue(pszValue); }
OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass ) { OGRwkbGeometryType eGType = wkbNone; if( poClass->GetGeometryPropertyCount() != 0 ) { eGType = static_cast<OGRwkbGeometryType>( poClass->GetGeometryProperty(0)->GetType() ); if( poClass->GetFeatureCount() == 0 ) eGType = wkbUnknown; } /* -------------------------------------------------------------------- */ /* Translate SRS. */ /* -------------------------------------------------------------------- */ const char* pszSRSName = poClass->GetSRSName(); OGRSpatialReference* poSRS = NULL; if (pszSRSName) { const char *pszHandle = strrchr( pszSRSName, ':' ); if( pszHandle != NULL ) { pszHandle += 1; poSRS = new OGRSpatialReference(); for( int i = 0; apszURNNames[i*2+0] != NULL; i++ ) { const char *pszTarget = apszURNNames[i*2+0]; const int nTLen = static_cast<int>(strlen(pszTarget)); // Are we just looking for a prefix match? if( pszTarget[nTLen-1] == '*' ) { if( EQUALN(pszTarget,pszHandle,nTLen-1) ) pszSRSName = apszURNNames[i*2+1]; } else { if( EQUAL(pszTarget,pszHandle) ) pszSRSName = apszURNNames[i*2+1]; } } if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE) { CPLDebug( "NAS", "Failed to translate srsName='%s'", pszSRSName ); delete poSRS; poSRS = NULL; } } } /* -------------------------------------------------------------------- */ /* Create an empty layer. */ /* -------------------------------------------------------------------- */ OGRNASLayer *poLayer = new OGRNASLayer( poClass->GetName(), poSRS, eGType, this ); delete poSRS; /* -------------------------------------------------------------------- */ /* Added attributes (properties). */ /* -------------------------------------------------------------------- */ for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ ) { GMLPropertyDefn *poProperty = poClass->GetProperty( iField ); OGRFieldType eFType; if( poProperty->GetType() == GMLPT_Untyped ) eFType = OFTString; else if( poProperty->GetType() == GMLPT_String ) eFType = OFTString; else if( poProperty->GetType() == GMLPT_Integer ) eFType = OFTInteger; else if( poProperty->GetType() == GMLPT_Real ) eFType = OFTReal; else if( poProperty->GetType() == GMLPT_StringList ) eFType = OFTStringList; else if( poProperty->GetType() == GMLPT_IntegerList ) eFType = OFTIntegerList; else if( poProperty->GetType() == GMLPT_RealList ) eFType = OFTRealList; else eFType = OFTString; OGRFieldDefn oField( poProperty->GetName(), eFType ); if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") ) oField.SetName(poProperty->GetName()+4); if( poProperty->GetWidth() > 0 ) oField.SetWidth( poProperty->GetWidth() ); poLayer->GetLayerDefn()->AddFieldDefn( &oField ); } return poLayer; }
static GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode, const char* pszName, CPLXMLNode *psComplexType) { /* -------------------------------------------------------------------- */ /* Grab the sequence of extensions greatgrandchild. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAttrSeq = CPLGetXMLNode( psComplexType, "complexContent.extension.sequence" ); if( psAttrSeq == NULL ) { return NULL; } /* -------------------------------------------------------------------- */ /* We are pretty sure this going to be a valid Feature class */ /* now, so create it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = new GMLFeatureClass( pszName ); /* -------------------------------------------------------------------- */ /* Loop over each of the attribute elements being defined for */ /* this feature class. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAttrDef; int nAttributeIndex = 0; int bGotUnrecognizedType = FALSE; for( psAttrDef = psAttrSeq->psChild; psAttrDef != NULL; psAttrDef = psAttrDef->psNext ) { if( strcmp(psAttrDef->pszValue,"group") == 0 ) { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } if( !EQUAL(psAttrDef->pszValue,"element") ) continue; /* MapServer WFS writes element type as an attribute of element */ /* not as a simpleType definition */ const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL ); const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL ); if (pszType != NULL) { const char* pszStrippedNSType = StripNS(pszType); int nWidth = 0, nPrecision = 0; GMLPropertyType gmlType = GMLPT_Untyped; if (EQUAL(pszStrippedNSType, "string") || EQUAL(pszStrippedNSType, "Character")) gmlType = GMLPT_String; /* TODO: Would be nice to have a proper date type */ else if (EQUAL(pszStrippedNSType, "date") || EQUAL(pszStrippedNSType, "dateTime")) gmlType = GMLPT_String; else if (EQUAL(pszStrippedNSType, "real") || EQUAL(pszStrippedNSType, "double") || EQUAL(pszStrippedNSType, "float") || EQUAL(pszStrippedNSType, "decimal")) gmlType = GMLPT_Real; else if (EQUAL(pszStrippedNSType, "short") || EQUAL(pszStrippedNSType, "int") || EQUAL(pszStrippedNSType, "integer") || EQUAL(pszStrippedNSType, "long")) gmlType = GMLPT_Integer; else if (strncmp(pszType, "gml:", 4) == 0) { const AssocNameType* psIter = apsPropertyTypes; while(psIter->pszName) { if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0) { if (poClass->GetGeometryAttributeIndex() != -1) { CPLDebug("GML", "Geometry field already found ! Ignoring the following ones"); } else { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(psIter->eType); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; } break; } psIter ++; } if (psIter->pszName == NULL) { /* Can be a non geometry gml type */ /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } if (poClass->GetGeometryAttributeIndex() == -1) bGotUnrecognizedType = TRUE; continue; } /* Integraph stuff */ else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 || strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0) { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(wkbMultiPoint); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; continue; } else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 || strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0) { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(wkbMultiLineString); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; continue; } else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 || strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 || strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0) { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(wkbMultiPolygon); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; continue; } /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */ else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0) { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(wkbMultiPolygon); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; continue; } else { gmlType = GMLPT_Untyped; if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType, &gmlType, &nWidth, &nPrecision) ) { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } } if (pszElementName == NULL) pszElementName = "unnamed"; GMLPropertyDefn *poProp = new GMLPropertyDefn( pszElementName, pszElementName ); poProp->SetType( gmlType ); poProp->SetAttributeIndex( nAttributeIndex ); poProp->SetWidth( nWidth ); poProp->SetPrecision( nPrecision ); if (poClass->AddProperty( poProp ) < 0) delete poProp; else nAttributeIndex ++; continue; } // For now we skip geometries .. fixup later. CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" ); if( psSimpleType == NULL ) { const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL ); /* FME .xsd */ if (pszRef != NULL && strncmp(pszRef, "gml:", 4) == 0) { const AssocNameType* psIter = apsRefTypes; while(psIter->pszName) { if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0) { if (poClass->GetGeometryAttributeIndex() != -1) { OGRwkbGeometryType eNewType = psIter->eType; OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryType(); if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) || (eNewType == wkbMultiLineString && eOldType == wkbLineString) || (eNewType == wkbMultiPolygon && eOldType == wkbPolygon)) { poClass->SetGeometryType(eNewType); } else { CPLDebug("GML", "Geometry field already found ! Ignoring the following ones"); } } else { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(psIter->eType); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; } break; } psIter ++; } if (psIter->pszName == NULL) { /* Can be a non geometry gml type */ /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } if (poClass->GetGeometryAttributeIndex() == -1) bGotUnrecognizedType = TRUE; continue; } /* Parse stuff like the following found in http://199.29.1.81:8181/miwfs/GetFeature.ashx?REQUEST=GetFeature&MAXFEATURES=1&SERVICE=WFS&VERSION=1.0.0&TYPENAME=miwfs:World : <xs:element name="Obj" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element ref="gml:_Geometry"/> </xs:sequence> </xs:complexType> </xs:element> */ CPLXMLNode* psComplexType = GetSingleChildElement( psAttrDef, "complexType" ); CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( psComplexType, "sequence" ); CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" ); if( pszElementName != NULL && CheckMinMaxOccursCardinality(psAttrDef) && psComplexTypeSequenceElement != NULL && CheckMinMaxOccursCardinality(psComplexTypeSequence) && strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 ) { poClass->SetGeometryElement(pszElementName); poClass->SetGeometryType(wkbUnknown); poClass->SetGeometryAttributeIndex( nAttributeIndex ); nAttributeIndex ++; continue; } else { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } } if (pszElementName == NULL) pszElementName = "unnamed"; GMLPropertyDefn *poProp = new GMLPropertyDefn( pszElementName, pszElementName ); GMLPropertyType eType = GMLPT_Untyped; int nWidth = 0, nPrecision = 0; GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision); poProp->SetType( eType ); poProp->SetWidth( nWidth ); poProp->SetPrecision( nPrecision ); poProp->SetAttributeIndex( nAttributeIndex ); if (poClass->AddProperty( poProp ) < 0) delete poProp; else nAttributeIndex ++; } /* Only report wkbNone if we didn't find a known geometry type */ /* and there were not any unknown types (in case this unknown type */ /* would be a geometry type) */ if (poClass->GetGeometryAttributeIndex() == -1 && !bGotUnrecognizedType) { poClass->SetGeometryType(wkbNone); } /* -------------------------------------------------------------------- */ /* Class complete, add to reader class list. */ /* -------------------------------------------------------------------- */ poClass->SetSchemaLocked( TRUE ); return poClass; }
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot ) { /* -------------------------------------------------------------------- */ /* Do some rudimentary checking that this is a well formed */ /* node. */ /* -------------------------------------------------------------------- */ if( psRoot == NULL || psRoot->eType != CXT_Element || !EQUAL(psRoot->pszValue,"GMLFeatureClass") ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass::InitializeFromXML() called on %s node!", psRoot->pszValue ); return FALSE; } if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass has no <Name> element." ); return FALSE; } /* -------------------------------------------------------------------- */ /* Collect base info. */ /* -------------------------------------------------------------------- */ CPLFree( m_pszName ); m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) ); SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) ); const char *pszGPath = CPLGetXMLValue( psRoot, "GeometryElementPath", "" ); if( strlen( pszGPath ) > 0 ) SetGeometryElement( pszGPath ); if( CPLGetXMLValue( psRoot, "GeometryType", NULL ) != NULL ) { SetGeometryType( atoi(CPLGetXMLValue( psRoot, "GeometryType", NULL )) ); } /* -------------------------------------------------------------------- */ /* Collect dataset specific info. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" ); if( psDSI != NULL ) { const char *pszValue; pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL ); if( pszValue != NULL ) SetFeatureCount( atoi(pszValue) ); // Eventually we should support XML subtrees. pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL ); if( pszValue != NULL ) SetExtraInfo( pszValue ); if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL ) { SetExtents( atof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )), atof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )), atof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )), atof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) ); } } /* -------------------------------------------------------------------- */ /* Collect property definitions. */ /* -------------------------------------------------------------------- */ for( CPLXMLNode *psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext ) { if( EQUAL(psThis->pszValue, "PropertyDefn") ) { const char *pszName = CPLGetXMLValue( psThis, "Name", NULL ); const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" ); GMLPropertyDefn *poPDefn; if( pszName == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass %s has a PropertyDefn without a <Name>..", m_pszName ); return FALSE; } poPDefn = new GMLPropertyDefn( pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) ); if( EQUAL(pszType,"Untyped") ) poPDefn->SetType( GMLPT_Untyped ); else if( EQUAL(pszType,"String") ) { poPDefn->SetType( GMLPT_String ); poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); } else if( EQUAL(pszType,"Integer") ) { poPDefn->SetType( GMLPT_Integer ); poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); } else if( EQUAL(pszType,"Real") ) { poPDefn->SetType( GMLPT_Real ); poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) ); } else if( EQUAL(pszType,"StringList") ) poPDefn->SetType( GMLPT_StringList ); else if( EQUAL(pszType,"IntegerList") ) poPDefn->SetType( GMLPT_IntegerList ); else if( EQUAL(pszType,"RealList") ) poPDefn->SetType( GMLPT_RealList ); else if( EQUAL(pszType,"Complex") ) poPDefn->SetType( GMLPT_Complex ); else { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised property type %s.", pszType ); return FALSE; } AddProperty( poPDefn ); } } return TRUE; }
CPLXMLNode *GMLFeatureClass::SerializeToXML() { CPLXMLNode *psRoot; int iProperty; /* -------------------------------------------------------------------- */ /* Set feature class and core information. */ /* -------------------------------------------------------------------- */ psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" ); CPLCreateXMLElementAndValue( psRoot, "Name", GetName() ); CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() ); if( GetGeometryElement() != NULL && strlen(GetGeometryElement()) > 0 ) CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", GetGeometryElement() ); if( GetGeometryType() != 0 /* wkbUnknown */ ) { char szValue[128]; sprintf( szValue, "%d", GetGeometryType() ); CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue ); } /* -------------------------------------------------------------------- */ /* Write out dataset specific information. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSI; if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL ) { psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" ); if( m_nFeatureCount != -1 ) { char szValue[128]; sprintf( szValue, "%d", m_nFeatureCount ); CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue ); } if( m_bHaveExtents ) { char szValue[128]; sprintf( szValue, "%.5f", m_dfXMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue ); sprintf( szValue, "%.5f", m_dfXMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue ); sprintf( szValue, "%.5f", m_dfYMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue ); sprintf( szValue, "%.5f", m_dfYMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue ); } if( m_pszExtraInfo ) CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo ); } /* -------------------------------------------------------------------- */ /* emit property information. */ /* -------------------------------------------------------------------- */ for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ ) { GMLPropertyDefn *poPDefn = GetProperty( iProperty ); CPLXMLNode *psPDefnNode; const char *pszTypeName = "Unknown"; psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" ); CPLCreateXMLElementAndValue( psPDefnNode, "Name", poPDefn->GetName() ); CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", poPDefn->GetSrcElement() ); switch( poPDefn->GetType() ) { case GMLPT_Untyped: pszTypeName = "Untyped"; break; case GMLPT_String: pszTypeName = "String"; break; case GMLPT_Integer: pszTypeName = "Integer"; break; case GMLPT_Real: pszTypeName = "Real"; break; case GMLPT_Complex: pszTypeName = "Complex"; break; case GMLPT_IntegerList: pszTypeName = "IntegerList"; break; case GMLPT_RealList: pszTypeName = "RealList"; break; case GMLPT_StringList: pszTypeName = "StringList"; break; } CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName ); if( EQUAL(pszTypeName,"String") ) { char szMaxLength[48]; sprintf(szMaxLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); char szPrecision[48]; sprintf(szPrecision, "%d", poPDefn->GetPrecision()); CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision ); } } return psRoot; }
void NASReader::SetFeatureProperty( const char *pszElement, const char *pszValue ) { GMLFeature *poFeature = GetState()->m_poFeature; CPLAssert( poFeature != NULL ); /* -------------------------------------------------------------------- */ /* Does this property exist in the feature class? If not, add */ /* it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = poFeature->GetClass(); int iProperty; for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ ) { if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(), pszElement ) ) break; } if( iProperty == poClass->GetPropertyCount() ) { if( poClass->IsSchemaLocked() ) { CPLDebug("GML","Encountered property missing from class schema."); return; } CPLString osFieldName; if( strchr(pszElement,'|') == NULL ) osFieldName = pszElement; else { osFieldName = strrchr(pszElement,'|') + 1; if( poClass->GetPropertyIndex(osFieldName) != -1 ) osFieldName = pszElement; } // Does this conflict with an existing property name? while( poClass->GetProperty(osFieldName) != NULL ) { osFieldName += "_"; } GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement); if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") ) poPDefn->SetType( GMLPT_String ); poClass->AddProperty( poPDefn ); } /* -------------------------------------------------------------------- */ /* Set the property */ /* -------------------------------------------------------------------- */ poFeature->SetProperty( iProperty, pszValue ); /* -------------------------------------------------------------------- */ /* Do we need to update the property type? */ /* -------------------------------------------------------------------- */ if( !poClass->IsSchemaLocked() ) { poClass->GetProperty(iProperty)->AnalysePropertyValue( poFeature->GetProperty(iProperty)); } }
int GMLReader::ParseXSD( const char *pszFile ) { if( pszFile == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Load the raw XML file. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psXSDTree = CPLParseXMLFile( pszFile ); if( psXSDTree == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Strip off any namespace qualifiers. */ /* -------------------------------------------------------------------- */ CPLStripXMLNamespace( psXSDTree, NULL, TRUE ); /* -------------------------------------------------------------------- */ /* Find <schema> root element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psSchemaNode = CPLGetXMLNode( psXSDTree, "=schema" ); if( psSchemaNode == NULL ) { CPLDestroyXMLNode( psXSDTree ); return FALSE; } /* ==================================================================== */ /* Process each feature class definition. */ /* ==================================================================== */ CPLXMLNode *psThis; int bIsLevel0 = TRUE; for( psThis = psSchemaNode->psChild; psThis != NULL; psThis = psThis->psNext ) { /* -------------------------------------------------------------------- */ /* Check for <xs:element> node. */ /* -------------------------------------------------------------------- */ if( psThis->eType != CXT_Element || !EQUAL(psThis->pszValue,"element") ) continue; /* -------------------------------------------------------------------- */ /* Check the substitution group. */ /* -------------------------------------------------------------------- */ const char *pszSubGroup = StripNS(CPLGetXMLValue(psThis,"substitutionGroup","")); // Old OGR produced elements for the feature collection. if( EQUAL(pszSubGroup, "_FeatureCollection") ) continue; if( !EQUAL(pszSubGroup, "_Feature") ) { bIsLevel0 = FALSE; break; } /* -------------------------------------------------------------------- */ /* Get name */ /* -------------------------------------------------------------------- */ const char *pszName; pszName = CPLGetXMLValue( psThis, "name", NULL ); if( pszName == NULL ) { bIsLevel0 = FALSE; break; } /* -------------------------------------------------------------------- */ /* Get type and verify relationship with name. */ /* -------------------------------------------------------------------- */ const char *pszType; pszType = CPLGetXMLValue( psThis, "type", NULL ); if( strstr( pszType, ":" ) != NULL ) pszType = strstr( pszType, ":" ) + 1; if( pszType == NULL || !EQUALN(pszType,pszName,strlen(pszName)) || !(EQUAL(pszType+strlen(pszName),"_Type") || EQUAL(pszType+strlen(pszName),"Type")) ) { bIsLevel0 = FALSE; break; } /* -------------------------------------------------------------------- */ /* The very next element should be the corresponding */ /* complexType declaration for the element. */ /* -------------------------------------------------------------------- */ psThis = psThis->psNext; while( psThis != NULL && psThis->eType == CXT_Comment ) psThis = psThis->psNext; if( psThis == NULL || psThis->eType != CXT_Element || !EQUAL(psThis->pszValue,"complexType") || !EQUAL(CPLGetXMLValue(psThis,"name",""),pszType) ) { bIsLevel0 = FALSE; break; } /* -------------------------------------------------------------------- */ /* Grab the sequence of extensions greatgrandchild. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAttrSeq = CPLGetXMLNode( psThis, "complexContent.extension.sequence" ); if( psAttrSeq == NULL ) { bIsLevel0 = FALSE; break; } /* -------------------------------------------------------------------- */ /* We are pretty sure this going to be a valid Feature class */ /* now, so create it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = new GMLFeatureClass( pszName ); /* -------------------------------------------------------------------- */ /* Loop over each of the attribute elements being defined for */ /* this feature class. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAttrDef; for( psAttrDef = psAttrSeq->psChild; psAttrDef != NULL; psAttrDef = psAttrDef->psNext ) { if( !EQUAL(psAttrDef->pszValue,"element") ) continue; // For now we skip geometries .. fixup later. if( CPLGetXMLNode( psAttrDef, "simpleType" ) == NULL ) continue; GMLPropertyDefn *poProp = new GMLPropertyDefn( CPLGetXMLValue( psAttrDef, "name", "unnamed" ), CPLGetXMLValue( psAttrDef, "name", "unnamed" ) ); const char *pszBase = StripNS( CPLGetXMLValue( psAttrDef, "simpleType.restriction.base", "" )); if( EQUAL(pszBase,"decimal") ) { poProp->SetType( GMLPT_Real ); const char *pszWidth = CPLGetXMLValue( psAttrDef, "simpleType.restriction.totalDigits.value", "0" ); const char *pszPrecision = CPLGetXMLValue( psAttrDef, "simpleType.restriction.fractionDigits.value", "0" ); poProp->SetWidth( atoi(pszWidth) ); poProp->SetPrecision( atoi(pszPrecision) ); } else if( EQUAL(pszBase,"float") || EQUAL(pszBase,"double") ) poProp->SetType( GMLPT_Real ); else if( EQUAL(pszBase,"integer") ) { poProp->SetType( GMLPT_Integer ); const char *pszWidth = CPLGetXMLValue( psAttrDef, "simpleType.restriction.totalDigits.value", "0" ); poProp->SetWidth( atoi(pszWidth) ); } else if( EQUAL(pszBase,"string") ) { poProp->SetType( GMLPT_String ); const char *pszWidth = CPLGetXMLValue( psAttrDef, "simpleType.restriction.maxLength.value", "0" ); poProp->SetWidth( atoi(pszWidth) ); } else poProp->SetType( GMLPT_Untyped ); poClass->AddProperty( poProp ); } /* -------------------------------------------------------------------- */ /* Class complete, add to reader class list. */ /* -------------------------------------------------------------------- */ poClass->SetSchemaLocked( TRUE ); AddClass( poClass ); } CPLDestroyXMLNode( psXSDTree ); if( m_nClassCount > 0 ) { SetClassListLocked( TRUE ); return TRUE; } else return FALSE; }
void NASReader::SetFeaturePropertyDirectly( const char *pszElement, char *pszValue ) { GMLFeature *poFeature = GetState()->m_poFeature; CPLAssert( poFeature != NULL ); /* -------------------------------------------------------------------- */ /* Does this property exist in the feature class? If not, add */ /* it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = poFeature->GetClass(); int iProperty; for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ ) { if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(), pszElement ) ) break; } if( iProperty == poClass->GetPropertyCount() ) { if( poClass->IsSchemaLocked() ) { CPLDebug("NAS","Encountered property missing from class schema."); CPLFree(pszValue); return; } CPLString osFieldName; if( strchr(pszElement,'|') == NULL ) osFieldName = pszElement; else { osFieldName = strrchr(pszElement,'|') + 1; if( poClass->GetPropertyIndex(osFieldName) != -1 ) osFieldName = pszElement; } // Does this conflict with an existing property name? while( poClass->GetProperty(osFieldName) != NULL ) { osFieldName += "_"; } GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement); if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") ) poPDefn->SetType( GMLPT_String ); poClass->AddProperty( poPDefn ); } /* -------------------------------------------------------------------- */ /* We want to handle <lage> specially to ensure it is zero */ /* filled, and treated as a string depspite the numeric */ /* content. https://trac.wheregroup.com/PostNAS/ticket/9 */ /* -------------------------------------------------------------------- */ if( strcmp(poClass->GetProperty(iProperty)->GetName(),"lage") == 0 ) { if( strlen(pszValue) < 5 ) { CPLString osValue = "00000"; osValue += pszValue; poFeature->SetPropertyDirectly( iProperty, CPLStrdup(osValue + osValue.size() - 5) ); CPLFree(pszValue); } else poFeature->SetPropertyDirectly( iProperty, pszValue ); if( !poClass->IsSchemaLocked() ) { poClass->GetProperty(iProperty)->SetWidth( 5 ); poClass->GetProperty(iProperty)->SetType( GMLPT_String ); } return; } /* -------------------------------------------------------------------- */ /* Set the property */ /* -------------------------------------------------------------------- */ poFeature->SetPropertyDirectly( iProperty, pszValue ); /* -------------------------------------------------------------------- */ /* Do we need to update the property type? */ /* -------------------------------------------------------------------- */ if( !poClass->IsSchemaLocked() ) { // Special handling for punktkennung per NAS #12 if( strcmp(poClass->GetProperty(iProperty)->GetName(), "punktkennung") == 0) { poClass->GetProperty(iProperty)->SetWidth( 15 ); poClass->GetProperty(iProperty)->SetType( GMLPT_String ); } // Special handling for artDerFlurstuecksgrenze per http://trac.osgeo.org/gdal/ticket/4255 else if( strcmp(poClass->GetProperty(iProperty)->GetName(), "artDerFlurstuecksgrenze") == 0) { poClass->GetProperty(iProperty)->SetType( GMLPT_IntegerList ); } else poClass->GetProperty(iProperty)->AnalysePropertyValue( poFeature->GetProperty(iProperty)); } }
OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass ) { OGRGMLLayer *poLayer; /* -------------------------------------------------------------------- */ /* Create an empty layer. */ /* -------------------------------------------------------------------- */ poLayer = new OGRGMLLayer( poClass->GetName(), NULL, FALSE, wkbUnknown, this ); /* -------------------------------------------------------------------- */ /* Added attributes (properties). */ /* -------------------------------------------------------------------- */ for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ ) { GMLPropertyDefn *poProperty = poClass->GetProperty( iField ); OGRFieldType eFType; if( poProperty->GetType() == GMLPT_Untyped ) eFType = OFTString; else if( poProperty->GetType() == GMLPT_String ) eFType = OFTString; else if( poProperty->GetType() == GMLPT_Integer ) eFType = OFTInteger; else if( poProperty->GetType() == GMLPT_Real ) eFType = OFTReal; else eFType = OFTString; OGRFieldDefn oField( poProperty->GetName(), eFType ); if ( EQUALN(oField.GetNameRef(), "ogr:", 4) ) oField.SetName(poProperty->GetName()+4); if( poProperty->GetWidth() > 0 ) oField.SetWidth( poProperty->GetWidth() ); if( poProperty->GetPrecision() > 0 ) oField.SetPrecision( poProperty->GetPrecision() ); poLayer->GetLayerDefn()->AddFieldDefn( &oField ); } return poLayer; }
static GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode, const char* pszName, CPLXMLNode *psComplexType) { /* -------------------------------------------------------------------- */ /* Grab the sequence of extensions greatgrandchild. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAttrSeq = CPLGetXMLNode( psComplexType, "complexContent.extension.sequence" ); if( psAttrSeq == NULL ) { return NULL; } /* -------------------------------------------------------------------- */ /* We are pretty sure this going to be a valid Feature class */ /* now, so create it. */ /* -------------------------------------------------------------------- */ GMLFeatureClass *poClass = new GMLFeatureClass( pszName ); /* -------------------------------------------------------------------- */ /* Loop over each of the attribute elements being defined for */ /* this feature class. */ /* -------------------------------------------------------------------- */ int nAttributeIndex = 0; bool bGotUnrecognizedType = false; CPLXMLNode *psAttrDef = psAttrSeq->psChild; for( ; psAttrDef != NULL; psAttrDef = psAttrDef->psNext ) { if( strcmp(psAttrDef->pszValue,"group") == 0 ) { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } /* Parse stuff like : <xs:choice> <xs:element ref="gml:polygonProperty"/> <xs:element ref="gml:multiPolygonProperty"/> </xs:choice> as found in https://downloadagiv.blob.core.windows.net/overstromingsgebieden-en-oeverzones/2014_01/Overstromingsgebieden_en_oeverzones_2014_01_GML.zip */ if( strcmp(psAttrDef->pszValue,"choice") == 0 ) { CPLXMLNode* psChild = psAttrDef->psChild; bool bPolygon = false; bool bMultiPolygon = false; for( ; psChild; psChild = psChild->psNext ) { if( psChild->eType != CXT_Element ) continue; if( strcmp(psChild->pszValue,"element") == 0 ) { const char* pszRef = CPLGetXMLValue( psChild, "ref", NULL ); if( pszRef != NULL ) { if( strcmp(pszRef, "gml:polygonProperty") == 0 ) bPolygon = true; else if( strcmp(pszRef, "gml:multiPolygonProperty") == 0 ) bMultiPolygon = true; else { delete poClass; return NULL; } } else { delete poClass; return NULL; } } } if( bPolygon && bMultiPolygon ) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbMultiPolygon, nAttributeIndex, true ) ); nAttributeIndex ++; } continue; } if( !EQUAL(psAttrDef->pszValue,"element") ) continue; /* MapServer WFS writes element type as an attribute of element */ /* not as a simpleType definition */ const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL ); const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL ); bool bNullable = EQUAL(CPLGetXMLValue( psAttrDef, "minOccurs", "1" ), "0"); const char* pszMaxOccurs = CPLGetXMLValue( psAttrDef, "maxOccurs", NULL ); if (pszType != NULL) { const char* pszStrippedNSType = StripNS(pszType); int nWidth = 0, nPrecision = 0; GMLPropertyType gmlType = GMLPT_Untyped; if (EQUAL(pszStrippedNSType, "string") || EQUAL(pszStrippedNSType, "Character")) gmlType = GMLPT_String; /* TODO: Would be nice to have a proper date type */ else if (EQUAL(pszStrippedNSType, "date") || EQUAL(pszStrippedNSType, "dateTime")) gmlType = GMLPT_String; else if (EQUAL(pszStrippedNSType, "real") || EQUAL(pszStrippedNSType, "double") || EQUAL(pszStrippedNSType, "decimal")) gmlType = GMLPT_Real; else if (EQUAL(pszStrippedNSType, "float") ) gmlType = GMLPT_Float; else if (EQUAL(pszStrippedNSType, "int") || EQUAL(pszStrippedNSType, "integer")) gmlType = GMLPT_Integer; else if (EQUAL(pszStrippedNSType, "long")) gmlType = GMLPT_Integer64; else if (EQUAL(pszStrippedNSType, "short") ) gmlType = GMLPT_Short; else if (EQUAL(pszStrippedNSType, "boolean") ) gmlType = GMLPT_Boolean; else if (strcmp(pszType, "gml:FeaturePropertyType") == 0 ) { gmlType = GMLPT_FeatureProperty; } else if (STARTS_WITH(pszType, "gml:")) { const AssocNameType* psIter = apsPropertyTypes; while(psIter->pszName) { if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0) { OGRwkbGeometryType eType = psIter->eType; /* Look if there's a comment restricting to subclasses */ if( psAttrDef->psNext != NULL && psAttrDef->psNext->eType == CXT_Comment ) { if( strstr(psAttrDef->psNext->pszValue, "restricted to Polygon") ) eType = wkbPolygon; else if( strstr(psAttrDef->psNext->pszValue, "restricted to LineString") ) eType = wkbLineString; else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiPolygon") ) eType = wkbMultiPolygon; else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiLineString") ) eType = wkbMultiLineString; } poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, eType, nAttributeIndex, bNullable ) ); nAttributeIndex ++; break; } psIter ++; } if (psIter->pszName == NULL) { /* Can be a non geometry gml type */ /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } if (poClass->GetGeometryPropertyCount() == 0) bGotUnrecognizedType = true; continue; } /* Integraph stuff */ else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 || strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, wkbMultiPoint, nAttributeIndex, bNullable ) ); nAttributeIndex ++; continue; } else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 || strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, wkbMultiLineString, nAttributeIndex, bNullable ) ); nAttributeIndex ++; continue; } else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 || strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 || strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex, bNullable ) ); nAttributeIndex ++; continue; } /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */ else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex, bNullable) ); nAttributeIndex ++; continue; } else { gmlType = GMLPT_Untyped; if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType, &gmlType, &nWidth, &nPrecision) ) { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } } if (pszElementName == NULL) pszElementName = "unnamed"; const char* pszPropertyName = pszElementName; if( gmlType == GMLPT_FeatureProperty ) { pszPropertyName = CPLSPrintf("%s_href", pszElementName); } GMLPropertyDefn *poProp = new GMLPropertyDefn( pszPropertyName, pszElementName ); if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 ) gmlType = GetListTypeFromSingleType(gmlType); poProp->SetType( gmlType ); poProp->SetWidth( nWidth ); poProp->SetPrecision( nPrecision ); poProp->SetNullable( bNullable ); if (poClass->AddProperty( poProp ) < 0) delete poProp; else nAttributeIndex ++; continue; } // For now we skip geometries .. fixup later. CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" ); if( psSimpleType == NULL ) { const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL ); /* FME .xsd */ if (pszRef != NULL && STARTS_WITH(pszRef, "gml:")) { const AssocNameType* psIter = apsRefTypes; while(psIter->pszName) { if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0) { if (poClass->GetGeometryPropertyCount() > 0) { OGRwkbGeometryType eNewType = psIter->eType; OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryProperty(0)->GetType(); if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) || (eNewType == wkbMultiLineString && eOldType == wkbLineString) || (eNewType == wkbMultiPolygon && eOldType == wkbPolygon)) { poClass->GetGeometryProperty(0)->SetType(eNewType); } else { CPLDebug("GML", "Geometry field already found ! Ignoring the following ones"); } } else { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, psIter->eType, nAttributeIndex, true ) ); nAttributeIndex ++; } break; } psIter ++; } if (psIter->pszName == NULL) { /* Can be a non geometry gml type */ /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } if (poClass->GetGeometryPropertyCount() == 0) bGotUnrecognizedType = true; continue; } /* Parse stuff like the following found in http://199.29.1.81:8181/miwfs/GetFeature.ashx?REQUEST=GetFeature&MAXFEATURES=1&SERVICE=WFS&VERSION=1.0.0&TYPENAME=miwfs:World : <xs:element name="Obj" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:sequence> <xs:element ref="gml:_Geometry"/> </xs:sequence> </xs:complexType> </xs:element> */ CPLXMLNode* l_psComplexType = GetSingleChildElement( psAttrDef, "complexType" ); CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( l_psComplexType, "sequence" ); CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" ); if( pszElementName != NULL && CheckMinMaxOccursCardinality(psAttrDef) && psComplexTypeSequenceElement != NULL && CheckMinMaxOccursCardinality(psComplexTypeSequence) && strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 ) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( pszElementName, pszElementName, wkbUnknown, nAttributeIndex, bNullable ) ); nAttributeIndex ++; continue; } else { /* Too complex schema for us. Aborts parsing */ delete poClass; return NULL; } } if (pszElementName == NULL) pszElementName = "unnamed"; GMLPropertyDefn *poProp = new GMLPropertyDefn( pszElementName, pszElementName ); GMLPropertyType eType = GMLPT_Untyped; int nWidth = 0, nPrecision = 0; GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision); if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 ) eType = GetListTypeFromSingleType(eType); poProp->SetType( eType ); poProp->SetWidth( nWidth ); poProp->SetPrecision( nPrecision ); poProp->SetNullable( bNullable ); if (poClass->AddProperty( poProp ) < 0) delete poProp; else nAttributeIndex ++; } /* If we have found an unknown types, let's be on the side of caution and */ /* create a geometry field */ if( poClass->GetGeometryPropertyCount() == 0 && bGotUnrecognizedType ) { poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) ); } /* -------------------------------------------------------------------- */ /* Class complete, add to reader class list. */ /* -------------------------------------------------------------------- */ poClass->SetSchemaLocked( true ); return poClass; }
CPLXMLNode *GMLFeatureClass::SerializeToXML() { CPLXMLNode *psRoot; int iProperty; /* -------------------------------------------------------------------- */ /* Set feature class and core information. */ /* -------------------------------------------------------------------- */ psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" ); CPLCreateXMLElementAndValue( psRoot, "Name", GetName() ); CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() ); if( m_nGeometryPropertyCount > 1 ) { for(int i=0; i < m_nGeometryPropertyCount; i++) { GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[i]; CPLXMLNode *psPDefnNode; psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "GeomPropertyDefn" ); if( strlen(poGeomFDefn->GetName()) > 0 ) CPLCreateXMLElementAndValue( psPDefnNode, "Name", poGeomFDefn->GetName() ); if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 ) CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", poGeomFDefn->GetSrcElement() ); if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ ) { char szValue[128]; OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType(); CPLString osStr(OGRToOGCGeomType(eType)); if( wkbHasZ(eType) ) osStr += "Z"; CPLCreateXMLNode( psPDefnNode, CXT_Comment, osStr.c_str() ); sprintf( szValue, "%d", eType ); CPLCreateXMLElementAndValue( psPDefnNode, "Type", szValue ); } } } else if( m_nGeometryPropertyCount == 1 ) { GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0]; if( strlen(poGeomFDefn->GetName()) > 0 ) CPLCreateXMLElementAndValue( psRoot, "GeometryName", poGeomFDefn->GetName() ); if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 ) CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", poGeomFDefn->GetSrcElement() ); if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ ) { char szValue[128]; OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType(); CPLString osStr(OGRToOGCGeomType(eType)); if( wkbHasZ(eType) ) osStr += "Z"; CPLCreateXMLNode( psRoot, CXT_Comment, osStr.c_str() ); sprintf( szValue, "%d", eType ); CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue ); } } else { CPLCreateXMLElementAndValue( psRoot, "GeometryType", "100" ); } const char* pszSRSName = GetSRSName(); if( pszSRSName ) { CPLCreateXMLElementAndValue( psRoot, "SRSName", pszSRSName ); } /* -------------------------------------------------------------------- */ /* Write out dataset specific information. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSI; if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL ) { psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" ); if( m_nFeatureCount != -1 ) { char szValue[128]; sprintf( szValue, CPL_FRMT_GIB, m_nFeatureCount ); CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue ); } if( m_bHaveExtents && fabs(m_dfXMin) < 1e100 && fabs(m_dfXMax) < 1e100 && fabs(m_dfYMin) < 1e100 && fabs(m_dfYMax) < 1e100 ) { char szValue[128]; CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMin ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue ); CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMax ); CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue ); } if( m_pszExtraInfo ) CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo ); } /* -------------------------------------------------------------------- */ /* emit property information. */ /* -------------------------------------------------------------------- */ for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ ) { GMLPropertyDefn *poPDefn = GetProperty( iProperty ); CPLXMLNode *psPDefnNode; const char *pszTypeName = "Unknown"; psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" ); CPLCreateXMLElementAndValue( psPDefnNode, "Name", poPDefn->GetName() ); CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", poPDefn->GetSrcElement() ); switch( poPDefn->GetType() ) { case GMLPT_Untyped: pszTypeName = "Untyped"; break; case GMLPT_String: case GMLPT_Boolean: pszTypeName = "String"; break; case GMLPT_Integer: case GMLPT_Short: case GMLPT_Integer64: pszTypeName = "Integer"; break; case GMLPT_Real: case GMLPT_Float: pszTypeName = "Real"; break; case GMLPT_Complex: pszTypeName = "Complex"; break; case GMLPT_IntegerList: case GMLPT_Integer64List: pszTypeName = "IntegerList"; break; case GMLPT_RealList: pszTypeName = "RealList"; break; case GMLPT_StringList: case GMLPT_BooleanList: pszTypeName = "StringList"; break; /* should not happen in practise for now because this is not */ /* autodetected */ case GMLPT_FeatureProperty: pszTypeName = "FeatureProperty"; break; /* should not happen in practise for now because this is not */ /* autodetected */ case GMLPT_FeaturePropertyList: pszTypeName = "FeaturePropertyList"; break; } CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName ); if( poPDefn->GetType() == GMLPT_Boolean || poPDefn->GetType() == GMLPT_BooleanList ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Boolean" ); else if( poPDefn->GetType() == GMLPT_Short ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Short" ); else if( poPDefn->GetType() == GMLPT_Float ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Float" ); else if( poPDefn->GetType() == GMLPT_Integer64 || poPDefn->GetType() == GMLPT_Integer64List ) CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Integer64" ); if( EQUAL(pszTypeName,"String") ) { char szMaxLength[48]; sprintf(szMaxLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); } if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") ) { char szLength[48]; sprintf(szLength, "%d", poPDefn->GetWidth()); CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength ); char szPrecision[48]; sprintf(szPrecision, "%d", poPDefn->GetPrecision()); CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision ); } } return psRoot; }
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot ) { /* -------------------------------------------------------------------- */ /* Do some rudimentary checking that this is a well formed */ /* node. */ /* -------------------------------------------------------------------- */ if( psRoot == NULL || psRoot->eType != CXT_Element || !EQUAL(psRoot->pszValue,"GMLFeatureClass") ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass::InitializeFromXML() called on %s node!", psRoot->pszValue ); return FALSE; } if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass has no <Name> element." ); return FALSE; } /* -------------------------------------------------------------------- */ /* Collect base info. */ /* -------------------------------------------------------------------- */ CPLFree( m_pszName ); m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) ); n_nNameLen = strlen(m_pszName); SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) ); /* -------------------------------------------------------------------- */ /* Collect geometry properties. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psThis; int bHasValidGeometryName = FALSE; int bHasValidGeometryElementPath = FALSE; int bHasFoundGeomType = FALSE; int bHasFoundGeomElements = FALSE; const char* pszGName = ""; const char* pszGPath = ""; int nGeomType = wkbUnknown; for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext ) { if( psThis->eType == CXT_Element && EQUAL(psThis->pszValue, "GeomPropertyDefn") ) { const char *pszName = CPLGetXMLValue( psThis, "Name", "" ); const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" ); const char *pszType = CPLGetXMLValue( psThis, "Type", NULL ); int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") ); nGeomType = wkbUnknown; if( pszType != NULL && !EQUAL(pszType, "0") ) { nGeomType = atoi(pszType); OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType); if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) ) { nGeomType = wkbUnknown; CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s", pszType); } else if( nGeomType == 0 ) nGeomType = OGRFromOGCGeomType(pszType); } bHasFoundGeomElements = TRUE; AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType, -1, bNullable ) ); bHasValidGeometryName = FALSE; bHasValidGeometryElementPath = FALSE; bHasFoundGeomType = FALSE; } else if( psThis->eType == CXT_Element && strcmp(psThis->pszValue, "GeometryName") == 0 ) { bHasFoundGeomElements = TRUE; if( bHasValidGeometryName ) { AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) ); bHasValidGeometryName = FALSE; bHasValidGeometryElementPath = FALSE; bHasFoundGeomType = FALSE; pszGPath = ""; nGeomType = wkbUnknown; } pszGName = CPLGetXMLValue( psThis, NULL, "" ); bHasValidGeometryName = TRUE; } else if( psThis->eType == CXT_Element && strcmp(psThis->pszValue, "GeometryElementPath") == 0 ) { bHasFoundGeomElements = TRUE; if( bHasValidGeometryElementPath ) { AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) ); bHasValidGeometryName = FALSE; bHasValidGeometryElementPath = FALSE; bHasFoundGeomType = FALSE; pszGName = ""; nGeomType = wkbUnknown; } pszGPath = CPLGetXMLValue( psThis, NULL, "" ); bHasValidGeometryElementPath = TRUE; } else if( psThis->eType == CXT_Element && strcmp(psThis->pszValue, "GeometryType") == 0 ) { bHasFoundGeomElements = TRUE; if( bHasFoundGeomType ) { AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) ); bHasValidGeometryName = FALSE; bHasValidGeometryElementPath = FALSE; bHasFoundGeomType = FALSE; pszGName = ""; pszGPath = ""; nGeomType = wkbUnknown; } const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL ); nGeomType = wkbUnknown; if( pszGeometryType != NULL && !EQUAL(pszGeometryType, "0") ) { nGeomType = atoi(pszGeometryType); OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType); if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") ) { bHasValidGeometryElementPath = FALSE; bHasFoundGeomType = FALSE; break; } else if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) ) { nGeomType = wkbUnknown; CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s", pszGeometryType); } else if( nGeomType == 0 ) nGeomType = OGRFromOGCGeomType(pszGeometryType); } bHasFoundGeomType = TRUE; } } /* If there was a dangling <GeometryElementPath> or <GeometryType> or */ /* that no explicit geometry information has been found, then add */ /* a geometry field */ if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements ) { AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) ); } SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) ); /* -------------------------------------------------------------------- */ /* Collect dataset specific info. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" ); if( psDSI != NULL ) { const char *pszValue; pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL ); if( pszValue != NULL ) SetFeatureCount( CPLAtoGIntBig(pszValue) ); // Eventually we should support XML subtrees. pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL ); if( pszValue != NULL ) SetExtraInfo( pszValue ); if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL ) { SetExtents( CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )), CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )), CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )), CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) ); } } /* -------------------------------------------------------------------- */ /* Collect property definitions. */ /* -------------------------------------------------------------------- */ for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext ) { if( psThis->eType == CXT_Element && EQUAL(psThis->pszValue, "PropertyDefn") ) { const char *pszName = CPLGetXMLValue( psThis, "Name", NULL ); const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" ); const char *pszSubType = CPLGetXMLValue( psThis, "Subtype", "" ); const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL ); int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") ); GMLPropertyDefn *poPDefn; if( pszName == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "GMLFeatureClass %s has a PropertyDefn without a <Name>..", m_pszName ); return FALSE; } poPDefn = new GMLPropertyDefn( pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) ); poPDefn->SetNullable(bNullable); if( EQUAL(pszType,"Untyped") ) poPDefn->SetType( GMLPT_Untyped ); else if( EQUAL(pszType,"String") ) { if( EQUAL(pszSubType, "Boolean") ) { poPDefn->SetType( GMLPT_Boolean ); poPDefn->SetWidth( 1 ); } else { poPDefn->SetType( GMLPT_String ); poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); } } else if( EQUAL(pszType,"Integer") ) { if( EQUAL(pszSubType, "Short") ) { poPDefn->SetType( GMLPT_Short ); } else if( EQUAL(pszSubType, "Integer64") ) { poPDefn->SetType( GMLPT_Integer64 ); } else { poPDefn->SetType( GMLPT_Integer ); } poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); } else if( EQUAL(pszType,"Real") ) { if( EQUAL(pszSubType, "Float") ) { poPDefn->SetType( GMLPT_Float ); } else { poPDefn->SetType( GMLPT_Real ); } poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) ); poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) ); } else if( EQUAL(pszType,"StringList") ) { if( EQUAL(pszSubType, "Boolean") ) poPDefn->SetType( GMLPT_BooleanList ); else poPDefn->SetType( GMLPT_StringList ); } else if( EQUAL(pszType,"IntegerList") ) { if( EQUAL(pszSubType, "Integer64") ) poPDefn->SetType( GMLPT_Integer64List ); else poPDefn->SetType( GMLPT_IntegerList ); } else if( EQUAL(pszType,"RealList") ) poPDefn->SetType( GMLPT_RealList ); else if( EQUAL(pszType,"Complex") ) poPDefn->SetType( GMLPT_Complex ); else if( EQUAL(pszType,"FeatureProperty") ) poPDefn->SetType( GMLPT_FeatureProperty ); else if( EQUAL(pszType,"FeaturePropertyList") ) poPDefn->SetType( GMLPT_FeaturePropertyList ); else { CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised property type %s.", pszType ); delete poPDefn; return FALSE; } if( pszCondition != NULL ) poPDefn->SetCondition(pszCondition); AddProperty( poPDefn ); } } return TRUE; }