@@ -1277,21 +1277,33 @@ def test_ogr_gml_35(tmp_path):
12771277
12781278
12791279@pytest .mark .parametrize ("GML_FACE_HOLE_NEGATIVE" , ("NO" , "YES" ))
1280- def test_ogr_gml_36 (tmp_path , GML_FACE_HOLE_NEGATIVE ):
1280+ @pytest .mark .parametrize ("skip_resolve_as_open_option" , (True , False ))
1281+ def test_ogr_gml_36 (tmp_path , GML_FACE_HOLE_NEGATIVE , skip_resolve_as_open_option ):
12811282
12821283 if GML_FACE_HOLE_NEGATIVE == "NO" :
12831284 if not ogrtest .have_geos ():
12841285 pytest .skip ("GEOS not available" )
12851286
12861287 shutil .copy ("data/gml/GmlTopo-sample.xml" , tmp_path )
12871288
1288- with gdal .config_options (
1289- {
1290- "GML_SKIP_RESOLVE_ELEMS" : "NONE" ,
1291- "GML_FACE_HOLE_NEGATIVE" : GML_FACE_HOLE_NEGATIVE ,
1292- }
1293- ):
1294- ds = ogr .Open (tmp_path / "GmlTopo-sample.xml" )
1289+ if skip_resolve_as_open_option :
1290+ with gdal .config_options (
1291+ {
1292+ "GML_FACE_HOLE_NEGATIVE" : GML_FACE_HOLE_NEGATIVE ,
1293+ }
1294+ ):
1295+ ds = gdal .OpenEx (
1296+ tmp_path / "GmlTopo-sample.xml" ,
1297+ open_options = ["SKIP_RESOLVE_ELEMS=NONE" ],
1298+ )
1299+ else :
1300+ with gdal .config_options (
1301+ {
1302+ "GML_SKIP_RESOLVE_ELEMS" : "NONE" ,
1303+ "GML_FACE_HOLE_NEGATIVE" : GML_FACE_HOLE_NEGATIVE ,
1304+ }
1305+ ):
1306+ ds = ogr .Open (tmp_path / "GmlTopo-sample.xml" )
12951307 assert gdal .GetLastErrorMsg () == "" , "did not expect error"
12961308
12971309 lyr = ds .GetLayerByName ("Suolo" )
@@ -1318,8 +1330,9 @@ def test_ogr_gml_36(tmp_path, GML_FACE_HOLE_NEGATIVE):
13181330
13191331
13201332@pytest .mark .parametrize ("resolver" , ("HUGE" , "NONE" ))
1333+ @pytest .mark .parametrize ("skip_resolve_as_open_option" , (True , False ))
13211334@pytest .mark .require_geos
1322- def test_ogr_gml_38 (tmp_path , resolver ):
1335+ def test_ogr_gml_38 (tmp_path , resolver , skip_resolve_as_open_option ):
13231336
13241337 if resolver == "HUGE" and ogr .GetDriverByName ("SQLite" ) is None :
13251338 pytest .skip ("Requires SQLite support" )
@@ -1329,8 +1342,15 @@ def test_ogr_gml_38(tmp_path, resolver):
13291342 tmp_path ,
13301343 )
13311344
1332- with gdal .config_option ("GML_SKIP_RESOLVE_ELEMS" , resolver ):
1333- ds = ogr .Open (tmp_path / "sample_gml_face_hole_negative_no.xml" )
1345+ if skip_resolve_as_open_option :
1346+ ds = gdal .OpenEx (
1347+ tmp_path / "sample_gml_face_hole_negative_no.xml" ,
1348+ open_options = [f"SKIP_RESOLVE_ELEMS={ resolver } " ],
1349+ )
1350+ else :
1351+ with gdal .config_option ("GML_SKIP_RESOLVE_ELEMS" , resolver ):
1352+ ds = ogr .Open (tmp_path / "sample_gml_face_hole_negative_no.xml" )
1353+
13341354 gdal .SetConfigOption ("GML_FACE_HOLE_NEGATIVE" , None )
13351355
13361356 if resolver == "HUGE" :
@@ -1353,7 +1373,10 @@ def test_ogr_gml_38(tmp_path, resolver):
13531373
13541374@pytest .mark .require_driver ("SQLite" )
13551375@pytest .mark .require_geos
1356- def test_ogr_gml_huge_resolver_same_nested_property_name (tmp_path ):
1376+ @pytest .mark .parametrize ("skip_resolve_as_open_option" , (True , False ))
1377+ def test_ogr_gml_huge_resolver_same_nested_property_name (
1378+ tmp_path , skip_resolve_as_open_option
1379+ ):
13571380
13581381 shutil .copy (
13591382 "data/gml/same_nested_property_name.gml" ,
@@ -1370,9 +1393,16 @@ def check_ds(ds):
13701393 ds = ogr .Open (tmp_path / "same_nested_property_name.gml" )
13711394 check_ds (ds )
13721395
1373- with gdal .config_option ("GML_SKIP_RESOLVE_ELEMS" , "HUGE" ):
1374- ds = ogr .Open (tmp_path / "same_nested_property_name.gml" )
1375- check_ds (ds )
1396+ if skip_resolve_as_open_option :
1397+ ds = gdal .OpenEx (
1398+ tmp_path / "same_nested_property_name.gml" ,
1399+ open_options = ["SKIP_RESOLVE_ELEMS=HUGE" ],
1400+ )
1401+ else :
1402+ with gdal .config_option ("GML_SKIP_RESOLVE_ELEMS" , "HUGE" ):
1403+ ds = ogr .Open (tmp_path / "same_nested_property_name.gml" )
1404+
1405+ check_ds (ds )
13761406
13771407
13781408###############################################################################
@@ -5027,6 +5057,7 @@ def test_ogr_gml_write_error(tmp_vsimem):
50275057 ds .Close ()
50285058
50295059
5060+ ###############################################################################
50305061# Test open option SKIP_CORRUPTED_FEATURES
50315062
50325063
@@ -5052,27 +5083,27 @@ def test_ogr_gml_skip_corrupted_features(tmp_vsimem):
50525083 <gml:featureMember>
50535084 <ogr:solids fid="solids.1">
50545085 <boundary>
5055- <ClosureSurface>
5056- <lod2MultiSurface>
5057- <gml:MultiSurface>
5058- <gml:surfaceMember>
5059- <gml:Polygon gml:id="UUID_da310e81-cd4a-4167-94a0-3ea04f39ebd0">
5060- <gml:exterior>
5061- <gml:LinearRing>
5062- <gml:posList srsDimension="3">646102.957 5667459.848 146.668 646102.957 5667459.848 142.56 646107.611 5667459.649 142.56 646107.611 5667459.649 146.696 646102.957 5667459.848 146.668</gml:posList>
5063- </gml:LinearRing>
5064- </gml:exterior>
5065- </gml:Polygon>
5066- </gml:surfaceMember>
5067- </gml:MultiSurface>
5068- </lod2MultiSurface>
5069- </ClosureSurface>
5070- </boundary>
5086+ <ClosureSurface>
5087+ <lod2MultiSurface>
5088+ <gml:MultiSurface>
5089+ <gml:surfaceMember>
5090+ <gml:Polygon gml:id="UUID_da310e81-cd4a-4167-94a0-3ea04f39ebd0">
5091+ <gml:exterior>
5092+ <gml:LinearRing>
5093+ <gml:posList srsDimension="3">646102.957 5667459.848 146.668 646102.957 5667459.848 142.56 646107.611 5667459.649 142.56 646107.611 5667459.649 146.696 646102.957 5667459.848 146.668</gml:posList>
5094+ </gml:LinearRing>
5095+ </gml:exterior>
5096+ </gml:Polygon>
5097+ </gml:surfaceMember>
5098+ </gml:MultiSurface>
5099+ </lod2MultiSurface>
5100+ </ClosureSurface>
5101+ </boundary>
50715102 <gml:Solid>
50725103 <gml:exterior>
5073- <gml:Shell >
5104+ <gml:XXXX >
50745105 <gml:surfaceMember xlink:href="#UUID_da310e81-cd4a-4167-94a0-3ea04f39ebd0"/>
5075- </gml:Shell >
5106+ </gml:XXXX >
50765107 </gml:exterior>
50775108 </gml:Solid>
50785109 </ogr:solids>
@@ -5109,3 +5140,77 @@ def test_ogr_gml_skip_corrupted_features(tmp_vsimem):
51095140 ds = gdal .OpenEx (filename , open_options = ["SKIP_CORRUPTED_FEATURES=NO" ])
51105141 layer = ds .GetLayer (0 )
51115142 layer .GetNextFeature ()
5143+
5144+
5145+ ###############################################################################
5146+ # Test CityGML3 for issue GH #12769
5147+
5148+
5149+ @pytest .mark .parametrize ("skip_resolve_as_open_option" , (True , False ))
5150+ def test_ogr_gml_citygml3 (tmp_vsimem , skip_resolve_as_open_option ):
5151+ """Test for issue GH #12769"""
5152+
5153+ filename = str (tmp_vsimem / "test.gml" )
5154+ gdal .FileFromMemBuffer (
5155+ filename ,
5156+ """<?xml version="1.0" encoding="utf-8" ?>
5157+ <CityModel>
5158+ <ogr:FeatureCollection
5159+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5160+ xsi:schemaLocation=""
5161+ xmlns:ogr="http://ogr.maptools.org/"
5162+ xmlns:gml="http://www.opengis.net/gml">
5163+ <gml:boundedBy>
5164+ <gml:Box>
5165+ <gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
5166+ <gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
5167+ </gml:Box>
5168+ </gml:boundedBy>
5169+ <gml:featureMember>
5170+ <ogr:solids fid="solids.1">
5171+ <lod2Solid>
5172+ <gml:Solid>
5173+ <gml:exterior>
5174+ <gml:Shell>
5175+ <gml:surfaceMember xlink:href="#UUID_da310e81-cd4a-4167-94a0-3ea04f39ebd0"/>
5176+ </gml:Shell>
5177+ </gml:exterior>
5178+ </gml:Solid>
5179+ </lod2Solid>
5180+ <boundary>
5181+ <ClosureSurface>
5182+ <lod2MultiSurface>
5183+ <gml:MultiSurface>
5184+ <gml:surfaceMember>
5185+ <gml:Polygon gml:id="UUID_da310e81-cd4a-4167-94a0-3ea04f39ebd0">
5186+ <gml:exterior>
5187+ <gml:LinearRing>
5188+ <gml:posList srsDimension="3">0 0 0 1 1 1 1 0 2 0 0 0</gml:posList>
5189+ </gml:LinearRing>
5190+ </gml:exterior>
5191+ </gml:Polygon>
5192+ </gml:surfaceMember>
5193+ </gml:MultiSurface>
5194+ </lod2MultiSurface>
5195+ </ClosureSurface>
5196+ </boundary>
5197+ </ogr:solids>
5198+ </gml:featureMember>
5199+ </ogr:FeatureCollection>
5200+ </CityModel>""" ,
5201+ )
5202+
5203+ if skip_resolve_as_open_option :
5204+ ds = gdal .OpenEx (filename , open_options = ["SKIP_RESOLVE_ELEMS=NONE" ])
5205+ else :
5206+ with gdal .config_option ("GML_SKIP_RESOLVE_ELEMS" , "NONE" ):
5207+ ds = ogr .Open (filename )
5208+
5209+ layer = ds .GetLayer (0 )
5210+ assert layer .GetGeometryColumn () == "lod2Solid"
5211+ f = layer .GetNextFeature ()
5212+ assert f is not None
5213+ assert (
5214+ f .GetGeometryRef ().ExportToWkt ()
5215+ == "POLYHEDRALSURFACE Z (((0 0 0,1 1 1,1 0 2,0 0 0)))"
5216+ )
0 commit comments