LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gml - ogrgmldriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 75 77 97.4 %
Date: 2024-11-21 22:18:42 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OGR
       4             :  * Purpose:  OGRGMLDriver implementation
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogr_gml.h"
      14             : #include "cpl_conv.h"
      15             : #include "cpl_multiproc.h"
      16             : #include "gmlreaderp.h"
      17             : 
      18             : /************************************************************************/
      19             : /*                         OGRGMLDriverIdentify()                       */
      20             : /************************************************************************/
      21             : 
      22       48776 : static int OGRGMLDriverIdentify(GDALOpenInfo *poOpenInfo)
      23             : 
      24             : {
      25       48776 :     if (poOpenInfo->fpL == nullptr)
      26             :     {
      27       43738 :         if (strstr(poOpenInfo->pszFilename, "xsd=") != nullptr)
      28           4 :             return -1; /* must be later checked */
      29       43734 :         return FALSE;
      30             :     }
      31             :     /* Might be a OS-Mastermap gzipped GML, so let be nice and try to open */
      32             :     /* it transparently with /vsigzip/ */
      33       10098 :     else if (poOpenInfo->pabyHeader[0] == 0x1f &&
      34          22 :              poOpenInfo->pabyHeader[1] == 0x8b &&
      35        5064 :              EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "gz") &&
      36           4 :              !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/"))
      37             :     {
      38           4 :         return -1; /* must be later checked */
      39             :     }
      40             :     else
      41             :     {
      42        5034 :         const char *szPtr =
      43             :             reinterpret_cast<const char *>(poOpenInfo->pabyHeader);
      44             : 
      45        5034 :         if ((static_cast<unsigned char>(szPtr[0]) == 0xEF) &&
      46           9 :             (static_cast<unsigned char>(szPtr[1]) == 0xBB) &&
      47           9 :             (static_cast<unsigned char>(szPtr[2]) == 0xBF))
      48             :         {
      49           9 :             szPtr += 3;
      50             :         }
      51             :         /* --------------------------------------------------------------------
      52             :          */
      53             :         /*      Here, we expect the opening chevrons of GML tree root element */
      54             :         /* --------------------------------------------------------------------
      55             :          */
      56        5034 :         if (szPtr[0] != '<')
      57        3871 :             return FALSE;
      58             : 
      59        1163 :         if (!poOpenInfo->TryToIngest(4096))
      60           0 :             return FALSE;
      61             : 
      62        1163 :         if (poOpenInfo->IsSingleAllowedDriver("GML"))
      63          68 :             return TRUE;
      64             : 
      65        2190 :         return OGRGMLDataSource::CheckHeader(
      66        1095 :             reinterpret_cast<const char *>(poOpenInfo->pabyHeader));
      67             :     }
      68             : }
      69             : 
      70             : /************************************************************************/
      71             : /*                                Open()                                */
      72             : /************************************************************************/
      73             : 
      74         414 : static GDALDataset *OGRGMLDriverOpen(GDALOpenInfo *poOpenInfo)
      75             : 
      76             : {
      77         414 :     if (poOpenInfo->eAccess == GA_Update)
      78           0 :         return nullptr;
      79             : 
      80         414 :     if (OGRGMLDriverIdentify(poOpenInfo) == FALSE)
      81          15 :         return nullptr;
      82             : 
      83         399 :     OGRGMLDataSource *poDS = new OGRGMLDataSource();
      84             : 
      85         399 :     if (!poDS->Open(poOpenInfo))
      86             :     {
      87           3 :         delete poDS;
      88           3 :         return nullptr;
      89             :     }
      90             :     else
      91         396 :         return poDS;
      92             : }
      93             : 
      94             : /************************************************************************/
      95             : /*                             Create()                                 */
      96             : /************************************************************************/
      97             : 
      98             : static GDALDataset *
      99          99 : OGRGMLDriverCreate(const char *pszName, CPL_UNUSED int nBands,
     100             :                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
     101             :                    CPL_UNUSED GDALDataType eDT, char **papszOptions)
     102             : {
     103          99 :     OGRGMLDataSource *poDS = new OGRGMLDataSource();
     104             : 
     105          99 :     if (!poDS->Create(pszName, papszOptions))
     106             :     {
     107           1 :         delete poDS;
     108           1 :         return nullptr;
     109             :     }
     110             :     else
     111          98 :         return poDS;
     112             : }
     113             : 
     114             : /************************************************************************/
     115             : /*                           RegisterOGRGML()                           */
     116             : /************************************************************************/
     117             : 
     118        1595 : void RegisterOGRGML()
     119             : 
     120             : {
     121        1595 :     if (GDALGetDriverByName("GML") != nullptr)
     122         302 :         return;
     123             : 
     124        1293 :     GDALDriver *poDriver = new GDALDriver();
     125             : 
     126        1293 :     poDriver->SetDescription("GML");
     127        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
     128        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
     129        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
     130        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_CURVE_GEOMETRIES, "YES");
     131        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
     132        1293 :     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
     133        1293 :                               "Geography Markup Language (GML)");
     134        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gml");
     135        1293 :     poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "gml xml");
     136        1293 :     poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/gml.html");
     137        1293 :     poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
     138             : 
     139        1293 :     poDriver->SetMetadataItem(
     140             :         GDAL_DMD_OPENOPTIONLIST,
     141             :         "<OpenOptionList>"
     142             :         "  <Option name='XSD' type='string' description='Name of the related "
     143             :         "application schema file (.xsd).'/>"
     144             :         "  <Option name='GFS_TEMPLATE' type='string' description='Filename of "
     145             :         "a .gfs template file to apply.'/>"
     146             :         "  <Option name='WRITE_GFS' type='string-select' description='Whether "
     147             :         "to write a .gfs file' default='AUTO'>"
     148             :         "    <Value>AUTO</Value>"
     149             :         "    <Value>YES</Value>"
     150             :         "    <Value>NO</Value>"
     151             :         "  </Option>"
     152             :         "  <Option name='FORCE_SRS_DETECTION' type='boolean' "
     153             :         "description='Force a full scan to detect the SRS of layers.' "
     154             :         "default='NO'/>"
     155             :         "  <Option name='EMPTY_AS_NULL' type='boolean' description='Force "
     156             :         "empty fields to be reported as NULL. Set to NO so that not-nullable "
     157             :         "fields can be exposed' default='YES'/>"
     158             :         "  <Option name='GML_ATTRIBUTES_TO_OGR_FIELDS' type='boolean' "
     159             :         "description='Whether GML attributes should be reported as OGR fields' "
     160             :         "default='NO'/>"
     161             :         "  <Option name='INVERT_AXIS_ORDER_IF_LAT_LONG' type='boolean' "
     162             :         "description='Whether to present SRS and coordinate ordering in "
     163             :         "traditional GIS order' default='YES'/>"
     164             :         "  <Option name='CONSIDER_EPSG_AS_URN' type='string-select' "
     165             :         "description='Whether to consider srsName like EPSG:XXXX as respecting "
     166             :         "EPSG axis order' default='AUTO'>"
     167             :         "    <Value>AUTO</Value>"
     168             :         "    <Value>YES</Value>"
     169             :         "    <Value>NO</Value>"
     170             :         "  </Option>"
     171             :         "  <Option name='SWAP_COORDINATES' type='string-select' "
     172             :         "description='Whether the order of geometry coordinates should be "
     173             :         "inverted.' "
     174             :         "default='AUTO'>"
     175             :         "    <Value>AUTO</Value>"
     176             :         "    <Value>YES</Value>"
     177             :         "    <Value>NO</Value>"
     178             :         "  </Option>"
     179             :         "  <Option name='READ_MODE' type='string-select' description='Read "
     180             :         "mode' default='AUTO'>"
     181             :         "    <Value>AUTO</Value>"
     182             :         "    <Value>STANDARD</Value>"
     183             :         "    <Value>SEQUENTIAL_LAYERS</Value>"
     184             :         "    <Value>INTERLEAVED_LAYERS</Value>"
     185             :         "  </Option>"
     186             :         "  <Option name='EXPOSE_GML_ID' type='string-select' "
     187             :         "description='Whether to make feature gml:id as a gml_id attribute' "
     188             :         "default='AUTO'>"
     189             :         "    <Value>AUTO</Value>"
     190             :         "    <Value>YES</Value>"
     191             :         "    <Value>NO</Value>"
     192             :         "  </Option>"
     193             :         "  <Option name='EXPOSE_FID' type='string-select' description='Whether "
     194             :         "to make feature fid as a fid attribute' default='AUTO'>"
     195             :         "    <Value>AUTO</Value>"
     196             :         "    <Value>YES</Value>"
     197             :         "    <Value>NO</Value>"
     198             :         "  </Option>"
     199             :         "  <Option name='DOWNLOAD_SCHEMA' type='boolean' description='Whether "
     200             :         "to download the remote application schema if needed (only for WFS "
     201             :         "currently)' default='YES'/>"
     202             :         "  <Option name='REGISTRY' type='string' description='Filename of the "
     203             :         "registry with application schemas.'/>"
     204             :         "  <Option name='USE_BBOX' type='boolean' description='Whether "
     205             :         "to use gml:boundedBy at feature level as feature geometry, "
     206             :         "if there are no other geometry' default='NO'/>"
     207             :         "  <Option name='USE_SCHEMA_IMPORT' type='boolean' "
     208             :         "description='Whether "
     209             :         "to read schema for imports along with includes or not' default='NO'/>"
     210        1293 :         "</OpenOptionList>");
     211             : 
     212        1293 :     poDriver->SetMetadataItem(
     213             :         GDAL_DMD_CREATIONOPTIONLIST,
     214             :         "<CreationOptionList>"
     215             :         "  <Option name='XSISCHEMAURI' type='string' description='URI to be "
     216             :         "inserted as the schema location.'/>"
     217             :         "  <Option name='XSISCHEMA' type='string-select' description='where to "
     218             :         "write a .xsd application schema. INTERNAL should not normally be "
     219             :         "used' default='EXTERNAL'>"
     220             :         "    <Value>EXTERNAL</Value>"
     221             :         "    <Value>INTERNAL</Value>"
     222             :         "    <Value>OFF</Value>"
     223             :         "  </Option>"
     224             :         "  <Option name='PREFIX' type='string' description='Prefix for the "
     225             :         "application target namespace.' default='ogr'/>"
     226             :         "  <Option name='STRIP_PREFIX' type='boolean' description='Whether to "
     227             :         "avoid writing the prefix of the application target namespace in the "
     228             :         "GML file.' default='NO'/>"
     229             :         "  <Option name='TARGET_NAMESPACE' type='string' "
     230             :         "description='Application target namespace.' "
     231             :         "default='http://ogr.maptools.org/'/>"
     232             :         "  <Option name='FORMAT' type='string-select' description='Version of "
     233             :         "GML to use' default='GML3.2'>"
     234             :         "    <Value>GML2</Value>"
     235             :         "    <Value>GML3</Value>"
     236             :         "    <Value>GML3.2</Value>"
     237             :         "    <Value>GML3Deegree</Value>"
     238             :         "  </Option>"
     239             :         "  <Option name='GML_FEATURE_COLLECTION' type='boolean' "
     240             :         "description='Whether to use the gml:FeatureCollection. Only valid for "
     241             :         "FORMAT=GML3/GML3.2' default='NO'/>"
     242             :         "  <Option name='GML3_LONGSRS' type='boolean' description='Whether to "
     243             :         "write SRS with \"urn:ogc:def:crs:EPSG::\" prefix with GML3* versions' "
     244             :         "default='YES'/>"
     245             :         "  <Option name='SRSNAME_FORMAT' type='string-select' "
     246             :         "description='Format of srsName (for GML3* versions)' "
     247             :         "default='OGC_URL'>"
     248             :         "    <Value>SHORT</Value>"
     249             :         "    <Value>OGC_URN</Value>"
     250             :         "    <Value>OGC_URL</Value>"
     251             :         "  </Option>"
     252             :         "  <Option name='WRITE_FEATURE_BOUNDED_BY' type='boolean' "
     253             :         "description='Whether to write &lt;gml:boundedBy&gt; element for each "
     254             :         "feature with GML3* versions' default='YES'/>"
     255             :         "  <Option name='SPACE_INDENTATION' type='boolean' "
     256             :         "description='Whether to indent the output for readability' "
     257             :         "default='YES'/>"
     258             :         "  <Option name='SRSDIMENSION_LOC' type='string-select' "
     259             :         "description='(only valid for FORMAT=GML3xx) Location where to put "
     260             :         "srsDimension attribute' default='POSLIST'>"
     261             :         "    <Value>POSLIST</Value>"
     262             :         "    <Value>GEOMETRY</Value>"
     263             :         "    <Value>GEOMETRY,POSLIST</Value>"
     264             :         "  </Option>"
     265             :         "  <Option name='GML_ID' type='string' description='Value of feature "
     266             :         "collection gml:id (GML 3.2 only)' default='aFeatureCollection'/>"
     267             :         "  <Option name='NAME' type='string' description='Content of GML name "
     268             :         "element'/>"
     269             :         "  <Option name='DESCRIPTION' type='string' description='Content of "
     270             :         "GML description element'/>"
     271        1293 :         "</CreationOptionList>");
     272             : 
     273        1293 :     poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
     274        1293 :                               "<LayerCreationOptionList/>");
     275        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
     276             :                               "Integer Integer64 Real String Date DateTime "
     277        1293 :                               "IntegerList Integer64List RealList StringList");
     278        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES,
     279        1293 :                               "Boolean Int16 Float32");
     280        1293 :     poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
     281        1293 :                               "WidthPrecision Nullable Unique Comment");
     282             : 
     283        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_NOTNULL_FIELDS, "YES");
     284        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_UNIQUE_FIELDS, "YES");
     285        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES");
     286        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     287        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
     288        1293 :     poDriver->SetMetadataItem(GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION, "YES");
     289             : 
     290        1293 :     poDriver->pfnOpen = OGRGMLDriverOpen;
     291        1293 :     poDriver->pfnIdentify = OGRGMLDriverIdentify;
     292        1293 :     poDriver->pfnCreate = OGRGMLDriverCreate;
     293             : 
     294        1293 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     295             : }

Generated by: LCOV version 1.14