Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: KML Driver
4 : * Purpose: Implementation of OGRKMLDriver class.
5 : * Author: Christopher Condit, condit@sdsc.edu;
6 : * Jens Oberender, j.obi@troja.net
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2006, Christopher Condit
10 : * 2007, Jens Oberender
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_port.h"
32 : #include "ogr_kml.h"
33 :
34 : #include <cstring>
35 :
36 : #include "cpl_conv.h"
37 : #include "cpl_error.h"
38 : #include "gdal.h"
39 : #include "gdal_priv.h"
40 :
41 : /************************************************************************/
42 : /* OGRKMLDriverIdentify() */
43 : /************************************************************************/
44 :
45 43426 : static int OGRKMLDriverIdentify(GDALOpenInfo *poOpenInfo)
46 :
47 : {
48 43426 : if (poOpenInfo->fpL == nullptr)
49 40461 : return FALSE;
50 :
51 2965 : return strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), "<kml") !=
52 5880 : nullptr ||
53 2915 : strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
54 2965 : "<kml:kml") != nullptr;
55 : }
56 :
57 : /************************************************************************/
58 : /* Open() */
59 : /************************************************************************/
60 :
61 25 : static GDALDataset *OGRKMLDriverOpen(GDALOpenInfo *poOpenInfo)
62 :
63 : {
64 25 : if (poOpenInfo->eAccess == GA_Update)
65 0 : return nullptr;
66 :
67 25 : if (!OGRKMLDriverIdentify(poOpenInfo))
68 0 : return nullptr;
69 :
70 : #ifdef HAVE_EXPAT
71 25 : OGRKMLDataSource *poDS = new OGRKMLDataSource();
72 :
73 25 : if (poDS->Open(poOpenInfo->pszFilename, TRUE))
74 : {
75 : #ifdef DEBUG_VERBOSE
76 : if (poDS->GetLayerCount() == 0)
77 : {
78 : CPLError(CE_Failure, CPLE_OpenFailed, "No layers in KML file: %s.",
79 : poOpenInfo->pszFilename);
80 :
81 : delete poDS;
82 : poDS = nullptr;
83 : }
84 : #endif
85 : }
86 : else
87 : {
88 2 : delete poDS;
89 2 : poDS = nullptr;
90 : }
91 :
92 25 : return poDS;
93 : #else
94 : return nullptr;
95 : #endif
96 : }
97 :
98 : /************************************************************************/
99 : /* Create() */
100 : /************************************************************************/
101 :
102 42 : static GDALDataset *OGRKMLDriverCreate(const char *pszName, int /* nBands */,
103 : int /* nXSize */, int /* nYSize */,
104 : GDALDataType /* eDT */,
105 : char **papszOptions)
106 : {
107 42 : CPLAssert(nullptr != pszName);
108 42 : CPLDebug("KML", "Attempt to create: %s", pszName);
109 :
110 42 : OGRKMLDataSource *poDS = new OGRKMLDataSource();
111 :
112 42 : if (!poDS->Create(pszName, papszOptions))
113 : {
114 1 : delete poDS;
115 1 : poDS = nullptr;
116 : }
117 :
118 42 : return poDS;
119 : }
120 :
121 : /************************************************************************/
122 : /* RegisterOGRKML() */
123 : /************************************************************************/
124 :
125 1509 : void RegisterOGRKML()
126 : {
127 1509 : if (GDALGetDriverByName("KML") != nullptr)
128 295 : return;
129 :
130 1214 : GDALDriver *poDriver = new GDALDriver();
131 :
132 1214 : poDriver->SetDescription("KML");
133 1214 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
134 1214 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
135 1214 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
136 1214 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
137 1214 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
138 1214 : "Keyhole Markup Language (KML)");
139 1214 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "kml");
140 1214 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/kml.html");
141 1214 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE");
142 :
143 1214 : poDriver->SetMetadataItem(
144 : GDAL_DMD_CREATIONOPTIONLIST,
145 : "<CreationOptionList>"
146 : " <Option name='DOCUMENT_ID' type='string' description='Id of the "
147 : "root <Document> node' default='root_doc'/>"
148 : " <Option name='GPX_USE_EXTENSIONS' type='boolean' "
149 : "description='Whether to write non-GPX attributes in an "
150 : "<extensions> tag' default='NO'/>"
151 : " <Option name='NameField' type='string' description='Field to use to "
152 : "fill the KML <name> element' default='Name'/>"
153 : " <Option name='DescriptionField' type='string' description='Field to "
154 : "use to fill the KML <description> element' "
155 : "default='Description'/>"
156 : " <Option name='AltitudeMode' type='string-select' description='Value "
157 : "of the <AltitudeMode> element for 3D geometries'>"
158 : " <Value>clampToGround</Value>"
159 : " <Value>relativeToGround</Value>"
160 : " <Value>absolute</Value>"
161 : " </Option>"
162 1214 : "</CreationOptionList>");
163 :
164 1214 : poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
165 1214 : "<LayerCreationOptionList/>");
166 1214 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
167 1214 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
168 1214 : "Integer Real String");
169 1214 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES");
170 1214 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES");
171 1214 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
172 :
173 1214 : poDriver->pfnOpen = OGRKMLDriverOpen;
174 1214 : poDriver->pfnIdentify = OGRKMLDriverIdentify;
175 1214 : poDriver->pfnCreate = OGRKMLDriverCreate;
176 :
177 1214 : GetGDALDriverManager()->RegisterDriver(poDriver);
178 : }
|