void kml2field ( OGRFeature * poOgrFeat, PlacemarkPtr poKmlPlacemark ) { const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" ); const char *descfield = CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" ); const char *tsfield = CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" ); const char *beginfield = CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" ); const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" ); const char *altitudeModefield = CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" ); const char *tessellatefield = CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" ); const char *extrudefield = CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" ); const char *visibilityfield = CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" ); /***** name *****/ if ( poKmlPlacemark->has_name ( ) ) { const std::string oKmlName = poKmlPlacemark->get_name ( ); int iField = poOgrFeat->GetFieldIndex ( namefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, oKmlName.c_str ( ) ); } /***** description *****/ if ( poKmlPlacemark->has_description ( ) ) { const std::string oKmlDesc = poKmlPlacemark->get_description ( ); int iField = poOgrFeat->GetFieldIndex ( descfield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, oKmlDesc.c_str ( ) ); } if ( poKmlPlacemark->has_timeprimitive ( ) ) { TimePrimitivePtr poKmlTimePrimitive = poKmlPlacemark->get_timeprimitive ( ); /***** timestamp *****/ if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeStamp ) ) { TimeStampPtr poKmlTimeStamp = AsTimeStamp ( poKmlTimePrimitive ); if ( poKmlTimeStamp->has_when ( ) ) { const std::string oKmlWhen = poKmlTimeStamp->get_when ( ); int iField = poOgrFeat->GetFieldIndex ( tsfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } } /***** timespan *****/ if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeSpan ) ) { TimeSpanPtr poKmlTimeSpan = AsTimeSpan ( poKmlTimePrimitive ); /***** begin *****/ if ( poKmlTimeSpan->has_begin ( ) ) { const std::string oKmlWhen = poKmlTimeSpan->get_begin ( ); int iField = poOgrFeat->GetFieldIndex ( beginfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } /***** end *****/ if ( poKmlTimeSpan->has_end ( ) ) { const std::string oKmlWhen = poKmlTimeSpan->get_end ( ); int iField = poOgrFeat->GetFieldIndex ( endfield ); if ( iField > -1 ) { int nYear, nMonth, nDay, nHour, nMinute, nTZ; float fSecond; if ( OGRParseXMLDateTime ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZ ) ) poOgrFeat->SetField ( iField, nYear, nMonth, nDay, nHour, nMinute, ( int )fSecond, nTZ ); } } } } if ( poKmlPlacemark->has_geometry ( ) ) { GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( ); /***** altitudeMode *****/ int bIsGX = FALSE; int nAltitudeMode = -1; int iField = poOgrFeat->GetFieldIndex ( altitudeModefield ); if ( iField > -1 ) { if ( kml2altitudemode_rec ( poKmlGeometry, &nAltitudeMode, &bIsGX ) ) { if ( !bIsGX ) { switch ( nAltitudeMode ) { case kmldom::ALTITUDEMODE_CLAMPTOGROUND: poOgrFeat->SetField ( iField, "clampToGround" ); break; case kmldom::ALTITUDEMODE_RELATIVETOGROUND: poOgrFeat->SetField ( iField, "relativeToGround" ); break; case kmldom::ALTITUDEMODE_ABSOLUTE: poOgrFeat->SetField ( iField, "absolute" ); break; } } else { switch ( nAltitudeMode ) { case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR: poOgrFeat->SetField ( iField, "relativeToSeaFloor" ); break; case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR: poOgrFeat->SetField ( iField, "clampToSeaFloor" ); break; } } } } /***** tessellate *****/ int nTessellate = -1; kml2tessellate_rec ( poKmlGeometry, &nTessellate ); iField = poOgrFeat->GetFieldIndex ( tessellatefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nTessellate ); /***** extrude *****/ int nExtrude = -1; kml2extrude_rec ( poKmlGeometry, &nExtrude ); iField = poOgrFeat->GetFieldIndex ( extrudefield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nExtrude ); } /***** visibility *****/ int nVisibility = -1; if ( poKmlPlacemark->has_visibility ( ) ) nVisibility = poKmlPlacemark->get_visibility ( ); int iField = poOgrFeat->GetFieldIndex ( visibilityfield ); if ( iField > -1 ) poOgrFeat->SetField ( iField, nVisibility ); ExtendedDataPtr poKmlExtendedData = NULL; if ( poKmlPlacemark->has_extendeddata ( ) ) { poKmlExtendedData = poKmlPlacemark->get_extendeddata ( ); /***** loop over the schemadata_arrays *****/ size_t nSchemaData = poKmlExtendedData->get_schemadata_array_size ( ); size_t iSchemaData; for ( iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ ) { SchemaDataPtr poKmlSchemaData = poKmlExtendedData->get_schemadata_array_at ( iSchemaData ); /***** loop over the simpledata array *****/ size_t nSimpleData = poKmlSchemaData->get_simpledata_array_size ( ); size_t iSimpleData; for ( iSimpleData = 0; iSimpleData < nSimpleData; iSimpleData++ ) { SimpleDataPtr poKmlSimpleData = poKmlSchemaData->get_simpledata_array_at ( iSimpleData ); /***** find the field index *****/ int iField = -1; if ( poKmlSimpleData->has_name ( ) ) { const string oName = poKmlSimpleData->get_name ( ); const char *pszName = oName.c_str ( ); iField = poOgrFeat->GetFieldIndex ( pszName ); } /***** if it has trxt set the field *****/ if ( iField > -1 && poKmlSimpleData->has_text ( ) ) { string oText = poKmlSimpleData->get_text ( ); /* SerializePretty() adds a new line before the data */ /* ands trailing spaces. I believe this is wrong */ /* as it breaks round-tripping */ /* Trim trailing spaces */ while (oText.size() != 0 && oText[oText.size()-1] == ' ') oText.resize(oText.size()-1); /* Skip leading newline and spaces */ const char* pszText = oText.c_str ( ); if (pszText[0] == '\n') pszText ++; while (pszText[0] == ' ') pszText ++; poOgrFeat->SetField ( iField, pszText ); } } } if (nSchemaData == 0 && poKmlExtendedData->get_data_array_size() > 0 ) { int bLaunderFieldNames = CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES")); size_t nDataArraySize = poKmlExtendedData->get_data_array_size(); for(size_t i=0; i < nDataArraySize; i++) { const DataPtr& data = poKmlExtendedData->get_data_array_at(i); if (data->has_name() && data->has_value()) { CPLString osName = data->get_name(); if (bLaunderFieldNames) osName = OGRLIBKMLLayer::LaunderFieldNames(osName); int iField = poOgrFeat->GetFieldIndex ( osName ); if (iField >= 0) { poOgrFeat->SetField ( iField, data->get_value().c_str() ); } } } } } }