Skip to content
Permalink
Browse files

Merge pull request #1992 from rouault/gml_support_date_time_datetime

GML/WFS: add support for Date, Time and DateTime fields
  • Loading branch information...
rouault committed Nov 7, 2019
2 parents d82644e + 8f2d9a2 commit 1b3aa3aac9ea0901ecdcd15f605665c503967dad
@@ -304,7 +304,6 @@ def test_ogr_gml_10():
field_defn = ogr.FieldDefn('string', ogr.OFTString)
field_defn.SetWidth(100)
lyr.CreateField(field_defn)
lyr.CreateField(ogr.FieldDefn('date', ogr.OFTDate))
field_defn = ogr.FieldDefn('real', ogr.OFTReal)
field_defn.SetWidth(4)
field_defn.SetPrecision(2)
@@ -313,13 +312,18 @@ def test_ogr_gml_10():
field_defn = ogr.FieldDefn('integer', ogr.OFTInteger)
field_defn.SetWidth(5)
lyr.CreateField(field_defn)
lyr.CreateField(ogr.FieldDefn('date', ogr.OFTDate))
lyr.CreateField(ogr.FieldDefn('time', ogr.OFTTime))
lyr.CreateField(ogr.FieldDefn('datetime', ogr.OFTDateTime))

dst_feat = ogr.Feature(lyr.GetLayerDefn())
dst_feat.SetField('string', 'test string of length 24')
dst_feat.SetField('date', '2003/04/22')
dst_feat.SetField('real', 12.34)
dst_feat.SetField('float', 1234.5678)
dst_feat.SetField('integer', '1234')
dst_feat.SetField('date', '2019/11/06')
dst_feat.SetField('time', '12:34:56')
dst_feat.SetField('datetime', '2019/11/06 12:34:56+00')

ret = lyr.CreateFeature(dst_feat)

@@ -333,22 +337,24 @@ def test_ogr_gml_10():

assert feat.GetFieldDefnRef(feat.GetFieldIndex('string')).GetType() == ogr.OFTString, \
('String type is reported wrong. Got ' + str(feat.GetFieldDefnRef(feat.GetFieldIndex('string')).GetType()))
assert feat.GetFieldDefnRef(feat.GetFieldIndex('date')).GetType() == ogr.OFTString, \
('Date type is not reported as OFTString. Got ' + str(feat.GetFieldDefnRef(feat.GetFieldIndex('date')).GetType()))
assert feat.GetFieldDefnRef(feat.GetFieldIndex('real')).GetType() == ogr.OFTReal, \
('Real type is reported wrong. Got ' + str(feat.GetFieldDefnRef(feat.GetFieldIndex('real')).GetType()))
assert feat.GetFieldDefnRef(feat.GetFieldIndex('float')).GetType() == ogr.OFTReal, \
('Float type is not reported as OFTReal. Got ' + str(feat.GetFieldDefnRef(feat.GetFieldIndex('float')).GetType()))
assert feat.GetFieldDefnRef(feat.GetFieldIndex('integer')).GetType() == ogr.OFTInteger, \
('Integer type is reported wrong. Got ' + str(feat.GetFieldDefnRef(feat.GetFieldIndex('integer')).GetType()))
assert feat.GetFieldDefnRef(feat.GetFieldIndex('date')).GetType() == ogr.OFTDate
assert feat.GetFieldDefnRef(feat.GetFieldIndex('time')).GetType() == ogr.OFTTime
assert feat.GetFieldDefnRef(feat.GetFieldIndex('datetime')).GetType() == ogr.OFTDateTime

assert feat.GetField('string') == 'test string of length 24', \
('Unexpected string content.' + feat.GetField('string'))
assert feat.GetField('date') == '2003/04/22', \
('Unexpected string content.' + feat.GetField('date'))
assert feat.GetFieldAsDouble('real') == 12.34, 'Unexpected real content.'
assert feat.GetField('float') == 1234.5678, 'Unexpected float content.'
assert feat.GetField('integer') == 1234, 'Unexpected integer content.'
assert feat.GetField('date') == '2019/11/06'
assert feat.GetField('time') == '12:34:56'
assert feat.GetField('datetime') == '2019/11/06 12:34:56+00'

assert lyr.GetLayerDefn().GetFieldDefn(lyr.GetLayerDefn().GetFieldIndex('string')).GetWidth() == 100, \
'Unexpected width of string field.'
@@ -1673,7 +1673,7 @@ def test_ogr_wfs_vsimem_wfs110_one_layer_getfeature(with_and_without_streaming):

f = lyr.GetNextFeature()
if f.gml_id != 'my_layer.1' or f.boolean != 1 or f.str != 'str' or f.short != 1 or \
f.int != 123456789 or f.float != 1.2 or f.double != 1.23 or f.dt != '2015-04-17T12:34:56Z' or \
f.int != 123456789 or f.float != 1.2 or f.double != 1.23 or f.dt != '2015/04/17 12:34:56+00' or \
f.GetGeometryRef().ExportToWkt() != 'POINT (2 49)':
f.DumpReadable()
pytest.fail()
@@ -3083,7 +3083,7 @@ def test_ogr_wfs_vsimem_wfs110_schema_not_understood(with_and_without_streaming)

f = lyr.GetNextFeature()
if f.gml_id != 'my_layer.1' or f.boolean != 1 or f.str != 'str' or f.short != 1 or \
f.int != 123456789 or f.float != 1.2 or f.double != 1.23 or f.dt != '2015-04-17T12:34:56Z' or \
f.int != 123456789 or f.float != 1.2 or f.double != 1.23 or f.dt != '2015/04/17 12:34:56+00' or \
f.GetGeometryRef().ExportToWkt() != 'POINT (2 49)':
f.DumpReadable()
pytest.fail()
@@ -674,6 +674,18 @@ bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
poPDefn->SetType(GMLPT_Boolean);
poPDefn->SetWidth(1);
}
else if( EQUAL(pszSubType, "Date") )
{
poPDefn->SetType(GMLPT_Date);
}
else if( EQUAL(pszSubType, "Time") )
{
poPDefn->SetType(GMLPT_Time);
}
else if( EQUAL(pszSubType, "Datetime") )
{
poPDefn->SetType(GMLPT_DateTime);
}
else
{
poPDefn->SetType(GMLPT_String);
@@ -903,44 +915,85 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
CPLCreateXMLElementAndValue(psPDefnNode, "Name", poPDefn->GetName());
CPLCreateXMLElementAndValue(psPDefnNode, "ElementPath",
poPDefn->GetSrcElement());
switch( poPDefn->GetType() )
const auto gmlType = poPDefn->GetType();
const char* pszSubTypeName = nullptr;
switch( gmlType )
{
case GMLPT_Untyped:
pszTypeName = "Untyped";
break;

case GMLPT_String:
pszTypeName = "String";
break;

case GMLPT_Boolean:
pszTypeName = "String";
pszSubTypeName = "Boolean";
break;

case GMLPT_Date:
pszTypeName = "String";
pszSubTypeName = "Date";
break;

case GMLPT_Time:
pszTypeName = "String";
pszSubTypeName = "Time";
break;

case GMLPT_DateTime:
pszTypeName = "String";
pszSubTypeName = "DateTime";
break;

case GMLPT_Integer:
pszTypeName = "Integer";
break;

case GMLPT_Short:
pszTypeName = "Integer";
pszSubTypeName = "Short";
break;

case GMLPT_Integer64:
pszTypeName = "Integer";
pszSubTypeName = "Integer64";
break;

case GMLPT_Real:
pszTypeName = "Real";
break;

case GMLPT_Float:
pszTypeName = "Real";
pszSubTypeName = "Float";
break;

case GMLPT_Complex:
pszTypeName = "Complex";
break;

case GMLPT_IntegerList:
pszTypeName = "IntegerList";
break;

case GMLPT_Integer64List:
pszTypeName = "IntegerList";
pszSubTypeName = "Integer64";
break;

case GMLPT_RealList:
pszTypeName = "RealList";
break;

case GMLPT_StringList:
pszTypeName = "StringList";
break;

case GMLPT_BooleanList:
pszTypeName = "StringList";
pszSubTypeName = "Boolean";
break;

// Should not happen in practice for now because this is not
@@ -956,15 +1009,8 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
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( pszSubTypeName )
CPLCreateXMLElementAndValue(psPDefnNode, "Subtype", pszSubTypeName);

if( EQUAL(pszTypeName, "String") )
{
@@ -993,3 +1039,60 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()

return psRoot;
}

/************************************************************************/
/* GML_GetOGRFieldType() */
/************************************************************************/

OGRFieldType GML_GetOGRFieldType(GMLPropertyType eType, OGRFieldSubType& eSubType)
{
OGRFieldType eFType = OFTString;
eSubType = OFSTNone;
if( eType == GMLPT_Untyped )
eFType = OFTString;
else if( eType == GMLPT_String )
eFType = OFTString;
else if( eType == GMLPT_Integer )
eFType = OFTInteger;
else if( eType == GMLPT_Boolean )
{
eFType = OFTInteger;
eSubType = OFSTBoolean;
}
else if( eType == GMLPT_Short )
{
eFType = OFTInteger;
eSubType = OFSTInt16;
}
else if( eType == GMLPT_Integer64 )
eFType = OFTInteger64;
else if( eType == GMLPT_Real )
eFType = OFTReal;
else if( eType == GMLPT_Float )
{
eFType = OFTReal;
eSubType = OFSTFloat32;
}
else if( eType == GMLPT_StringList )
eFType = OFTStringList;
else if( eType == GMLPT_IntegerList )
eFType = OFTIntegerList;
else if( eType == GMLPT_BooleanList )
{
eFType = OFTIntegerList;
eSubType = OFSTBoolean;
}
else if( eType == GMLPT_Integer64List )
eFType = OFTInteger64List;
else if( eType == GMLPT_RealList )
eFType = OFTRealList;
else if( eType == GMLPT_Date)
eFType = OFTDate;
else if( eType == GMLPT_Time )
eFType = OFTTime;
else if( eType == GMLPT_DateTime )
eFType = OFTDateTime;
else if( eType == GMLPT_FeaturePropertyList )
eFType = OFTStringList;
return eFType;
}
@@ -34,6 +34,7 @@
#include "cpl_port.h"
#include "cpl_vsi.h"
#include "cpl_minixml.h"
#include "ogr_core.h"
#include "gmlutils.h"

#include <map>
@@ -58,7 +59,10 @@ typedef enum {
GMLPT_Short = 12,
GMLPT_Float = 13,
GMLPT_Integer64 = 14,
GMLPT_Integer64List = 15
GMLPT_Integer64List = 15,
GMLPT_DateTime = 16,
GMLPT_Date = 17,
GMLPT_Time = 18,
} GMLPropertyType;

/************************************************************************/
@@ -333,4 +337,6 @@ IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
GMLSwapCoordinatesEnum eSwapCoordinates,
bool bGetSecondaryGeometryOption);

OGRFieldType GML_GetOGRFieldType(GMLPropertyType eType, OGRFieldSubType& eSubType);

#endif /* GMLREADER_H_INCLUDED */

0 comments on commit 1b3aa3a

Please sign in to comment.
You can’t perform that action at this time.